browser_treeupdate_move.js (3368B)
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 add_setup(async function () { 15 await SpecialPowers.pushPrefEnv({ 16 set: [["test.wait300msAfterTabSwitch", true]], 17 }); 18 }); 19 20 /** 21 * Test moving Accessibles: 22 * 1. A moved Accessible keeps the same Accessible. 23 * 2. If the moved Accessible is focused, it remains focused. 24 * 3. A child of the moved Accessible also keeps the same Accessible. 25 * 4. A child removed at the same time as the move gets shut down. 26 */ 27 addAccessibleTask( 28 ` 29 <div id="scrollable" role="presentation" style="height: 1px;"> 30 <div contenteditable id="textbox" role="textbox"> 31 <h1 id="heading">Heading</h1> 32 <p id="para">Para</p> 33 </div> 34 <iframe id="iframe" src="https://example.com/"></iframe> 35 </div> 36 `, 37 async function (browser, docAcc) { 38 const textbox = findAccessibleChildByID(docAcc, "textbox"); 39 const heading = findAccessibleChildByID(docAcc, "heading"); 40 const para = findAccessibleChildByID(docAcc, "para"); 41 const iframe = findAccessibleChildByID(docAcc, "iframe"); 42 const iframeDoc = iframe.firstChild; 43 ok(iframeDoc, "iframe contains a document"); 44 45 let focused = waitForEvent(EVENT_FOCUS, textbox); 46 textbox.takeFocus(); 47 await focused; 48 testStates(textbox, STATE_FOCUSED, 0, 0, EXT_STATE_DEFUNCT); 49 50 let hidden = waitForEvent(EVENT_HIDE, textbox); 51 let reordered = waitForEvent(EVENT_REORDER, docAcc); 52 await invokeContentTask(browser, [], () => { 53 // scrollable wasn't in the a11y tree, but this will force it to be created. 54 // textbox will be moved inside it. 55 content.document.getElementById("scrollable").style.overflow = "scroll"; 56 content.document.getElementById("heading").remove(); 57 }); 58 await hidden; 59 ok(!para.nextSibling, "para nextSibling is null during move"); 60 await reordered; 61 // Despite the move, ensure textbox is still alive and is focused. 62 testStates(textbox, STATE_FOCUSED, 0, 0, EXT_STATE_DEFUNCT); 63 // Ensure para (a child of textbox) is also still alive. 64 ok(!isDefunct(para), "para is alive"); 65 // heading was a child of textbox, but was removed when textbox 66 // was moved. Ensure it is dead. 67 ok(isDefunct(heading), "heading is dead"); 68 // Ensure the iframe and its embedded document are alive. 69 ok(!isDefunct(iframe), "iframe is alive"); 70 ok(!isDefunct(iframeDoc), "iframeDoc is alive"); 71 }, 72 { chrome: true, topLevel: true, iframe: true, remoteIframe: true } 73 ); 74 75 /** 76 * Test that moving a subtree containing an iframe doesn't cause assertions or 77 * crashes. Note that aria-owns moves Accessibles even if it is set before load. 78 */ 79 addAccessibleTask( 80 ` 81 <div id="container"> 82 <iframe id="iframe"></iframe> 83 <div aria-owns="iframe"></div> 84 </div> 85 `, 86 async function (browser, docAcc) { 87 const container = findAccessibleChildByID(docAcc, "container"); 88 testAccessibleTree(container, { 89 SECTION: [{ SECTION: [{ INTERNAL_FRAME: [{ DOCUMENT: [] }] }] }], 90 }); 91 }, 92 { topLevel: true } 93 );