Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* 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 () {
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"]);
}
);