browser_radio_position.js (10121B)
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 /* import-globals-from ../../mochitest/role.js */ 8 /* import-globals-from ../../mochitest/states.js */ 9 loadScripts( 10 { name: "role.js", dir: MOCHITESTS_DIR }, 11 { name: "states.js", dir: MOCHITESTS_DIR } 12 ); 13 14 function getChildRoles(parent) { 15 return parent 16 .getAttributeValue("AXChildren") 17 .map(c => c.getAttributeValue("AXRole")); 18 } 19 20 function getLinkedTitles(element) { 21 return element.getAttributeValue("AXLinkedUIElements").map(linkedElem => { 22 let labelElem = linkedElem.getAttributeValue("AXTitleUIElement"); 23 let labelText = labelElem 24 ? labelElem 25 .getAttributeValue("AXChildren") 26 .map(c => c.getAttributeValue("AXValue")) 27 .join("") 28 : null; 29 return labelText ? labelText : linkedElem.getAttributeValue("AXTitle"); 30 }); 31 } 32 33 /** 34 * Test radio group 35 */ 36 addAccessibleTask( 37 `<div role="radiogroup" id="radioGroup"> 38 <div role="radio" 39 id="radioGroupItem1"> 40 Regular crust 41 </div> 42 <div role="radio" 43 id="radioGroupItem2"> 44 Deep dish 45 </div> 46 <div role="radio" 47 id="radioGroupItem3"> 48 Thin crust 49 </div> 50 </div>`, 51 async (browser, accDoc) => { 52 let item1 = getNativeInterface(accDoc, "radioGroupItem1"); 53 let item2 = getNativeInterface(accDoc, "radioGroupItem2"); 54 let item3 = getNativeInterface(accDoc, "radioGroupItem3"); 55 let titleList = ["Regular crust", "Deep dish", "Thin crust"]; 56 57 Assert.deepEqual( 58 titleList, 59 [item1, item2, item3].map(c => c.getAttributeValue("AXTitle")), 60 "Title list matches" 61 ); 62 63 let linkedElems = item1.getAttributeValue("AXLinkedUIElements"); 64 is(linkedElems.length, 3, "Item 1 has three linked UI elems"); 65 Assert.deepEqual( 66 getLinkedTitles(item1), 67 titleList, 68 "Item one has correctly ordered linked elements" 69 ); 70 71 linkedElems = item2.getAttributeValue("AXLinkedUIElements"); 72 is(linkedElems.length, 3, "Item 2 has three linked UI elems"); 73 Assert.deepEqual( 74 getLinkedTitles(item2), 75 titleList, 76 "Item two has correctly ordered linked elements" 77 ); 78 79 linkedElems = item3.getAttributeValue("AXLinkedUIElements"); 80 is(linkedElems.length, 3, "Item 3 has three linked UI elems"); 81 Assert.deepEqual( 82 getLinkedTitles(item3), 83 titleList, 84 "Item three has correctly ordered linked elements" 85 ); 86 } 87 ); 88 89 /** 90 * Test dynamic add to a radio group 91 */ 92 addAccessibleTask( 93 `<div role="radiogroup" id="radioGroup"> 94 <div role="radio" 95 id="radioGroupItem1"> 96 Option One 97 </div> 98 </div>`, 99 async (browser, accDoc) => { 100 let item1 = getNativeInterface(accDoc, "radioGroupItem1"); 101 let linkedElems = item1.getAttributeValue("AXLinkedUIElements"); 102 103 is(linkedElems.length, 1, "Item 1 has one linked UI elem"); 104 is( 105 linkedElems[0].getAttributeValue("AXTitle"), 106 item1.getAttributeValue("AXTitle"), 107 "Item 1 is first element" 108 ); 109 110 let reorder = waitForEvent(EVENT_REORDER, "radioGroup"); 111 await SpecialPowers.spawn(browser, [], () => { 112 let d = content.document.createElement("div"); 113 d.setAttribute("role", "radio"); 114 content.document.getElementById("radioGroup").appendChild(d); 115 }); 116 await reorder; 117 118 let radioGroup = getNativeInterface(accDoc, "radioGroup"); 119 let groupMembers = radioGroup.getAttributeValue("AXChildren"); 120 is(groupMembers.length, 2, "Radio group has two members"); 121 let item2 = groupMembers[1]; 122 item1 = getNativeInterface(accDoc, "radioGroupItem1"); 123 let titleList = ["Option One", ""]; 124 125 Assert.deepEqual( 126 titleList, 127 [item1, item2].map(c => c.getAttributeValue("AXTitle")), 128 "Title list matches" 129 ); 130 131 linkedElems = item1.getAttributeValue("AXLinkedUIElements"); 132 is(linkedElems.length, 2, "Item 1 has two linked UI elems"); 133 Assert.deepEqual( 134 getLinkedTitles(item1), 135 titleList, 136 "Item one has correctly ordered linked elements" 137 ); 138 139 linkedElems = item2.getAttributeValue("AXLinkedUIElements"); 140 is(linkedElems.length, 2, "Item 2 has two linked UI elems"); 141 Assert.deepEqual( 142 getLinkedTitles(item2), 143 titleList, 144 "Item two has correctly ordered linked elements" 145 ); 146 } 147 ); 148 149 /** 150 * Test input[type=radio] for single group 151 */ 152 addAccessibleTask( 153 `<input type="radio" id="cat" name="animal"><label for="cat">Cat</label> 154 <input type="radio" id="dog" name="animal"><label for="dog">Dog</label> 155 <input type="radio" id="catdog" name="animal"><label for="catdog">CatDog</label>`, 156 async (browser, accDoc) => { 157 let cat = getNativeInterface(accDoc, "cat"); 158 let dog = getNativeInterface(accDoc, "dog"); 159 let catdog = getNativeInterface(accDoc, "catdog"); 160 let titleList = ["Cat", "Dog", "CatDog"]; 161 162 let linkedElems = cat.getAttributeValue("AXLinkedUIElements"); 163 is(linkedElems.length, 3, "Cat has three linked UI elems"); 164 Assert.deepEqual( 165 getLinkedTitles(cat), 166 titleList, 167 "Cat has correctly ordered linked elements" 168 ); 169 170 linkedElems = dog.getAttributeValue("AXLinkedUIElements"); 171 is(linkedElems.length, 3, "Dog has three linked UI elems"); 172 Assert.deepEqual( 173 getLinkedTitles(dog), 174 titleList, 175 "Dog has correctly ordered linked elements" 176 ); 177 178 linkedElems = catdog.getAttributeValue("AXLinkedUIElements"); 179 is(linkedElems.length, 3, "Catdog has three linked UI elems"); 180 Assert.deepEqual( 181 getLinkedTitles(catdog), 182 titleList, 183 "catdog has correctly ordered linked elements" 184 ); 185 } 186 ); 187 188 /** 189 * Test input[type=radio] for different groups 190 */ 191 addAccessibleTask( 192 `<input type="radio" id="cat" name="one"><label for="cat">Cat</label> 193 <input type="radio" id="dog" name="two"><label for="dog">Dog</label> 194 <input type="radio" id="catdog"><label for="catdog">CatDog</label>`, 195 async (browser, accDoc) => { 196 let cat = getNativeInterface(accDoc, "cat"); 197 let dog = getNativeInterface(accDoc, "dog"); 198 let catdog = getNativeInterface(accDoc, "catdog"); 199 200 let linkedElems = cat.getAttributeValue("AXLinkedUIElements"); 201 is(linkedElems.length, 1, "Cat has one linked UI elem"); 202 is( 203 linkedElems[0].getAttributeValue("AXTitle"), 204 cat.getAttributeValue("AXTitle"), 205 "Cat is only element" 206 ); 207 208 linkedElems = dog.getAttributeValue("AXLinkedUIElements"); 209 is(linkedElems.length, 1, "Dog has one linked UI elem"); 210 is( 211 linkedElems[0].getAttributeValue("AXTitle"), 212 dog.getAttributeValue("AXTitle"), 213 "Dog is only element" 214 ); 215 216 linkedElems = catdog.getAttributeValue("AXLinkedUIElements"); 217 is(linkedElems.length, 0, "Catdog has no linked UI elem"); 218 } 219 ); 220 221 /** 222 * Test input[type=radio] for single group across DOM 223 */ 224 addAccessibleTask( 225 `<input type="radio" id="cat" name="animal"><label for="cat">Cat</label> 226 <div> 227 <span> 228 <input type="radio" id="dog" name="animal"><label for="dog">Dog</label> 229 </span> 230 </div> 231 <div> 232 <input type="radio" id="catdog" name="animal"><label for="catdog">CatDog</label> 233 </div>`, 234 async (browser, accDoc) => { 235 let cat = getNativeInterface(accDoc, "cat"); 236 let dog = getNativeInterface(accDoc, "dog"); 237 let catdog = getNativeInterface(accDoc, "catdog"); 238 let titleList = ["Cat", "Dog", "CatDog"]; 239 240 let linkedElems = cat.getAttributeValue("AXLinkedUIElements"); 241 is(linkedElems.length, 3, "Cat has three linked UI elems"); 242 Assert.deepEqual( 243 getLinkedTitles(cat), 244 titleList, 245 "cat has correctly ordered linked elements" 246 ); 247 248 linkedElems = dog.getAttributeValue("AXLinkedUIElements"); 249 is(linkedElems.length, 3, "Dog has three linked UI elems"); 250 Assert.deepEqual( 251 getLinkedTitles(dog), 252 titleList, 253 "dog has correctly ordered linked elements" 254 ); 255 256 linkedElems = catdog.getAttributeValue("AXLinkedUIElements"); 257 is(linkedElems.length, 3, "Catdog has three linked UI elems"); 258 Assert.deepEqual( 259 getLinkedTitles(catdog), 260 titleList, 261 "catdog has correctly ordered linked elements" 262 ); 263 } 264 ); 265 266 /** 267 * Test dynamic add of input[type=radio] in a single group 268 */ 269 addAccessibleTask( 270 `<div id="container"><input type="radio" id="cat" name="animal"></div>`, 271 async (browser, accDoc) => { 272 let cat = getNativeInterface(accDoc, "cat"); 273 let container = getNativeInterface(accDoc, "container"); 274 275 let containerChildren = container.getAttributeValue("AXChildren"); 276 is(containerChildren.length, 1, "container has one button"); 277 is( 278 containerChildren[0].getAttributeValue("AXRole"), 279 "AXRadioButton", 280 "Container child is radio button" 281 ); 282 283 let linkedElems = cat.getAttributeValue("AXLinkedUIElements"); 284 is(linkedElems.length, 1, "Cat has 1 linked UI elem"); 285 is( 286 linkedElems[0].getAttributeValue("AXTitle"), 287 cat.getAttributeValue("AXTitle"), 288 "Cat is first element" 289 ); 290 let reorder = waitForEvent(EVENT_REORDER, "container"); 291 await SpecialPowers.spawn(browser, [], () => { 292 let input = content.document.createElement("input"); 293 input.setAttribute("type", "radio"); 294 input.setAttribute("name", "animal"); 295 content.document.getElementById("container").appendChild(input); 296 }); 297 await reorder; 298 299 container = getNativeInterface(accDoc, "container"); 300 containerChildren = container.getAttributeValue("AXChildren"); 301 302 is(containerChildren.length, 2, "container has two children"); 303 304 Assert.deepEqual( 305 getChildRoles(container), 306 ["AXRadioButton", "AXRadioButton"], 307 "Both children are radio buttons" 308 ); 309 310 linkedElems = containerChildren[0].getAttributeValue("AXLinkedUIElements"); 311 is(linkedElems.length, 2, "Cat has 2 linked elements"); 312 313 linkedElems = containerChildren[1].getAttributeValue("AXLinkedUIElements"); 314 is(linkedElems.length, 2, "New button has 2 linked elements"); 315 } 316 );