122 lines
3.2 KiB
JavaScript
122 lines
3.2 KiB
JavaScript
/* 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 HeadersTraversalRule, ObjectTraversalRule, testPivotSequence, testFailsWithNotInTree */
|
|
|
|
// Load the shared-head file first.
|
|
Services.scriptloader.loadSubScript(
|
|
"chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js",
|
|
this
|
|
);
|
|
|
|
/* import-globals-from ../../mochitest/layout.js */
|
|
/* import-globals-from ../../mochitest/role.js */
|
|
/* import-globals-from ../../mochitest/states.js */
|
|
loadScripts(
|
|
{ name: "common.js", dir: MOCHITESTS_DIR },
|
|
{ name: "promisified-events.js", dir: MOCHITESTS_DIR },
|
|
{ name: "states.js", dir: MOCHITESTS_DIR },
|
|
{ name: "role.js", dir: MOCHITESTS_DIR },
|
|
{ name: "layout.js", dir: MOCHITESTS_DIR }
|
|
);
|
|
|
|
const FILTER_MATCH = nsIAccessibleTraversalRule.FILTER_MATCH;
|
|
const FILTER_IGNORE = nsIAccessibleTraversalRule.FILTER_IGNORE;
|
|
const FILTER_IGNORE_SUBTREE = nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
|
|
|
|
const NS_ERROR_NOT_IN_TREE = 0x80780026;
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// Traversal rules
|
|
|
|
/**
|
|
* Rule object to traverse all focusable nodes and text nodes.
|
|
*/
|
|
const HeadersTraversalRule = {
|
|
match(acc) {
|
|
return acc.role == ROLE_HEADING ? FILTER_MATCH : FILTER_IGNORE;
|
|
},
|
|
|
|
QueryInterface: ChromeUtils.generateQI([nsIAccessibleTraversalRule]),
|
|
};
|
|
|
|
/**
|
|
* Traversal rule for all focusable nodes or leafs.
|
|
*/
|
|
const ObjectTraversalRule = {
|
|
match(acc) {
|
|
let [state, extstate] = getStates(acc);
|
|
if (state & STATE_INVISIBLE) {
|
|
return FILTER_IGNORE;
|
|
}
|
|
|
|
if ((extstate & EXT_STATE_OPAQUE) == 0) {
|
|
return FILTER_IGNORE | FILTER_IGNORE_SUBTREE;
|
|
}
|
|
|
|
let rv = FILTER_IGNORE;
|
|
let role = acc.role;
|
|
if (
|
|
hasState(acc, STATE_FOCUSABLE) &&
|
|
role != ROLE_DOCUMENT &&
|
|
role != ROLE_INTERNAL_FRAME
|
|
) {
|
|
rv = FILTER_IGNORE_SUBTREE | FILTER_MATCH;
|
|
} else if (
|
|
acc.childCount == 0 &&
|
|
role != ROLE_LISTITEM_MARKER &&
|
|
acc.name.trim()
|
|
) {
|
|
rv = FILTER_MATCH;
|
|
}
|
|
|
|
return rv;
|
|
},
|
|
|
|
QueryInterface: ChromeUtils.generateQI([nsIAccessibleTraversalRule]),
|
|
};
|
|
|
|
function getIdOrName(acc) {
|
|
let id = getAccessibleDOMNodeID(acc);
|
|
if (id) {
|
|
return id;
|
|
}
|
|
return acc.name;
|
|
}
|
|
|
|
function* pivotNextGenerator(pivot, rule) {
|
|
for (let acc = pivot.first(rule); acc; acc = pivot.next(acc, rule)) {
|
|
yield acc;
|
|
}
|
|
}
|
|
|
|
function* pivotPreviousGenerator(pivot, rule) {
|
|
for (let acc = pivot.last(rule); acc; acc = pivot.prev(acc, rule)) {
|
|
yield acc;
|
|
}
|
|
}
|
|
|
|
function testPivotSequence(pivot, rule, expectedSequence) {
|
|
is(
|
|
JSON.stringify([...pivotNextGenerator(pivot, rule)].map(getIdOrName)),
|
|
JSON.stringify(expectedSequence),
|
|
"Forward pivot sequence is correct"
|
|
);
|
|
is(
|
|
JSON.stringify([...pivotPreviousGenerator(pivot, rule)].map(getIdOrName)),
|
|
JSON.stringify([...expectedSequence].reverse()),
|
|
"Reverse pivot sequence is correct"
|
|
);
|
|
}
|
|
|
|
function testFailsWithNotInTree(func, msg) {
|
|
try {
|
|
func();
|
|
ok(false, msg);
|
|
} catch (x) {
|
|
is(x.result, NS_ERROR_NOT_IN_TREE, `Expecting NOT_IN_TREE: ${msg}`);
|
|
}
|
|
}
|