summaryrefslogtreecommitdiffstats
path: root/accessible/tests/browser/tree
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /accessible/tests/browser/tree
parentInitial commit. (diff)
downloadfirefox-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.ini11
-rw-r--r--accessible/tests/browser/tree/browser_aria_owns.js278
-rw-r--r--accessible/tests/browser/tree/browser_searchbar.js52
-rw-r--r--accessible/tests/browser/tree/browser_shadowdom.js64
-rw-r--r--accessible/tests/browser/tree/head.js34
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.`
+ );
+}