browser_relationProps.js (6439B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 function testUiaRelationArray(id, prop, targets) { 8 return isUiaElementArray( 9 `findUiaByDomId(doc, "${id}").Current${prop}`, 10 targets, 11 `${id} has correct ${prop} targets` 12 ); 13 } 14 15 function testCustomUiaRelationArray(id, prop, targets) { 16 return isUiaElementArray( 17 ` 18 findUiaByDomId(doc, "${id}") 19 .GetCurrentPropertyValue(uia${prop}PropertyId) 20 .QueryInterface(IUIAutomationElementArray) 21 `, 22 targets, 23 `${id} has correct ${prop} targets` 24 ); 25 } 26 27 /** 28 * Test the ControllerFor property. 29 */ 30 addUiaTask( 31 ` 32 <input id="controls" aria-controls="t1 t2"> 33 <input id="error" aria-errormessage="t3 t4" aria-invalid="true"> 34 <input id="controlsError" aria-controls="t1 t2" aria-errormessage="t3 t4" aria-invalid="true"> 35 <div id="t1">t1</div> 36 <div id="t2">t2</div> 37 <div id="t3">t3</div> 38 <div id="t4">t4</div> 39 <button id="none">none</button> 40 `, 41 async function testControllerFor() { 42 await definePyVar("doc", `getDocUia()`); 43 await testUiaRelationArray("controls", "ControllerFor", ["t1", "t2"]); 44 // The IA2 -> UIA proxy doesn't support IA2_RELATION_ERROR. 45 if (gIsUiaEnabled) { 46 await testUiaRelationArray("error", "ControllerFor", ["t3", "t4"]); 47 await testUiaRelationArray("controlsError", "ControllerFor", [ 48 "t1", 49 "t2", 50 "t3", 51 "t4", 52 ]); 53 } 54 await testUiaRelationArray("none", "ControllerFor", []); 55 } 56 ); 57 58 /** 59 * Test the DescribedBy property. 60 */ 61 addUiaTask( 62 ` 63 <input id="describedby" aria-describedby="t1 t2"> 64 <input id="details" aria-details="t3 t4"> 65 <input id="describedbyDetails" aria-describedby="t1 t2" aria-details="t3 t4" aria-invalid="true"> 66 <div id="t1">t1</div> 67 <div id="t2">t2</div> 68 <div id="t3">t3</div> 69 <div id="t4">t4</div> 70 <button id="none">none</button> 71 `, 72 async function testDescribedBy() { 73 await definePyVar("doc", `getDocUia()`); 74 await testUiaRelationArray("describedby", "DescribedBy", ["t1", "t2"]); 75 // The IA2 -> UIA proxy doesn't support IA2_RELATION_DETAILS. 76 if (gIsUiaEnabled) { 77 await testUiaRelationArray("details", "DescribedBy", ["t3", "t4"]); 78 await testUiaRelationArray("describedbyDetails", "DescribedBy", [ 79 "t1", 80 "t2", 81 "t3", 82 "t4", 83 ]); 84 } 85 await testUiaRelationArray("none", "DescribedBy", []); 86 } 87 ); 88 89 /** 90 * Test the FlowsFrom and FlowsTo properties. 91 */ 92 addUiaTask( 93 ` 94 <div id="t1" aria-flowto="t2">t1</div> 95 <div id="t2">t2</div> 96 <button id="none">none</button> 97 `, 98 async function testFlows() { 99 await definePyVar("doc", `getDocUia()`); 100 await testUiaRelationArray("t1", "FlowsTo", ["t2"]); 101 await testUiaRelationArray("t2", "FlowsFrom", ["t1"]); 102 await testUiaRelationArray("none", "FlowsFrom", []); 103 await testUiaRelationArray("none", "FlowsTo", []); 104 } 105 ); 106 107 /** 108 * Test the LabeledBy property. 109 */ 110 addUiaTask( 111 ` 112 <label id="label">label</label> 113 <input id="input" aria-labelledby="label"> 114 <label id="wrappingLabel"> 115 <input id="wrappedInput" value="wrappedInput"> 116 <p id="wrappingLabelP">wrappingLabel</p> 117 </label> 118 <button id="button" aria-labelledby="label">content</button> 119 <button id="noLabel">noLabel</button> 120 `, 121 async function testLabeledBy() { 122 await definePyVar("doc", `getDocUia()`); 123 // input's LabeledBy should be label's text leaf. 124 let result = await runPython(` 125 input = findUiaByDomId(doc, "input") 126 label = findUiaByDomId(doc, "label") 127 labelLeaf = uiaClient.RawViewWalker.GetFirstChildElement(label) 128 return uiaClient.CompareElements(input.CurrentLabeledBy, labelLeaf) 129 `); 130 ok(result, "input has correct LabeledBy"); 131 // wrappedInput's LabeledBy should be wrappingLabelP's text leaf. 132 result = await runPython(` 133 wrappedInput = findUiaByDomId(doc, "wrappedInput") 134 wrappingLabelP = findUiaByDomId(doc, "wrappingLabelP") 135 wrappingLabelLeaf = uiaClient.RawViewWalker.GetFirstChildElement(wrappingLabelP) 136 return uiaClient.CompareElements(wrappedInput.CurrentLabeledBy, wrappingLabelLeaf) 137 `); 138 ok(result, "wrappedInput has correct LabeledBy"); 139 // button has aria-labelledby, but UIA prohibits LabeledBy on buttons. 140 ok( 141 !(await runPython( 142 `bool(findUiaByDomId(doc, "button").CurrentLabeledBy)` 143 )), 144 "button has no LabeledBy" 145 ); 146 ok( 147 !(await runPython( 148 `bool(findUiaByDomId(doc, "noLabel").CurrentLabeledBy)` 149 )), 150 "noLabel has no LabeledBy" 151 ); 152 }, 153 // The IA2 -> UIA proxy doesn't expose LabeledBy properly. 154 { uiaEnabled: true, uiaDisabled: false } 155 ); 156 157 /** 158 * Test the AccessibleActions property. 159 */ 160 addUiaTask( 161 ` 162 <dialog aria-actions="btn" id="dlg" onclick="" open> 163 Dialog with its own click listener 164 <form method="dialog"> 165 <button id="btn">Close</button> 166 </form> 167 </dialog> 168 `, 169 async function testActions() { 170 await definePyVar("doc", `getDocUia()`); 171 await testCustomUiaRelationArray("dlg", "AccessibleActions", ["btn"]); 172 await testCustomUiaRelationArray("btn", "AccessibleActions", []); 173 }, 174 // The IA2 -> UIA proxy doesn't support AccessibleActions. 175 { uiaEnabled: true, uiaDisabled: false } 176 ); 177 178 /** 179 * Test exposure of AriaProperties.hasactions. 180 */ 181 addUiaTask( 182 ` 183 <button id="button">button</button> 184 <div role="tablist"> 185 <div id="tab1" role="tab" tabindex="0" aria-actions="tab1Button"> 186 tab1 187 <button id="tab1Button">tab1Button</button> 188 </div> 189 <div id="tab2" role="tab" aria-actions="tab2Button"> 190 tab2 191 <button id="tab2Button" hidden>tab2Button</button> 192 </div> 193 </div> 194 `, 195 async function testHasActions() { 196 await definePyVar("doc", `getDocUia()`); 197 is( 198 await runPython(`findUiaByDomId(doc, "button").CurrentAriaProperties`), 199 "", 200 "button missing hasactions" 201 ); 202 // tab1 has a visible action. 203 is( 204 await runPython(`findUiaByDomId(doc, "tab1").CurrentAriaProperties`), 205 "hasactions=true", 206 "tab1 hasactions=true" 207 ); 208 // tab2 has an action, but it's hidden. 209 is( 210 await runPython(`findUiaByDomId(doc, "tab2").CurrentAriaProperties`), 211 "hasactions=true", 212 "tab2 hasactions=true" 213 ); 214 }, 215 // The IA2 -> UIA proxy doesn't support hasactions. 216 { uiaEnabled: true, uiaDisabled: false } 217 );