browser_aria_owns.js (8138B)
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 let NO_MOVE = { unexpected: [[EVENT_REORDER, "container"]] }; 8 let MOVE = { expected: [[EVENT_REORDER, "container"]] }; 9 10 // Set last ordinal child as aria-owned, should produce no reorder. 11 addAccessibleTask( 12 `<ul id="container"><li id="a">Test</li></ul>`, 13 async function (browser, accDoc) { 14 let containerAcc = findAccessibleChildByID(accDoc, "container"); 15 16 testChildrenIds(containerAcc, ["a"]); 17 18 await contentSpawnMutation(browser, NO_MOVE, function () { 19 // aria-own ordinal child in place, should be a no-op. 20 content.document 21 .getElementById("container") 22 .setAttribute("aria-owns", "a"); 23 }); 24 25 testChildrenIds(containerAcc, ["a"]); 26 } 27 ); 28 29 // Add a new ordinal child to a container with an aria-owned child. 30 // Order should respect aria-owns. 31 addAccessibleTask( 32 `<ul id="container"><li id="a">Test</li></ul>`, 33 async function (browser, accDoc) { 34 let containerAcc = findAccessibleChildByID(accDoc, "container"); 35 36 testChildrenIds(containerAcc, ["a"]); 37 38 await contentSpawnMutation(browser, MOVE, function () { 39 let container = content.document.getElementById("container"); 40 container.setAttribute("aria-owns", "a"); 41 42 let aa = content.document.createElement("li"); 43 aa.id = "aa"; 44 container.appendChild(aa); 45 }); 46 47 testChildrenIds(containerAcc, ["aa", "a"]); 48 49 await contentSpawnMutation(browser, MOVE, function () { 50 content.document.getElementById("container").removeAttribute("aria-owns"); 51 }); 52 53 testChildrenIds(containerAcc, ["a", "aa"]); 54 } 55 ); 56 57 // Remove a no-move aria-owns attribute, should result in a no-move. 58 addAccessibleTask( 59 `<ul id="container" aria-owns="a"><li id="a">Test</li></ul>`, 60 async function (browser, accDoc) { 61 let containerAcc = findAccessibleChildByID(accDoc, "container"); 62 63 testChildrenIds(containerAcc, ["a"]); 64 65 await contentSpawnMutation(browser, NO_MOVE, function () { 66 // remove aria-owned child that is already ordinal, should be no-op. 67 content.document.getElementById("container").removeAttribute("aria-owns"); 68 }); 69 70 testChildrenIds(containerAcc, ["a"]); 71 } 72 ); 73 74 // Attempt to steal an aria-owned child. The attempt should fail. 75 addAccessibleTask( 76 ` 77 <ul> 78 <li id="a">Test</li> 79 </ul> 80 <ul aria-owns="a"></ul> 81 <ul id="container"></ul>`, 82 async function (browser, accDoc) { 83 let containerAcc = findAccessibleChildByID(accDoc, "container"); 84 85 testChildrenIds(containerAcc, []); 86 87 await contentSpawnMutation(browser, NO_MOVE, function () { 88 content.document 89 .getElementById("container") 90 .setAttribute("aria-owns", "a"); 91 }); 92 93 testChildrenIds(containerAcc, []); 94 } 95 ); 96 97 // Don't aria-own children of <select> 98 addAccessibleTask( 99 ` 100 <div id="container" role="group" aria-owns="b"></div> 101 <select id="select"> 102 <option id="a"></option> 103 <option id="b"></option> 104 </select>`, 105 async function (browser, accDoc) { 106 let containerAcc = findAccessibleChildByID(accDoc, "container"); 107 let selectAcc = findAccessibleChildByID(accDoc, "select"); 108 109 testChildrenIds(containerAcc, []); 110 testChildrenIds(selectAcc.firstChild, ["a", "b"]); 111 } 112 ); 113 114 // Don't allow <select> to aria-own 115 addAccessibleTask( 116 ` 117 <div id="container" role="group"> 118 <div id="a"></div> 119 <div id="b"></div> 120 </div> 121 <select id="select" aria-owns="a"> 122 <option id="c"></option> 123 </select>`, 124 async function (browser, accDoc) { 125 let containerAcc = findAccessibleChildByID(accDoc, "container"); 126 let selectAcc = findAccessibleChildByID(accDoc, "select"); 127 128 testChildrenIds(containerAcc, ["a", "b"]); 129 testChildrenIds(selectAcc.firstChild, ["c"]); 130 } 131 ); 132 133 // Don't allow one <select> to aria-own an <option> from another <select>. 134 addAccessibleTask( 135 ` 136 <select id="select1" aria-owns="c"> 137 <option id="a"></option> 138 <option id="b"></option> 139 </select> 140 <select id="select2"> 141 <option id="c"></option> 142 </select>`, 143 async function (browser, accDoc) { 144 let selectAcc1 = findAccessibleChildByID(accDoc, "select1"); 145 let selectAcc2 = findAccessibleChildByID(accDoc, "select2"); 146 147 testChildrenIds(selectAcc1.firstChild, ["a", "b"]); 148 testChildrenIds(selectAcc2.firstChild, ["c"]); 149 } 150 ); 151 152 // Don't allow a <select> to reorder its children with aria-owns. 153 addAccessibleTask( 154 ` 155 <select id="container" aria-owns="c b a"> 156 <option id="a"></option> 157 <option id="b"></option> 158 <option id="c"></option> 159 </select>`, 160 async function (browser, accDoc) { 161 let containerAcc = findAccessibleChildByID(accDoc, "container"); 162 163 testChildrenIds(containerAcc.firstChild, ["a", "b", "c"]); 164 165 await contentSpawnMutation(browser, NO_MOVE, function () { 166 content.document 167 .getElementById("container") 168 .setAttribute("aria-owns", "a c b"); 169 }); 170 171 testChildrenIds(containerAcc.firstChild, ["a", "b", "c"]); 172 } 173 ); 174 175 // Don't crash if ID in aria-owns does not exist 176 addAccessibleTask( 177 ` 178 <select id="container" aria-owns="boom" multiple></select>`, 179 async function () { 180 ok(true, "Did not crash"); 181 } 182 ); 183 184 addAccessibleTask( 185 ` 186 <ul id="one"> 187 <li id="a">Test</li> 188 <li id="b">Test 2</li> 189 <li id="c">Test 3</li> 190 </ul> 191 <ul id="two"></ul>`, 192 async function (browser, accDoc) { 193 let one = findAccessibleChildByID(accDoc, "one"); 194 let two = findAccessibleChildByID(accDoc, "two"); 195 196 let waitfor = { 197 expected: [ 198 [EVENT_REORDER, "one"], 199 [EVENT_REORDER, "two"], 200 ], 201 }; 202 203 await contentSpawnMutation(browser, waitfor, function () { 204 // Put same id twice in aria-owns 205 content.document.getElementById("two").setAttribute("aria-owns", "a a"); 206 }); 207 208 testChildrenIds(one, ["b", "c"]); 209 testChildrenIds(two, ["a"]); 210 211 await contentSpawnMutation(browser, waitfor, function () { 212 // If the previous double-id aria-owns worked correctly, we should 213 // be in a good state and all is fine.. 214 content.document.getElementById("two").setAttribute("aria-owns", "a b"); 215 }); 216 217 testChildrenIds(one, ["c"]); 218 testChildrenIds(two, ["a", "b"]); 219 } 220 ); 221 222 addAccessibleTask( 223 `<div id="a"></div><div id="b"></div>`, 224 async function (browser, accDoc) { 225 testChildrenIds(accDoc, ["a", "b"]); 226 227 let waitFor = { 228 expected: [[EVENT_REORDER, e => e.accessible == accDoc]], 229 }; 230 231 await contentSpawnMutation(browser, waitFor, function () { 232 content.document.documentElement.style.display = "none"; 233 content.document.documentElement.getBoundingClientRect(); 234 content.document.body.setAttribute("aria-owns", "b a"); 235 content.document.documentElement.remove(); 236 }); 237 238 testChildrenIds(accDoc, []); 239 } 240 ); 241 242 // Don't allow ordinal child to be placed after aria-owned child (bug 1405796) 243 addAccessibleTask( 244 `<div id="container"><div id="a">Hello</div></div> 245 <div><div id="c">There</div><div id="d">There</div></div>`, 246 async function (browser, accDoc) { 247 let containerAcc = findAccessibleChildByID(accDoc, "container"); 248 249 testChildrenIds(containerAcc, ["a"]); 250 251 await contentSpawnMutation(browser, MOVE, function () { 252 content.document 253 .getElementById("container") 254 .setAttribute("aria-owns", "c"); 255 }); 256 257 testChildrenIds(containerAcc, ["a", "c"]); 258 259 await contentSpawnMutation(browser, MOVE, function () { 260 let span = content.document.createElement("span"); 261 content.document.getElementById("container").appendChild(span); 262 263 let b = content.document.createElement("div"); 264 b.id = "b"; 265 content.document.getElementById("container").appendChild(b); 266 }); 267 268 testChildrenIds(containerAcc, ["a", "b", "c"]); 269 270 await contentSpawnMutation(browser, MOVE, function () { 271 content.document 272 .getElementById("container") 273 .setAttribute("aria-owns", "c d"); 274 }); 275 276 testChildrenIds(containerAcc, ["a", "b", "c", "d"]); 277 } 278 );