browser_popover_and_command.js (13418B)
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 /** 8 * Test details relations for the popovertarget content attribute. 9 */ 10 addAccessibleTask( 11 ` 12 <button id="hide" popovertarget="popover" popovertargetaction="hide">hide</button> 13 <button id="toggle1" popovertarget="popover">toggle1</button> 14 <button id="toggle2">toggle2</button> 15 <button id="toggleSibling">toggleSibling</button> 16 <div id="popover" popover>popover</div> 17 <div id="details">details</div> 18 `, 19 async function testPopoverContent(browser, docAcc) { 20 // The popover is hidden, so nothing should be referring to it. 21 const hide = findAccessibleChildByID(docAcc, "hide"); 22 await testCachedRelation(hide, RELATION_DETAILS, []); 23 const toggle1 = findAccessibleChildByID(docAcc, "toggle1"); 24 await testCachedRelation(toggle1, RELATION_DETAILS, []); 25 const toggle2 = findAccessibleChildByID(docAcc, "toggle2"); 26 await testCachedRelation(toggle2, RELATION_DETAILS, []); 27 const toggleSibling = findAccessibleChildByID(docAcc, "toggleSibling"); 28 await testCachedRelation(toggleSibling, RELATION_DETAILS, []); 29 30 info("Showing popover"); 31 let shown = waitForEvent(EVENT_SHOW, "popover"); 32 toggle1.doAction(0); 33 const popover = (await shown).accessible; 34 await testCachedRelation(toggle1, RELATION_DETAILS, popover); 35 // toggle2 shouldn't have a details relation because it doesn't have a 36 // popovertarget. 37 await testCachedRelation(toggle2, RELATION_DETAILS, []); 38 // hide shouldn't have a details relation because its action is hide. 39 await testCachedRelation(hide, RELATION_DETAILS, []); 40 // toggleSibling shouldn't have a details relation because it is a sibling 41 // of the popover. 42 await testCachedRelation(toggleSibling, RELATION_DETAILS, []); 43 await testCachedRelation(popover, RELATION_DETAILS_FOR, toggle1); 44 45 is( 46 toggle1.attributes.getStringProperty("details-from"), 47 "popover-target", 48 "Correct details-from attribute" 49 ); 50 51 info("Setting toggle2 popovertarget"); 52 await invokeSetAttribute(browser, "toggle2", "popovertarget", "popover"); 53 await testCachedRelation(toggle2, RELATION_DETAILS, popover); 54 await testCachedRelation(popover, RELATION_DETAILS_FOR, [toggle1, toggle2]); 55 56 info("Removing toggle2 popovertarget"); 57 await invokeSetAttribute(browser, "toggle2", "popovertarget", null); 58 await testCachedRelation(toggle2, RELATION_DETAILS, []); 59 await testCachedRelation(popover, RELATION_DETAILS_FOR, toggle1); 60 61 info("Setting aria-details on toggle1"); 62 await invokeSetAttribute(browser, "toggle1", "aria-details", "details"); 63 const details = findAccessibleChildByID(docAcc, "details"); 64 // aria-details overrides popover. 65 await testCachedRelation(toggle1, RELATION_DETAILS, details); 66 await testCachedRelation(popover, RELATION_DETAILS_FOR, []); 67 68 info("Removing aria-details from toggle1"); 69 await invokeSetAttribute(browser, "toggle1", "aria-details", null); 70 await testCachedRelation(toggle1, RELATION_DETAILS, popover); 71 await testCachedRelation(popover, RELATION_DETAILS_FOR, toggle1); 72 73 info("Hiding popover"); 74 let hidden = waitForEvent(EVENT_HIDE, popover); 75 toggle1.doAction(0); 76 // The relations between toggle1 and popover are removed when popover shuts 77 // down. However, this doesn't cause a cache update notification. Therefore, 78 // to avoid timing out in testCachedRelation, we must wait for a hide event 79 // first. 80 await hidden; 81 await testCachedRelation(toggle1, RELATION_DETAILS, []); 82 }, 83 { chrome: false, topLevel: true } 84 ); 85 86 /** 87 * Test details relations for the commandfor content attribute. 88 */ 89 addAccessibleTask( 90 ` 91 <button id="hide" commandfor="popover" command="hide-popover">hide</button> 92 <button id="toggle1" commandfor="popover" command="toggle-popover">toggle1</button> 93 <button id="show" commandfor="popover" command="show-popover">show</button> 94 <button id="showModal" commandfor="popover" command="show-modal">show-modal</button> 95 <button id="invalid" commandfor="popover" command="invalid">invalid</button> 96 <button id="custom" commandfor="popover" command="--custom">custom</button> 97 <button id="toggle2" command="toggle-popover">toggle2</button> 98 <button id="toggleSibling" commandfor="popover" command="toggle-popover">toggleSibling</button> 99 <dialog id="popover" popover>popover</dialog> 100 <div id="details">details</div> 101 `, 102 async function testPopoverContent(browser, docAcc) { 103 // The popover is hidden, so nothing should be referring to it. 104 const hide = findAccessibleChildByID(docAcc, "hide"); 105 await testCachedRelation(hide, RELATION_DETAILS, []); 106 const toggle1 = findAccessibleChildByID(docAcc, "toggle1"); 107 await testCachedRelation(toggle1, RELATION_DETAILS, []); 108 const show = findAccessibleChildByID(docAcc, "show"); 109 await testCachedRelation(show, RELATION_DETAILS, []); 110 const toggle2 = findAccessibleChildByID(docAcc, "toggle2"); 111 await testCachedRelation(toggle2, RELATION_DETAILS, []); 112 const showModal = findAccessibleChildByID(docAcc, "showModal"); 113 await testCachedRelation(showModal, RELATION_DETAILS, []); 114 const invalid = findAccessibleChildByID(docAcc, "invalid"); 115 await testCachedRelation(invalid, RELATION_DETAILS, []); 116 const custom = findAccessibleChildByID(docAcc, "custom"); 117 await testCachedRelation(custom, RELATION_DETAILS, []); 118 const toggleSibling = findAccessibleChildByID(docAcc, "toggleSibling"); 119 await testCachedRelation(toggleSibling, RELATION_DETAILS, []); 120 121 info("Showing popover"); 122 let shown = waitForEvent(EVENT_SHOW, "popover"); 123 toggle1.doAction(0); 124 const popover = (await shown).accessible; 125 await testCachedRelation(toggle1, RELATION_DETAILS, popover); 126 await testCachedRelation(show, RELATION_DETAILS, popover); 127 // toggle2 shouldn't have a details relation because it doesn't have a 128 // commandfor. 129 await testCachedRelation(toggle2, RELATION_DETAILS, []); 130 // hide shouldn't have a details relation because its action is hide-popover. 131 await testCachedRelation(hide, RELATION_DETAILS, []); 132 // showModal shouldn't have a details relation because it is executing a 133 // non-popover command. 134 await testCachedRelation(showModal, RELATION_DETAILS, []); 135 // invalid shouldn't have a details relation because it has an invalid command. 136 await testCachedRelation(invalid, RELATION_DETAILS, []); 137 // custom shouldn't have a details relation because it has a custom command. 138 await testCachedRelation(invalid, RELATION_DETAILS, []); 139 // toggleSibling shouldn't have a details relation because it is a sibling 140 // of the popover. 141 await testCachedRelation(toggleSibling, RELATION_DETAILS, []); 142 await testCachedRelation(popover, RELATION_DETAILS_FOR, [toggle1, show]); 143 is( 144 toggle1.attributes.getStringProperty("details-from"), 145 "command-for", 146 "Correct details-from attribute" 147 ); 148 149 info("Setting toggle2 commandfor"); 150 await invokeSetAttribute(browser, "toggle2", "commandfor", "popover"); 151 await testCachedRelation(toggle2, RELATION_DETAILS, popover); 152 153 await testCachedRelation(popover, RELATION_DETAILS_FOR, [ 154 toggle1, 155 show, 156 toggle2, 157 ]); 158 159 info("Removing toggle2 commandfor"); 160 await invokeSetAttribute(browser, "toggle2", "commandfor", null); 161 await testCachedRelation(toggle2, RELATION_DETAILS, []); 162 await testCachedRelation(popover, RELATION_DETAILS_FOR, [toggle1, show]); 163 164 info("Setting aria-details on toggle1"); 165 await invokeSetAttribute(browser, "toggle1", "aria-details", "details"); 166 const details = findAccessibleChildByID(docAcc, "details"); 167 // aria-details overrides popover. 168 await testCachedRelation(toggle1, RELATION_DETAILS, details); 169 is( 170 toggle1.attributes.getStringProperty("details-from"), 171 "aria-details", 172 "Correct details-from attribute" 173 ); 174 175 await testCachedRelation(popover, RELATION_DETAILS_FOR, [show]); 176 177 info("Removing aria-details from toggle1"); 178 await invokeSetAttribute(browser, "toggle1", "aria-details", null); 179 await testCachedRelation(toggle1, RELATION_DETAILS, popover); 180 await testCachedRelation(popover, RELATION_DETAILS_FOR, [toggle1, show]); 181 182 is( 183 toggle1.attributes.getStringProperty("details-from"), 184 "command-for", 185 "Correct details-from attribute" 186 ); 187 188 info("Hiding popover"); 189 let hidden = waitForEvent(EVENT_HIDE, popover); 190 toggle1.doAction(0); 191 // The relations between toggle1 and popover are removed when popover shuts 192 // down. However, this doesn't cause a cache update notification. Therefore, 193 // to avoid timing out in testCachedRelation, we must wait for a hide event 194 // first. 195 await hidden; 196 await testCachedRelation(toggle1, RELATION_DETAILS, []); 197 await testCachedRelation(show, RELATION_DETAILS, []); 198 }, 199 { chrome: false, topLevel: true } 200 ); 201 202 /** 203 * Test details relations for the popoverTargetElement WebIDL attribute. 204 */ 205 addAccessibleTask( 206 ` 207 <button id="toggle1">toggle1</button> 208 <button id="toggle2">toggle2</button> 209 between 210 <div id="popover1" popover>popover1</div> 211 <button id="toggle3">toggle3</button> 212 <div id="shadowHost"><template shadowrootmode="open"> 213 <button id="toggle4">toggle4</button> 214 between 215 <div id="popover2" popover>popover2</div> 216 <button id="toggle5">toggle5</button> 217 </template></div> 218 `, 219 async function testPopoverIdl(browser, docAcc) { 220 // No popover is showing, so there shouldn't be any details relations. 221 const toggle1 = findAccessibleChildByID(docAcc, "toggle1"); 222 await testCachedRelation(toggle1, RELATION_DETAILS, []); 223 const toggle2 = findAccessibleChildByID(docAcc, "toggle2"); 224 await testCachedRelation(toggle2, RELATION_DETAILS, []); 225 const toggle3 = findAccessibleChildByID(docAcc, "toggle3"); 226 await testCachedRelation(toggle3, RELATION_DETAILS, []); 227 const toggle4 = findAccessibleChildByID(docAcc, "toggle4"); 228 await testCachedRelation(toggle4, RELATION_DETAILS, []); 229 const toggle5 = findAccessibleChildByID(docAcc, "toggle5"); 230 await testCachedRelation(toggle5, RELATION_DETAILS, []); 231 232 info("Showing popover1"); 233 let shown = waitForEvent(EVENT_SHOW, "popover1"); 234 toggle1.doAction(0); 235 const popover1 = (await shown).accessible; 236 await testCachedRelation(toggle1, RELATION_DETAILS, popover1); 237 // toggle5 is inside the shadow DOM and popover1 is outside, so the target 238 // is valid. 239 await testCachedRelation(toggle5, RELATION_DETAILS, popover1); 240 await testCachedRelation(popover1, RELATION_DETAILS_FOR, [ 241 toggle1, 242 toggle5, 243 ]); 244 info("Setting toggle2's popover target to popover1"); 245 await invokeContentTask(browser, [], () => { 246 const toggle2Dom = content.document.getElementById("toggle2"); 247 const popover1Dom = content.document.getElementById("popover1"); 248 toggle2Dom.popoverTargetElement = popover1Dom; 249 }); 250 await testCachedRelation(toggle2, RELATION_DETAILS, popover1); 251 await testCachedRelation(popover1, RELATION_DETAILS_FOR, [ 252 toggle1, 253 toggle2, 254 toggle5, 255 ]); 256 info("Clearing toggle2's popover target"); 257 await invokeContentTask(browser, [], () => { 258 const toggle2Dom = content.document.getElementById("toggle2"); 259 toggle2Dom.popoverTargetElement = null; 260 }); 261 await testCachedRelation(toggle2, RELATION_DETAILS, []); 262 await testCachedRelation(popover1, RELATION_DETAILS_FOR, [ 263 toggle1, 264 toggle5, 265 ]); 266 info("Hiding popover1"); 267 let hidden = waitForEvent(EVENT_HIDE, popover1); 268 toggle1.doAction(0); 269 await hidden; 270 await testCachedRelation(toggle1, RELATION_DETAILS, []); 271 await testCachedRelation(toggle2, RELATION_DETAILS, []); 272 await testCachedRelation(toggle5, RELATION_DETAILS, []); 273 274 info("Showing popover2"); 275 shown = waitForEvent(EVENT_SHOW, "popover2"); 276 toggle4.doAction(0); 277 const popover2 = (await shown).accessible; 278 // toggle4 is in the same shadow DOM as popover2. 279 await testCachedRelation(toggle4, RELATION_DETAILS, popover2); 280 // toggle3 is outside popover2's shadow DOM, so the target isn't valid. 281 await testCachedRelation(toggle3, RELATION_DETAILS, []); 282 await testCachedRelation(popover2, RELATION_DETAILS_FOR, [toggle4]); 283 info("Hiding popover2"); 284 hidden = waitForEvent(EVENT_HIDE, popover2); 285 toggle4.doAction(0); 286 await hidden; 287 await testCachedRelation(toggle4, RELATION_DETAILS, []); 288 }, 289 { 290 chrome: true, 291 topLevel: true, 292 contentSetup: async function contentSetup() { 293 const toggle1 = content.document.getElementById("toggle1"); 294 const popover1 = content.document.getElementById("popover1"); 295 toggle1.popoverTargetElement = popover1; 296 const toggle3 = content.document.getElementById("toggle3"); 297 const shadow = content.document.getElementById("shadowHost").shadowRoot; 298 const toggle4 = shadow.getElementById("toggle4"); 299 const popover2 = shadow.getElementById("popover2"); 300 toggle3.popoverTargetElement = popover2; 301 toggle4.popoverTargetElement = popover2; 302 const toggle5 = shadow.getElementById("toggle5"); 303 toggle5.popoverTargetElement = popover1; 304 }, 305 } 306 );