diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /accessible/tests/browser/tree | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'accessible/tests/browser/tree')
-rw-r--r-- | accessible/tests/browser/tree/browser.ini | 11 | ||||
-rw-r--r-- | accessible/tests/browser/tree/browser_aria_owns.js | 278 | ||||
-rw-r--r-- | accessible/tests/browser/tree/browser_searchbar.js | 52 | ||||
-rw-r--r-- | accessible/tests/browser/tree/browser_shadowdom.js | 64 | ||||
-rw-r--r-- | accessible/tests/browser/tree/head.js | 34 |
5 files changed, 439 insertions, 0 deletions
diff --git a/accessible/tests/browser/tree/browser.ini b/accessible/tests/browser/tree/browser.ini new file mode 100644 index 0000000000..8072f55c37 --- /dev/null +++ b/accessible/tests/browser/tree/browser.ini @@ -0,0 +1,11 @@ +[DEFAULT] +support-files = + head.js + !/accessible/tests/browser/shared-head.js + !/accessible/tests/mochitest/*.js + !/accessible/tests/browser/*.jsm + +[browser_aria_owns.js] +skip-if = true || (verify && !debug && (os == 'linux')) #Bug 1445513 +[browser_searchbar.js] +[browser_shadowdom.js] diff --git a/accessible/tests/browser/tree/browser_aria_owns.js b/accessible/tests/browser/tree/browser_aria_owns.js new file mode 100644 index 0000000000..084ac83fea --- /dev/null +++ b/accessible/tests/browser/tree/browser_aria_owns.js @@ -0,0 +1,278 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +let NO_MOVE = { unexpected: [[EVENT_REORDER, "container"]] }; +let MOVE = { expected: [[EVENT_REORDER, "container"]] }; + +// Set last ordinal child as aria-owned, should produce no reorder. +addAccessibleTask( + `<ul id="container"><li id="a">Test</li></ul>`, + async function(browser, accDoc) { + let containerAcc = findAccessibleChildByID(accDoc, "container"); + + testChildrenIds(containerAcc, ["a"]); + + await contentSpawnMutation(browser, NO_MOVE, function() { + // aria-own ordinal child in place, should be a no-op. + content.document + .getElementById("container") + .setAttribute("aria-owns", "a"); + }); + + testChildrenIds(containerAcc, ["a"]); + } +); + +// Add a new ordinal child to a container with an aria-owned child. +// Order should respect aria-owns. +addAccessibleTask( + `<ul id="container"><li id="a">Test</li></ul>`, + async function(browser, accDoc) { + let containerAcc = findAccessibleChildByID(accDoc, "container"); + + testChildrenIds(containerAcc, ["a"]); + + await contentSpawnMutation(browser, MOVE, function() { + let container = content.document.getElementById("container"); + container.setAttribute("aria-owns", "a"); + + let aa = content.document.createElement("li"); + aa.id = "aa"; + container.appendChild(aa); + }); + + testChildrenIds(containerAcc, ["aa", "a"]); + + await contentSpawnMutation(browser, MOVE, function() { + content.document.getElementById("container").removeAttribute("aria-owns"); + }); + + testChildrenIds(containerAcc, ["a", "aa"]); + } +); + +// Remove a no-move aria-owns attribute, should result in a no-move. +addAccessibleTask( + `<ul id="container" aria-owns="a"><li id="a">Test</li></ul>`, + async function(browser, accDoc) { + let containerAcc = findAccessibleChildByID(accDoc, "container"); + + testChildrenIds(containerAcc, ["a"]); + + await contentSpawnMutation(browser, NO_MOVE, function() { + // remove aria-owned child that is already ordinal, should be no-op. + content.document.getElementById("container").removeAttribute("aria-owns"); + }); + + testChildrenIds(containerAcc, ["a"]); + } +); + +// Attempt to steal an aria-owned child. The attempt should fail. +addAccessibleTask( + ` + <ul> + <li id="a">Test</li> + </ul> + <ul aria-owns="a"></ul> + <ul id="container"></ul>`, + async function(browser, accDoc) { + let containerAcc = findAccessibleChildByID(accDoc, "container"); + + testChildrenIds(containerAcc, []); + + await contentSpawnMutation(browser, NO_MOVE, function() { + content.document + .getElementById("container") + .setAttribute("aria-owns", "a"); + }); + + testChildrenIds(containerAcc, []); + } +); + +// Don't aria-own children of <select> +addAccessibleTask( + ` + <div id="container" role="group" aria-owns="b"></div> + <select id="select"> + <option id="a"></option> + <option id="b"></option> + </select>`, + async function(browser, accDoc) { + let containerAcc = findAccessibleChildByID(accDoc, "container"); + let selectAcc = findAccessibleChildByID(accDoc, "select"); + + testChildrenIds(containerAcc, []); + testChildrenIds(selectAcc.firstChild, ["a", "b"]); + } +); + +// Don't allow <select> to aria-own +addAccessibleTask( + ` + <div id="container" role="group"> + <div id="a"></div> + <div id="b"></div> + </div> + <select id="select" aria-owns="a"> + <option id="c"></option> + </select>`, + async function(browser, accDoc) { + let containerAcc = findAccessibleChildByID(accDoc, "container"); + let selectAcc = findAccessibleChildByID(accDoc, "select"); + + testChildrenIds(containerAcc, ["a", "b"]); + testChildrenIds(selectAcc.firstChild, ["c"]); + } +); + +// Don't allow one <select> to aria-own an <option> from another <select>. +addAccessibleTask( + ` + <select id="select1" aria-owns="c"> + <option id="a"></option> + <option id="b"></option> + </select> + <select id="select2"> + <option id="c"></option> + </select>`, + async function(browser, accDoc) { + let selectAcc1 = findAccessibleChildByID(accDoc, "select1"); + let selectAcc2 = findAccessibleChildByID(accDoc, "select2"); + + testChildrenIds(selectAcc1.firstChild, ["a", "b"]); + testChildrenIds(selectAcc2.firstChild, ["c"]); + } +); + +// Don't allow a <select> to reorder its children with aria-owns. +addAccessibleTask( + ` + <select id="container" aria-owns="c b a"> + <option id="a"></option> + <option id="b"></option> + <option id="c"></option> + </select>`, + async function(browser, accDoc) { + let containerAcc = findAccessibleChildByID(accDoc, "container"); + + testChildrenIds(containerAcc.firstChild, ["a", "b", "c"]); + + await contentSpawnMutation(browser, NO_MOVE, function() { + content.document + .getElementById("container") + .setAttribute("aria-owns", "a c b"); + }); + + testChildrenIds(containerAcc.firstChild, ["a", "b", "c"]); + } +); + +// Don't crash if ID in aria-owns does not exist +addAccessibleTask( + ` + <select id="container" aria-owns="boom" multiple></select>`, + async function(browser, accDoc) { + ok(true, "Did not crash"); + } +); + +addAccessibleTask( + ` + <ul id="one"> + <li id="a">Test</li> + <li id="b">Test 2</li> + <li id="c">Test 3</li> + </ul> + <ul id="two"></ul>`, + async function(browser, accDoc) { + let one = findAccessibleChildByID(accDoc, "one"); + let two = findAccessibleChildByID(accDoc, "two"); + + let waitfor = { + expected: [ + [EVENT_REORDER, "one"], + [EVENT_REORDER, "two"], + ], + }; + + await contentSpawnMutation(browser, waitfor, function() { + // Put same id twice in aria-owns + content.document.getElementById("two").setAttribute("aria-owns", "a a"); + }); + + testChildrenIds(one, ["b", "c"]); + testChildrenIds(two, ["a"]); + + await contentSpawnMutation(browser, waitfor, function() { + // If the previous double-id aria-owns worked correctly, we should + // be in a good state and all is fine.. + content.document.getElementById("two").setAttribute("aria-owns", "a b"); + }); + + testChildrenIds(one, ["c"]); + testChildrenIds(two, ["a", "b"]); + } +); + +addAccessibleTask(`<div id="a"></div><div id="b"></div>`, async function( + browser, + accDoc +) { + testChildrenIds(accDoc, ["a", "b"]); + + let waitFor = { + expected: [[EVENT_REORDER, e => e.accessible == accDoc]], + }; + + await contentSpawnMutation(browser, waitFor, function() { + content.document.documentElement.style.display = "none"; + content.document.documentElement.getBoundingClientRect(); + content.document.body.setAttribute("aria-owns", "b a"); + content.document.documentElement.remove(); + }); + + testChildrenIds(accDoc, []); +}); + +// Don't allow ordinal child to be placed after aria-owned child (bug 1405796) +addAccessibleTask( + `<div id="container"><div id="a">Hello</div></div> + <div><div id="c">There</div><div id="d">There</div></div>`, + async function(browser, accDoc) { + let containerAcc = findAccessibleChildByID(accDoc, "container"); + + testChildrenIds(containerAcc, ["a"]); + + await contentSpawnMutation(browser, MOVE, function() { + content.document + .getElementById("container") + .setAttribute("aria-owns", "c"); + }); + + testChildrenIds(containerAcc, ["a", "c"]); + + await contentSpawnMutation(browser, MOVE, function() { + let span = content.document.createElement("span"); + content.document.getElementById("container").appendChild(span); + + let b = content.document.createElement("div"); + b.id = "b"; + content.document.getElementById("container").appendChild(b); + }); + + testChildrenIds(containerAcc, ["a", "b", "c"]); + + await contentSpawnMutation(browser, MOVE, function() { + content.document + .getElementById("container") + .setAttribute("aria-owns", "c d"); + }); + + testChildrenIds(containerAcc, ["a", "b", "c", "d"]); + } +); diff --git a/accessible/tests/browser/tree/browser_searchbar.js b/accessible/tests/browser/tree/browser_searchbar.js new file mode 100644 index 0000000000..e41ba9819d --- /dev/null +++ b/accessible/tests/browser/tree/browser_searchbar.js @@ -0,0 +1,52 @@ +"use strict"; + +/* import-globals-from ../../mochitest/role.js */ +loadScripts({ name: "role.js", dir: MOCHITESTS_DIR }); + +// eslint-disable-next-line camelcase +add_task(async function test_searchbar_a11y_tree() { + await SpecialPowers.pushPrefEnv({ + set: [["browser.search.widget.inNavBar", true]], + }); + + let searchbar = await TestUtils.waitForCondition( + () => document.getElementById("searchbar"), + "wait for search bar to appear" + ); + + // Make sure the popup has been rendered so it shows up in the a11y tree. + let popup = document.getElementById("PopupSearchAutoComplete"); + let promise = BrowserTestUtils.waitForEvent(popup, "popupshown", false); + searchbar.textbox.openPopup(); + await promise; + + promise = BrowserTestUtils.waitForEvent(popup, "popuphidden", false); + searchbar.textbox.closePopup(); + await promise; + + const TREE = { + role: ROLE_EDITCOMBOBOX, + + children: [ + // input element + { + role: ROLE_ENTRY, + children: [], + }, + + // context menu + { + role: ROLE_COMBOBOX_LIST, + children: [], + }, + + // result list + { + role: ROLE_GROUPING, + // not testing the structure inside the result list + }, + ], + }; + + testAccessibleTree(searchbar, TREE); +}); diff --git a/accessible/tests/browser/tree/browser_shadowdom.js b/accessible/tests/browser/tree/browser_shadowdom.js new file mode 100644 index 0000000000..728284d3e2 --- /dev/null +++ b/accessible/tests/browser/tree/browser_shadowdom.js @@ -0,0 +1,64 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const REORDER = { expected: [[EVENT_REORDER, "container"]] }; + +// Dynamically inserted slotted accessible elements should be in +// the accessible tree. +const snippet = ` +<script> +customElements.define("x-el", class extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: "open" }); + this.shadowRoot.innerHTML = + "<div role='presentation'><slot></slot></div>"; + } +}); +</script> +<x-el id="container" role="group"><label id="l1">label1</label></x-el> +`; + +addAccessibleTask(snippet, async function(browser, accDoc) { + let container = findAccessibleChildByID(accDoc, "container"); + + testChildrenIds(container, ["l1"]); + + await contentSpawnMutation(browser, REORDER, function() { + let labelEl = content.document.createElement("label"); + labelEl.id = "l2"; + + let containerEl = content.document.getElementById("container"); + containerEl.appendChild(labelEl); + }); + + testChildrenIds(container, ["l1", "l2"]); +}); + +// Dynamically inserted not accessible custom element containing an accessible +// in its shadow DOM. +const snippet2 = ` +<script> +customElements.define("x-el2", class extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: "open" }); + this.shadowRoot.innerHTML = "<input id='input'>"; + } +}); +</script> +<div role="group" id="container"></div> +`; + +addAccessibleTask(snippet2, async function(browser, accDoc) { + let container = findAccessibleChildByID(accDoc, "container"); + + await contentSpawnMutation(browser, REORDER, function() { + content.document.getElementById("container").innerHTML = "<x-el2></x-el2>"; + }); + + testChildrenIds(container, ["input"]); +}); diff --git a/accessible/tests/browser/tree/head.js b/accessible/tests/browser/tree/head.js new file mode 100644 index 0000000000..867a1b1417 --- /dev/null +++ b/accessible/tests/browser/tree/head.js @@ -0,0 +1,34 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* exported testChildrenIds */ + +// Load the shared-head file first. +/* import-globals-from ../shared-head.js */ +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js", + this +); + +// Loading and common.js from accessible/tests/mochitest/ for all tests, as +// well as promisified-events.js. +loadScripts( + { name: "common.js", dir: MOCHITESTS_DIR }, + { name: "promisified-events.js", dir: MOCHITESTS_DIR } +); + +/* + * A test function for comparing the IDs of an accessible's children + * with an expected array of IDs. + */ +function testChildrenIds(acc, expectedIds) { + let ids = arrayFromChildren(acc).map(child => getAccessibleDOMNodeID(child)); + Assert.deepEqual( + ids, + expectedIds, + `Children for ${getAccessibleDOMNodeID(acc)} are wrong.` + ); +} |