mirror of
https://github.com/google/blockly.git
synced 2026-01-04 15:40:08 +01:00
* Revert "fix: Auto-close widget divs on lost focus (#9216)" This reverts commitbea183d85d. * Revert "fix: Auto close drop-down divs on lost focus (reapply) (#9213)" This reverts commit0e16b0405a.
5980 lines
234 KiB
JavaScript
5980 lines
234 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import {
|
|
FocusManager,
|
|
getFocusManager,
|
|
} from '../../build/src/core/focus_manager.js';
|
|
import {assert} from '../../node_modules/chai/chai.js';
|
|
import {
|
|
sharedTestSetup,
|
|
sharedTestTeardown,
|
|
} from './test_helpers/setup_teardown.js';
|
|
|
|
class FocusableNodeImpl {
|
|
constructor(element, tree) {
|
|
this.element = element;
|
|
this.tree = tree;
|
|
}
|
|
|
|
getFocusableElement() {
|
|
return this.element;
|
|
}
|
|
|
|
getFocusableTree() {
|
|
return this.tree;
|
|
}
|
|
|
|
onNodeFocus() {}
|
|
|
|
onNodeBlur() {}
|
|
|
|
canBeFocused() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
class FocusableTreeImpl {
|
|
constructor(rootElement, nestedTrees) {
|
|
this.nestedTrees = nestedTrees;
|
|
this.idToNodeMap = {};
|
|
this.rootNode = this.addNode(rootElement);
|
|
this.fallbackNode = null;
|
|
}
|
|
|
|
addNode(element) {
|
|
const node = new FocusableNodeImpl(element, this);
|
|
this.idToNodeMap[element.id] = node;
|
|
return node;
|
|
}
|
|
|
|
removeNode(node) {
|
|
delete this.idToNodeMap[node.getFocusableElement().id];
|
|
}
|
|
|
|
getRootFocusableNode() {
|
|
return this.rootNode;
|
|
}
|
|
|
|
getRestoredFocusableNode() {
|
|
return this.fallbackNode;
|
|
}
|
|
|
|
getNestedTrees() {
|
|
return this.nestedTrees;
|
|
}
|
|
|
|
lookUpFocusableNode(id) {
|
|
return this.idToNodeMap[id];
|
|
}
|
|
|
|
onTreeFocus() {}
|
|
|
|
onTreeBlur() {}
|
|
}
|
|
|
|
suite('FocusManager', function () {
|
|
const ACTIVE_FOCUS_NODE_CSS_SELECTOR = `.${FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME}`;
|
|
const PASSIVE_FOCUS_NODE_CSS_SELECTOR = `.${FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME}`;
|
|
|
|
setup(function () {
|
|
sharedTestSetup.call(this);
|
|
this.focusManager = getFocusManager();
|
|
|
|
this.allFocusableTrees = [];
|
|
this.allFocusableNodes = [];
|
|
this.createFocusableTree = function (rootElementId, nestedTrees) {
|
|
const tree = new FocusableTreeImpl(
|
|
document.getElementById(rootElementId),
|
|
nestedTrees || [],
|
|
);
|
|
this.allFocusableTrees.push(tree);
|
|
return tree;
|
|
};
|
|
this.createFocusableNode = function (tree, elementId) {
|
|
const node = tree.addNode(document.getElementById(elementId));
|
|
this.allFocusableNodes.push(node);
|
|
return node;
|
|
};
|
|
|
|
this.testFocusableTree1 = this.createFocusableTree('testFocusableTree1');
|
|
this.testFocusableTree1Node1 = this.createFocusableNode(
|
|
this.testFocusableTree1,
|
|
'testFocusableTree1.node1',
|
|
);
|
|
this.testFocusableTree1Node1Child1 = this.createFocusableNode(
|
|
this.testFocusableTree1,
|
|
'testFocusableTree1.node1.child1',
|
|
);
|
|
this.testFocusableTree1Node2 = this.createFocusableNode(
|
|
this.testFocusableTree1,
|
|
'testFocusableTree1.node2',
|
|
);
|
|
this.testFocusableNestedTree4 = this.createFocusableTree(
|
|
'testFocusableNestedTree4',
|
|
);
|
|
this.testFocusableNestedTree4Node1 = this.createFocusableNode(
|
|
this.testFocusableNestedTree4,
|
|
'testFocusableNestedTree4.node1',
|
|
);
|
|
this.testFocusableNestedTree5 = this.createFocusableTree(
|
|
'testFocusableNestedTree5',
|
|
);
|
|
this.testFocusableNestedTree5Node1 = this.createFocusableNode(
|
|
this.testFocusableNestedTree5,
|
|
'testFocusableNestedTree5.node1',
|
|
);
|
|
this.testFocusableTree2 = this.createFocusableTree('testFocusableTree2', [
|
|
this.testFocusableNestedTree4,
|
|
this.testFocusableNestedTree5,
|
|
]);
|
|
this.testFocusableTree2Node1 = this.createFocusableNode(
|
|
this.testFocusableTree2,
|
|
'testFocusableTree2.node1',
|
|
);
|
|
|
|
this.testFocusableGroup1 = this.createFocusableTree('testFocusableGroup1');
|
|
this.testFocusableGroup1Node1 = this.createFocusableNode(
|
|
this.testFocusableGroup1,
|
|
'testFocusableGroup1.node1',
|
|
);
|
|
this.testFocusableGroup1Node1Child1 = this.createFocusableNode(
|
|
this.testFocusableGroup1,
|
|
'testFocusableGroup1.node1.child1',
|
|
);
|
|
this.testFocusableGroup1Node2 = this.createFocusableNode(
|
|
this.testFocusableGroup1,
|
|
'testFocusableGroup1.node2',
|
|
);
|
|
this.testFocusableNestedGroup4 = this.createFocusableTree(
|
|
'testFocusableNestedGroup4',
|
|
);
|
|
this.testFocusableNestedGroup4Node1 = this.createFocusableNode(
|
|
this.testFocusableNestedGroup4,
|
|
'testFocusableNestedGroup4.node1',
|
|
);
|
|
this.testFocusableGroup2 = this.createFocusableTree('testFocusableGroup2', [
|
|
this.testFocusableNestedGroup4,
|
|
]);
|
|
this.testFocusableGroup2Node1 = this.createFocusableNode(
|
|
this.testFocusableGroup2,
|
|
'testFocusableGroup2.node1',
|
|
);
|
|
});
|
|
|
|
teardown(function () {
|
|
sharedTestTeardown.call(this);
|
|
|
|
// Ensure all node CSS styles are reset so that state isn't leaked between tests.
|
|
const activeElems = document.querySelectorAll(
|
|
ACTIVE_FOCUS_NODE_CSS_SELECTOR,
|
|
);
|
|
const passiveElems = document.querySelectorAll(
|
|
PASSIVE_FOCUS_NODE_CSS_SELECTOR,
|
|
);
|
|
for (const elem of activeElems) {
|
|
elem.classList.remove(FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME);
|
|
}
|
|
for (const elem of passiveElems) {
|
|
elem.classList.remove(FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME);
|
|
}
|
|
|
|
// Ensure any set tab indexes are properly reset between tests.
|
|
for (const tree of this.allFocusableTrees) {
|
|
tree
|
|
.getRootFocusableNode()
|
|
.getFocusableElement()
|
|
.removeAttribute('tabindex');
|
|
}
|
|
for (const node of this.allFocusableNodes) {
|
|
node.getFocusableElement().removeAttribute('tabindex');
|
|
}
|
|
this.allFocusableTrees = [];
|
|
this.allFocusableNodes = [];
|
|
|
|
// Reset the current active element.
|
|
document.body.focus();
|
|
});
|
|
|
|
assert.includesClass = function (classList, className) {
|
|
assert.isTrue(
|
|
classList.contains(className),
|
|
'Expected class list to include: ' + className,
|
|
);
|
|
};
|
|
|
|
assert.notIncludesClass = function (classList, className) {
|
|
assert.isFalse(
|
|
classList.contains(className),
|
|
'Expected class list to not include: ' + className,
|
|
);
|
|
};
|
|
|
|
/* Basic lifecycle tests. */
|
|
|
|
suite('registerTree()', function () {
|
|
test('once does not throw', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
// The test should pass due to no exception being thrown.
|
|
});
|
|
|
|
test('twice for same tree throws error', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
const errorMsgRegex =
|
|
/Attempted to re-register already registered tree.+?/;
|
|
assert.throws(
|
|
() => this.focusManager.registerTree(this.testFocusableTree1),
|
|
errorMsgRegex,
|
|
);
|
|
});
|
|
|
|
test('twice with different trees does not throw', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
// The test shouldn't throw since two different trees were registered.
|
|
});
|
|
|
|
test('register after an unregister does not throw', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
// The second register should not fail since the tree was previously unregistered.
|
|
});
|
|
|
|
test('for tree with missing ID throws error', function () {
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
const oldId = rootElem.id;
|
|
rootElem.removeAttribute('id');
|
|
|
|
const errorMsgRegex =
|
|
/Attempting to register a tree with a root element that has an invalid ID.+?/;
|
|
assert.throws(
|
|
() => this.focusManager.registerTree(this.testFocusableTree1),
|
|
errorMsgRegex,
|
|
);
|
|
// Restore the ID for other tests.
|
|
rootElem.id = oldId;
|
|
});
|
|
|
|
test('for tree with null ID throws error', function () {
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
const oldId = rootElem.id;
|
|
rootElem.setAttribute('id', null);
|
|
|
|
const errorMsgRegex =
|
|
/Attempting to register a tree with a root element that has an invalid ID.+?/;
|
|
assert.throws(
|
|
() => this.focusManager.registerTree(this.testFocusableTree1),
|
|
errorMsgRegex,
|
|
);
|
|
// Restore the ID for other tests.
|
|
rootElem.id = oldId;
|
|
});
|
|
|
|
test('for tree with empty throws error', function () {
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
const oldId = rootElem.id;
|
|
rootElem.setAttribute('id', '');
|
|
|
|
const errorMsgRegex =
|
|
/Attempting to register a tree with a root element that has an invalid ID.+?/;
|
|
assert.throws(
|
|
() => this.focusManager.registerTree(this.testFocusableTree1),
|
|
errorMsgRegex,
|
|
);
|
|
// Restore the ID for other tests.
|
|
rootElem.id = oldId;
|
|
});
|
|
|
|
test('for unmanaged tree does not overwrite tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, false);
|
|
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.isNull(rootElem.getAttribute('tabindex'));
|
|
});
|
|
|
|
test('for unmanaged tree with custom tab index does not overwrite tab index', function () {
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
rootElem.tabIndex = -1;
|
|
|
|
this.focusManager.registerTree(this.testFocusableTree1, false);
|
|
|
|
// The custom tab index shouldn't be overwritten for an unmanaged tree.
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('for managed tree overwrites root tab index to be tab navigable', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '0');
|
|
});
|
|
|
|
test('for managed tree with custom tab index overwrites root tab index to be tab navigable', function () {
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
rootElem.tabIndex = -1;
|
|
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
|
|
// A custom tab index should be overwritten for a managed tree.
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '0');
|
|
});
|
|
});
|
|
|
|
suite('unregisterTree()', function () {
|
|
test('for not yet registered tree throws', function () {
|
|
const errorMsgRegex = /Attempted to unregister not registered tree.+?/;
|
|
assert.throws(
|
|
() => this.focusManager.unregisterTree(this.testFocusableTree1),
|
|
errorMsgRegex,
|
|
);
|
|
});
|
|
|
|
test('for registered tree does not throw', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Unregistering a registered tree should not fail.
|
|
});
|
|
|
|
test('twice for registered tree throws', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
const errorMsgRegex = /Attempted to unregister not registered tree.+?/;
|
|
assert.throws(
|
|
() => this.focusManager.unregisterTree(this.testFocusableTree1),
|
|
errorMsgRegex,
|
|
);
|
|
});
|
|
|
|
test('for unmanaged tree with custom tab index does not change tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, false);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
rootElem.tabIndex = -1;
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Unregistering an unmanaged tree shouldn't change its tab index.
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('for managed tree removes tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Unregistering a managed tree should remove its tab index.
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.isNull(rootElem.getAttribute('tabindex'));
|
|
});
|
|
|
|
test('for managed tree with custom tab index removes tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
rootElem.tabIndex = -1;
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Unregistering a managed tree should remove its tab index.
|
|
assert.isNull(rootElem.getAttribute('tabindex'));
|
|
});
|
|
});
|
|
|
|
suite('isRegistered()', function () {
|
|
test('for not registered tree returns false', function () {
|
|
const isRegistered = this.focusManager.isRegistered(
|
|
this.testFocusableTree1,
|
|
);
|
|
|
|
assert.isFalse(isRegistered);
|
|
});
|
|
|
|
test('for registered tree returns true', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
const isRegistered = this.focusManager.isRegistered(
|
|
this.testFocusableTree1,
|
|
);
|
|
|
|
assert.isTrue(isRegistered);
|
|
});
|
|
|
|
test('for unregistered tree returns false', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
const isRegistered = this.focusManager.isRegistered(
|
|
this.testFocusableTree1,
|
|
);
|
|
|
|
assert.isFalse(isRegistered);
|
|
});
|
|
|
|
test('for re-registered tree returns true', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
const isRegistered = this.focusManager.isRegistered(
|
|
this.testFocusableTree1,
|
|
);
|
|
|
|
assert.isTrue(isRegistered);
|
|
});
|
|
|
|
test('for unregistered tree with other registered tree returns false', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
const isRegistered = this.focusManager.isRegistered(
|
|
this.testFocusableTree1,
|
|
);
|
|
|
|
assert.isFalse(isRegistered);
|
|
});
|
|
});
|
|
|
|
suite('getFocusedTree()', function () {
|
|
test('by default returns null', function () {
|
|
const focusedTree = this.focusManager.getFocusedTree();
|
|
|
|
assert.isNull(focusedTree);
|
|
});
|
|
});
|
|
|
|
suite('getFocusedNode()', function () {
|
|
test('by default returns null', function () {
|
|
const focusedNode = this.focusManager.getFocusedNode();
|
|
|
|
assert.isNull(focusedNode);
|
|
});
|
|
|
|
test('after focusing unfocusable node returns null', function () {
|
|
this.testFocusableTree1Node1.canBeFocused = () => false;
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
const focusedNode = this.focusManager.getFocusedNode();
|
|
|
|
// Unfocusable nodes should not be focused.
|
|
assert.isNull(focusedNode);
|
|
});
|
|
});
|
|
|
|
suite('focusTree()', function () {
|
|
test('for not registered tree throws', function () {
|
|
const errorMsgRegex = /Attempted to focus unregistered tree.+?/;
|
|
assert.throws(
|
|
() => this.focusManager.focusTree(this.testFocusableTree1),
|
|
errorMsgRegex,
|
|
);
|
|
});
|
|
|
|
test('for unregistered tree throws', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
const errorMsgRegex = /Attempted to focus unregistered tree.+?/;
|
|
assert.throws(
|
|
() => this.focusManager.focusTree(this.testFocusableTree1),
|
|
errorMsgRegex,
|
|
);
|
|
});
|
|
});
|
|
|
|
test('unfocused node does not have a tab index by default', function () {
|
|
const elem = this.testFocusableTree1Node1.getFocusableElement();
|
|
|
|
// This is slightly testing the test setup, but it acts as a precondition sanity test for the
|
|
// other tab index tests below. Important: 'getAttribute' is used here since direct access to
|
|
// 'tabIndex' can default the value returned even when the tab index isn't set.
|
|
assert.isNull(elem.getAttribute('tabindex'));
|
|
});
|
|
|
|
suite('focusNode()', function () {
|
|
test('for not registered node throws', function () {
|
|
const errorMsgRegex = /Attempted to focus unregistered node.+?/;
|
|
assert.throws(
|
|
() => this.focusManager.focusNode(this.testFocusableTree1Node1),
|
|
errorMsgRegex,
|
|
);
|
|
});
|
|
|
|
test('for unregistered node throws', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
const errorMsgRegex = /Attempted to focus unregistered node.+?/;
|
|
assert.throws(
|
|
() => this.focusManager.focusNode(this.testFocusableTree1Node1),
|
|
errorMsgRegex,
|
|
);
|
|
});
|
|
|
|
test('focuses element', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
const nodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.strictEqual(document.activeElement, nodeElem);
|
|
});
|
|
|
|
test('fires focusin event', function () {
|
|
let focusCount = 0;
|
|
const focusListener = () => focusCount++;
|
|
document.addEventListener('focusin', focusListener);
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
document.removeEventListener('focusin', focusListener);
|
|
|
|
// There should be exactly 1 focus event fired from focusNode().
|
|
assert.strictEqual(focusCount, 1);
|
|
});
|
|
|
|
test('for orphaned node returns tree root by default', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.testFocusableTree1.removeNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
// Focusing an invalid node should fall back to the tree root when it has no restoration
|
|
// fallback node.
|
|
const currentNode = this.focusManager.getFocusedNode();
|
|
const treeRoot = this.testFocusableTree1.getRootFocusableNode();
|
|
assert.strictEqual(currentNode, treeRoot);
|
|
});
|
|
|
|
test('for orphaned node returns specified fallback node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.testFocusableTree1.fallbackNode = this.testFocusableTree1Node2;
|
|
this.testFocusableTree1.removeNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
// Focusing an invalid node should fall back to the restored fallback.
|
|
const currentNode = this.focusManager.getFocusedNode();
|
|
assert.strictEqual(currentNode, this.testFocusableTree1Node2);
|
|
});
|
|
|
|
test('restores focus when element quietly loses focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
// Remove the FocusManager's listeners to simulate not receiving a focus
|
|
// event when focus is lost. This can happen in Firefox and Safari when an
|
|
// element is removed and then re-added to the DOM. This is a contrived
|
|
// setup to achieve the same outcome on all browsers. For context, see:
|
|
// https://github.com/google/blockly-keyboard-experimentation/issues/87.
|
|
for (const registeredListener of this.globalDocumentEventListeners) {
|
|
const eventType = registeredListener.type;
|
|
const eventListener = registeredListener.listener;
|
|
document.removeEventListener(eventType, eventListener);
|
|
}
|
|
document.body.focus();
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
const currentNode = this.focusManager.getFocusedNode();
|
|
const currentElem = currentNode?.getFocusableElement();
|
|
assert.strictEqual(currentNode, this.testFocusableTree1Node1);
|
|
assert.strictEqual(document.activeElement, currentElem);
|
|
});
|
|
|
|
test('restores focus when element and new node focused', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
// Remove the FocusManager's listeners to simulate not receiving a focus
|
|
// event when focus is lost. This can happen in Firefox and Safari when an
|
|
// element is removed and then re-added to the DOM. This is a contrived
|
|
// setup to achieve the same outcome on all browsers. For context, see:
|
|
// https://github.com/google/blockly-keyboard-experimentation/issues/87.
|
|
for (const registeredListener of this.globalDocumentEventListeners) {
|
|
const eventType = registeredListener.type;
|
|
const eventListener = registeredListener.listener;
|
|
document.removeEventListener(eventType, eventListener);
|
|
}
|
|
document.body.focus();
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node2);
|
|
|
|
const currentNode = this.focusManager.getFocusedNode();
|
|
const currentElem = currentNode?.getFocusableElement();
|
|
assert.strictEqual(currentNode, this.testFocusableTree1Node2);
|
|
assert.strictEqual(document.activeElement, currentElem);
|
|
});
|
|
|
|
test('for unfocused node calls onNodeFocus once', function () {
|
|
sinon.spy(this.testFocusableTree1Node1, 'onNodeFocus');
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
assert.strictEqual(this.testFocusableTree1Node1.onNodeFocus.callCount, 1);
|
|
});
|
|
|
|
test('for previously focused node calls onNodeBlur once', function () {
|
|
sinon.spy(this.testFocusableTree1Node1, 'onNodeBlur');
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node2);
|
|
|
|
assert.strictEqual(this.testFocusableTree1Node1.onNodeBlur.callCount, 1);
|
|
});
|
|
|
|
test('for unfocused tree calls onTreeFocus once', function () {
|
|
sinon.spy(this.testFocusableTree1, 'onTreeFocus');
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
assert.strictEqual(this.testFocusableTree1.onTreeFocus.callCount, 1);
|
|
});
|
|
|
|
test('for previously focused tree calls onTreeBlur once', function () {
|
|
sinon.spy(this.testFocusableTree1, 'onTreeBlur');
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
assert.strictEqual(this.testFocusableTree1.onTreeBlur.callCount, 1);
|
|
});
|
|
|
|
test('for same node twice calls onNodeFocus once', function () {
|
|
sinon.spy(this.testFocusableTree1Node1, 'onNodeFocus');
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
// Call focus for the same node a second time.
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
// Despite two calls to focus the node should only focus once.
|
|
assert.strictEqual(this.testFocusableTree1Node1.onNodeFocus.callCount, 1);
|
|
});
|
|
|
|
test('for unfocusable node does not call onNodeFocus', function () {
|
|
sinon.spy(this.testFocusableTree1Node1, 'onNodeFocus');
|
|
this.testFocusableTree1Node1.canBeFocused = () => false;
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
// Unfocusable nodes should not be focused, nor have their callbacks called.
|
|
assert.strictEqual(this.testFocusableTree1Node1.onNodeFocus.callCount, 0);
|
|
});
|
|
|
|
test('for unfocused node overwrites tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
// Focusing an element should overwrite its tab index.
|
|
const elem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.strictEqual(elem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('for previously focused node keeps new tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node2);
|
|
|
|
// The previously focused element should retain its tab index.
|
|
const elem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.strictEqual(elem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('for node with custom tab index does not change tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
const elem = this.testFocusableTree1Node1.getFocusableElement();
|
|
elem.tabIndex = 0;
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
// If the node already has a tab index set then it should retain that index.
|
|
assert.strictEqual(elem.getAttribute('tabindex'), '0');
|
|
});
|
|
|
|
suite('for unmanaged tree', function () {
|
|
test('focused root overwrites tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, false);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
|
|
this.focusManager.focusNode(rootNode);
|
|
|
|
// Focusing an unmanaged tree's root should overwrite its tab index.
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('focused root with custom tab index does not change tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, false);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
rootElem.tabIndex = 0;
|
|
|
|
this.focusManager.focusNode(rootNode);
|
|
|
|
// If the node already has a tab index set then it should retain that index.
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '0');
|
|
});
|
|
|
|
test('focused node in a tree after unmanaged was focused should keep previous root unchanged', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, false);
|
|
this.focusManager.registerTree(this.testFocusableTree2, false);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
// Focusing a different tree shouldn't change the root of the previous tree if it's unmanaged.
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.isNull(rootElem.getAttribute('tabindex'));
|
|
});
|
|
|
|
test('focused node in a tree after unmanaged was root focused should make previous root tab navigable', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, false);
|
|
this.focusManager.registerTree(this.testFocusableTree2, false);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
// The previous tree's root should be kept unchanged (since it was managed).
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '-1');
|
|
});
|
|
});
|
|
|
|
suite('for managed tree', function () {
|
|
test('for unfocused node in managed tree overwrites tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
// Focusing an element should overwrite its tab index.
|
|
const elem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.strictEqual(elem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('for previously focused node in managed tree keeps new tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node2);
|
|
|
|
// The previously focused element should retain its tab index.
|
|
const elem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.strictEqual(elem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('focused root makes root non-tab navigable', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
|
|
this.focusManager.focusNode(rootNode);
|
|
|
|
// Focusing the root in a managed tree should make it non-tab navigable.
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('focused root with custom tab index should overwrite tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
rootElem.tabIndex = 0;
|
|
|
|
this.focusManager.focusNode(rootNode);
|
|
|
|
// Custom tab indexes are overwritten for the root in a managed tree.
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('focused node tree root makes root non-tab navigable', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
// Focusing a node of a managed tree should make the root non-tab navigable.
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('focused node root with custom tab index should overwrite tab index', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
rootElem.tabIndex = 0;
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
// Custom tab indexes are overwritten for the root in a managed tree even when a tree's node
|
|
// is focused.
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '-1');
|
|
});
|
|
|
|
test('focused node in a tree after managed was focused should make previous root tab navigable', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
this.focusManager.registerTree(this.testFocusableTree2, false);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
// Focusing a different tree shouldn't after a managed tree should make the managed tree tab
|
|
// navigable.
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '0');
|
|
});
|
|
|
|
test('focused node in a tree after managed was root focused should make previous root tab navigable', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1, true);
|
|
this.focusManager.registerTree(this.testFocusableTree2, false);
|
|
const rootNode = this.testFocusableTree1.getRootFocusableNode();
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
// Focusing a different tree shouldn't after a managed tree should make the managed tree tab
|
|
// navigable.
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.strictEqual(rootElem.getAttribute('tabindex'), '0');
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('getFocusManager()', function () {
|
|
test('returns non-null manager', function () {
|
|
const manager = getFocusManager();
|
|
|
|
assert.isNotNull(manager);
|
|
});
|
|
|
|
test('returns the exact same instance in subsequent calls', function () {
|
|
const manager1 = getFocusManager();
|
|
const manager2 = getFocusManager();
|
|
|
|
assert.strictEqual(manager2, manager1);
|
|
});
|
|
});
|
|
|
|
/* Focus tests for HTML trees. */
|
|
|
|
suite('focus*() switching in HTML tree', function () {
|
|
suite('getFocusedTree()', function () {
|
|
test('registered tree focusTree()ed no prev focus returns tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed prev node focused returns tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree prev focused returns new tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree node prev focused returns new tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
});
|
|
|
|
test('registered root focusNode()ed no prev focus returns tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableTree1.getRootFocusableNode(),
|
|
);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test("registered node focusNode()ed no prev focus returns node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test("registered subnode focusNode()ed no prev focus returns node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1Child1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus returns same tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test("registered node focusNode()ed after prev node focus diff tree returns new node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
});
|
|
|
|
test("registered tree root focusNode()ed after prev node focus diff tree returns new node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableTree2.getRootFocusableNode(),
|
|
);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusTree()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node prior focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the more recent tree was removed, there's no tree currently focused.
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node recently focused returns new tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the most recent tree still exists, it still has focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
});
|
|
|
|
test('nested tree focusTree()ed with no prev focus returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
|
|
this.focusManager.focusTree(this.testFocusableNestedTree4);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedTree4,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed with no prev focus returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedTree4Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedTree4,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed after parent focused returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedTree4Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedTree4,
|
|
);
|
|
});
|
|
});
|
|
suite('getFocusedNode()', function () {
|
|
test('registered tree focusTree()ed no prev focus returns root node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed prev node focused returns original node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
// The original node retains focus since the tree already holds focus (per focusTree's
|
|
// contract).
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node1,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree prev focused returns new root node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree node prev focused returns new root node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('registered root focusNode()ed no prev focus returns root node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableTree1.getRootFocusableNode(),
|
|
);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed no prev focus returns node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node1,
|
|
);
|
|
});
|
|
|
|
test('registered subnode focusNode()ed no prev focus returns subnode', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1Child1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node1Child1,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node2,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus diff tree returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
});
|
|
|
|
test('registered tree root focusNode()ed after prev node focus diff tree returns new root', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableTree2.getRootFocusableNode(),
|
|
);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusTree()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node prior focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the more recent tree was removed, there's no tree currently focused.
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node recently focused returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the most recent tree still exists, it still has focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
});
|
|
|
|
test('nested tree focusTree()ed with no prev focus returns nested root', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
|
|
this.focusManager.focusTree(this.testFocusableNestedTree4);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedTree4.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed with no prev focus returns focused node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedTree4Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedTree4Node1,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed after parent focused returns focused node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedTree4Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedTree4Node1,
|
|
);
|
|
});
|
|
|
|
test('deletion after focusNode() returns null', function () {
|
|
const rootElem = document.createElement('div');
|
|
const nodeElem = document.createElement('div');
|
|
rootElem.setAttribute('id', 'focusRoot');
|
|
rootElem.setAttribute('tabindex', '-1');
|
|
nodeElem.setAttribute('id', 'focusNode');
|
|
nodeElem.setAttribute('tabindex', '-1');
|
|
nodeElem.textContent = 'Focusable node';
|
|
rootElem.appendChild(nodeElem);
|
|
document.body.appendChild(rootElem);
|
|
const root = this.createFocusableTree('focusRoot');
|
|
const node = this.createFocusableNode(root, 'focusNode');
|
|
this.focusManager.registerTree(root);
|
|
this.focusManager.focusNode(node);
|
|
|
|
node.getFocusableElement().remove();
|
|
|
|
assert.notStrictEqual(this.focusManager.getFocusedNode(), node);
|
|
rootElem.remove(); // Cleanup.
|
|
});
|
|
});
|
|
suite('CSS classes', function () {
|
|
test('registered tree focusTree()ed no prev focus root elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
const rootElem = this.testFocusableTree1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed prev node focused original elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
// The original node retains active focus since the tree already holds focus (per
|
|
// focusTree's contract).
|
|
const nodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree prev focused new root elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
const rootElem = this.testFocusableTree2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree node prev focused new root elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
const rootElem = this.testFocusableTree2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered root focusNode()ed no prev focus returns root elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableTree1.getRootFocusableNode(),
|
|
);
|
|
|
|
const rootElem = this.testFocusableTree1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed no prev focus node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
const nodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus same tree old node elem has no focus property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node2);
|
|
|
|
const prevNodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus same tree new node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node2);
|
|
|
|
const newNodeElem = this.testFocusableTree1Node2.getFocusableElement();
|
|
assert.includesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus diff tree old node elem has passive property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
const prevNodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus diff tree new node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
const newNodeElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree root focusNode()ed after prev node focus diff tree new root has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableTree2.getRootFocusableNode(),
|
|
);
|
|
|
|
const rootElem = this.testFocusableTree2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusTree()ed with no prev focus removes focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators.
|
|
const rootElem = this.testFocusableTree1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with no prev focus removes focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators.
|
|
const nodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node prior removes focus from removed tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators. However, the old node
|
|
// should still have passive indication.
|
|
const otherNodeElem =
|
|
this.testFocusableTree2Node1.getFocusableElement();
|
|
const removedNodeElem =
|
|
this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node recently removes focus from removed tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators. However, the new node
|
|
// should still have active indication.
|
|
const otherNodeElem =
|
|
this.testFocusableTree2Node1.getFocusableElement();
|
|
const removedNodeElem =
|
|
this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('focusNode() multiple nodes in same tree with switches ensure passive focus has gone', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node2);
|
|
|
|
// When switching back to the first tree, ensure the original passive node is no longer
|
|
// passive now that the new node is active.
|
|
const node1 = this.testFocusableTree1Node1.getFocusableElement();
|
|
const node2 = this.testFocusableTree1Node2.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
node1.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
node2.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed other tree node passively focused tree node now has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
|
|
// The original node in the tree should be moved from passive to active focus per the
|
|
// contract of focusTree). Also, the root of the tree should have no focus indication.
|
|
const nodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
const rootElem = this.testFocusableTree1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('focus on root, node in diff tree, then node in first tree; root should have focus gone', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
const nodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
const rootElem = this.testFocusableTree1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree focusTree()ed with no prev root has active focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
|
|
this.focusManager.focusTree(this.testFocusableNestedTree4);
|
|
|
|
const rootElem = this.testFocusableNestedTree4
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed with no prev focus node has active focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedTree4Node1);
|
|
|
|
const nodeElem =
|
|
this.testFocusableNestedTree4Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed after parent focused prev has passive node has active', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedTree4Node1);
|
|
|
|
const prevNodeElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
const currNodeElem =
|
|
this.testFocusableNestedTree4Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
currNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('DOM focus() switching in HTML tree', function () {
|
|
suite('getFocusedTree()', function () {
|
|
test('registered root focus()ed no prev focus returns tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableTree1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test("registered node focus()ed no prev focus returns node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test("registered subnode focus()ed no prev focus returns node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1.child1').tabIndex =
|
|
-1;
|
|
|
|
document.getElementById('testFocusableTree1.node1.child1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus returns same tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node2').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree1.node2').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test("registered node focus()ed after prev node focus diff tree returns new node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
});
|
|
|
|
test("registered tree root focus()ed after prev node focus diff tree returns new node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree2').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
});
|
|
|
|
test("non-registered node subelement focus()ed returns node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById(
|
|
'testFocusableTree1.node2.unregisteredChild1',
|
|
).tabIndex = -1;
|
|
|
|
document
|
|
.getElementById('testFocusableTree1.node2.unregisteredChild1')
|
|
.focus();
|
|
|
|
// The tree of the unregistered child element should take focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test('non-registered tree focus()ed returns null', function () {
|
|
document.getElementById('testUnregisteredFocusableTree3').tabIndex = -1;
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('non-registered tree node focus()ed returns null', function () {
|
|
document.getElementById(
|
|
'testUnregisteredFocusableTree3.node1',
|
|
).tabIndex = -1;
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3.node1').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('non-registered tree node focus()ed after registered node focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById(
|
|
'testUnregisteredFocusableTree3.node1',
|
|
).tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3.node1').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unfocusable element focus()ed after registered node focused returns original tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testUnfocusableElement').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree1,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node prior focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the more recent tree was removed, there's no tree currently focused.
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node recently focused returns new tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the most recent tree still exists, it still has focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node after unregistering returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
// Attempting to focus a now removed tree should result in nothing being
|
|
// focused since the removed tree can have DOM focus, but that focus is
|
|
// ignored by FocusManager.
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('nested tree focusTree()ed with no prev focus returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
document.getElementById('testFocusableNestedTree4').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableNestedTree4').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedTree4,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed with no prev focus returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
document.getElementById('testFocusableNestedTree4.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableNestedTree4.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedTree4,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed after parent focused returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableNestedTree4.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
document.getElementById('testFocusableNestedTree4.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedTree4,
|
|
);
|
|
});
|
|
});
|
|
suite('getFocusedNode()', function () {
|
|
test('registered root focus()ed no prev focus returns root node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableTree1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed no prev focus returns node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node1,
|
|
);
|
|
});
|
|
|
|
test('registered subnode focus()ed no prev focus returns subnode', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1.child1').tabIndex =
|
|
-1;
|
|
|
|
document.getElementById('testFocusableTree1.node1.child1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node1Child1,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node2').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree1.node2').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node2,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus diff tree returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
});
|
|
|
|
test('registered tree root focus()ed after prev node focus diff tree returns new root', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree2').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('non-registered node subelement focus()ed returns nearest node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById(
|
|
'testFocusableTree1.node2.unregisteredChild1',
|
|
).tabIndex = -1;
|
|
|
|
document
|
|
.getElementById('testFocusableTree1.node2.unregisteredChild1')
|
|
.focus();
|
|
|
|
// The nearest node of the unregistered child element should take focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node2,
|
|
);
|
|
});
|
|
|
|
test('non-registered tree focus()ed returns null', function () {
|
|
document.getElementById('testUnregisteredFocusableTree3').tabIndex = -1;
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('non-registered tree node focus()ed returns null', function () {
|
|
document.getElementById(
|
|
'testUnregisteredFocusableTree3.node1',
|
|
).tabIndex = -1;
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3.node1').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('non-registered tree node focus()ed after registered node focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById(
|
|
'testUnregisteredFocusableTree3.node1',
|
|
).tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3.node1').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unfocusable element focus()ed after registered node focused returns original node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testUnfocusableElement').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node1,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node prior focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the more recent tree was removed, there's no tree currently focused.
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node recently focused returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the most recent tree still exists, it still has focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node after unregistering returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
// Attempting to focus a now removed tree should result in nothing being
|
|
// focused since the removed tree can have DOM focus, but that focus is
|
|
// ignored by FocusManager.
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('nested tree focus()ed with no prev focus returns nested root', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
document.getElementById('testFocusableNestedTree4').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableNestedTree4').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedTree4.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('nested tree node focus()ed with no prev focus returns focused node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
document.getElementById('testFocusableNestedTree4.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableNestedTree4.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedTree4Node1,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focus()ed after parent focused returns focused node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableNestedTree4.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
document.getElementById('testFocusableNestedTree4.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedTree4Node1,
|
|
);
|
|
});
|
|
|
|
test('deletion after focus() returns null', function () {
|
|
const rootElem = document.createElement('div');
|
|
const nodeElem = document.createElement('div');
|
|
rootElem.setAttribute('id', 'focusRoot');
|
|
rootElem.setAttribute('tabindex', '-1');
|
|
nodeElem.setAttribute('id', 'focusNode');
|
|
nodeElem.setAttribute('tabindex', '-1');
|
|
nodeElem.textContent = 'Focusable node';
|
|
rootElem.appendChild(nodeElem);
|
|
document.body.appendChild(rootElem);
|
|
const root = this.createFocusableTree('focusRoot');
|
|
const node = this.createFocusableNode(root, 'focusNode');
|
|
this.focusManager.registerTree(root);
|
|
document.getElementById('focusNode').tabIndex = -1;
|
|
document.getElementById('focusNode').focus();
|
|
|
|
node.getFocusableElement().remove();
|
|
|
|
assert.notStrictEqual(this.focusManager.getFocusedNode(), node);
|
|
rootElem.remove(); // Cleanup.
|
|
});
|
|
|
|
test('after focus() after trying to focusNode() an unfocusable node updates returns focus()ed node', function () {
|
|
this.testFocusableTree1Node1.canBeFocused = () => false;
|
|
document.getElementById('testFocusableTree1.node2').tabIndex = -1;
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
document.getElementById('testFocusableTree1.node2').focus();
|
|
|
|
// focus()ing a new node should overwrite a failed attempt to focusNode() an unfocusable
|
|
// node. This verifies that DOM focus syncing is properly reenabled by FocusManager.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node2,
|
|
);
|
|
});
|
|
|
|
test('after focus() after trying to focusNode() the same node twice returns focus()ed node', function () {
|
|
document.getElementById('testFocusableTree1.node2').tabIndex = -1;
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
// Intentionally try to focus the same node twice.
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
this.focusManager.focusNode(this.testFocusableTree1Node1);
|
|
|
|
document.getElementById('testFocusableTree1.node2').focus();
|
|
|
|
// focus()ing a new node should overwrite a failed attempt to focusNode() the same node
|
|
// twice. This verifies that DOM focus syncing is properly reenabled by FocusManager.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree1Node2,
|
|
);
|
|
});
|
|
});
|
|
suite('CSS classes', function () {
|
|
test('registered root focus()ed no prev focus returns root elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableTree1').focus();
|
|
|
|
const rootElem = this.testFocusableTree1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed no prev focus node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
const nodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus same tree old node elem has no focus property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node2').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree1.node2').focus();
|
|
|
|
const prevNodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus same tree new node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node2').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree1.node2').focus();
|
|
|
|
const newNodeElem = this.testFocusableTree1Node2.getFocusableElement();
|
|
assert.includesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus diff tree old node elem has passive property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
const prevNodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus diff tree new node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
const newNodeElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree root focus()ed after prev node focus diff tree new root has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree2').focus();
|
|
|
|
const rootElem = this.testFocusableTree2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('non-registered node subelement focus()ed nearest node has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById(
|
|
'testFocusableTree1.node2.unregisteredChild1',
|
|
).tabIndex = -1;
|
|
|
|
document
|
|
.getElementById('testFocusableTree1.node2.unregisteredChild1')
|
|
.focus();
|
|
|
|
// The nearest node of the unregistered child element should be actively focused.
|
|
const nodeElem = this.testFocusableTree1Node2.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('non-registered tree focus()ed has no focus', function () {
|
|
document.getElementById('testUnregisteredFocusableTree3').tabIndex = -1;
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
const rootElem = document.getElementById(
|
|
'testUnregisteredFocusableTree3',
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('non-registered tree node focus()ed has no focus', function () {
|
|
document.getElementById(
|
|
'testUnregisteredFocusableTree3.node1',
|
|
).tabIndex = -1;
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3.node1').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
const nodeElem = document.getElementById(
|
|
'testUnregisteredFocusableTree3.node1',
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unfocsable element focus()ed after registered node focused original node has active focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
document.getElementById('testUnfocusableElement').focus();
|
|
|
|
// The original node should be unchanged, and the unregistered node should not have any
|
|
// focus indicators.
|
|
const nodeElem = document.getElementById('testFocusableTree1.node1');
|
|
const attemptedNewNodeElem = document.getElementById(
|
|
'testUnfocusableElement',
|
|
);
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
attemptedNewNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
attemptedNewNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus removes focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators.
|
|
const rootElem = this.testFocusableTree1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus removes focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators.
|
|
const nodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node prior removes focus from removed tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators. However, the old node
|
|
// should still have passive indication.
|
|
const otherNodeElem =
|
|
this.testFocusableTree2Node1.getFocusableElement();
|
|
const removedNodeElem =
|
|
this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node recently removes focus from removed tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators. However, the new node
|
|
// should still have active indication.
|
|
const otherNodeElem =
|
|
this.testFocusableTree2Node1.getFocusableElement();
|
|
const removedNodeElem =
|
|
this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node after unregistering removes active indicator', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
this.focusManager.unregisterTree(this.testFocusableTree1);
|
|
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
// Attempting to focus a now removed tree should remove active.
|
|
const otherNodeElem =
|
|
this.testFocusableTree2Node1.getFocusableElement();
|
|
const removedNodeElem =
|
|
this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('focus() multiple nodes in same tree with switches ensure passive focus has gone', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node2').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree1.node2').focus();
|
|
|
|
// When switching back to the first tree, ensure the original passive node is no longer
|
|
// passive now that the new node is active.
|
|
const node1 = this.testFocusableTree1Node1.getFocusableElement();
|
|
const node2 = this.testFocusableTree1Node2.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
node1.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
node2.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree focus()ed other tree node passively focused tree node now has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree1').focus();
|
|
|
|
// Directly refocusing a tree's root should have functional parity with focusTree(). That
|
|
// means the tree's previous node should now have active focus again and its root should
|
|
// have no focus indication.
|
|
const rootElem = this.testFocusableTree1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
const nodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('focus on root, node in diff tree, then node in first tree; root should have focus gone', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree1);
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableTree1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree1').focus();
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree1.node1').focus();
|
|
|
|
const nodeElem = this.testFocusableTree1Node1.getFocusableElement();
|
|
const rootElem = this.testFocusableTree1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree focus()ed with no prev root has active focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
document.getElementById('testFocusableNestedTree4').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableNestedTree4').focus();
|
|
|
|
const rootElem = this.testFocusableNestedTree4
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focus()ed with no prev focus node has active focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
document.getElementById('testFocusableNestedTree4.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableNestedTree4.node1').focus();
|
|
|
|
const nodeElem =
|
|
this.testFocusableNestedTree4Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focus()ed after parent focused prev has passive node has active', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableNestedTree4.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
document.getElementById('testFocusableNestedTree4.node1').focus();
|
|
|
|
const prevNodeElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
const currNodeElem =
|
|
this.testFocusableNestedTree4Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
currNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
/* Focus tests for SVG trees. */
|
|
|
|
suite('focus*() switching in SVG tree', function () {
|
|
suite('getFocusedTree()', function () {
|
|
test('registered tree focusTree()ed no prev focus returns tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed prev node focused returns tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree prev focused returns new tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree node prev focused returns new tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
});
|
|
|
|
test('registered root focusNode()ed no prev focus returns tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableGroup1.getRootFocusableNode(),
|
|
);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test("registered node focusNode()ed no prev focus returns node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test("registered subnode focusNode()ed no prev focus returns node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1Child1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus returns same tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test("registered node focusNode()ed after prev node focus diff tree returns new node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
});
|
|
|
|
test("registered tree root focusNode()ed after prev node focus diff tree returns new node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableGroup2.getRootFocusableNode(),
|
|
);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusTree()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node prior focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the more recent tree was removed, there's no tree currently focused.
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node recently focused returns new tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the most recent tree still exists, it still has focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
});
|
|
|
|
test('nested tree focusTree()ed with no prev focus returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
|
|
this.focusManager.focusTree(this.testFocusableNestedGroup4);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedGroup4,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed with no prev focus returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedGroup4Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedGroup4,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed after parent focused returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedGroup4Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedGroup4,
|
|
);
|
|
});
|
|
});
|
|
suite('getFocusedNode()', function () {
|
|
test('registered tree focusTree()ed no prev focus returns root node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed prev node focused returns original node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
// The original node retains focus since the tree already holds focus (per focusTree's
|
|
// contract).
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node1,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree prev focused returns new root node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree node prev focused returns new root node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('registered root focusNode()ed no prev focus returns root node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableGroup1.getRootFocusableNode(),
|
|
);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed no prev focus returns node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node1,
|
|
);
|
|
});
|
|
|
|
test('registered subnode focusNode()ed no prev focus returns subnode', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1Child1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node1Child1,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node2,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus diff tree returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
});
|
|
|
|
test('registered tree root focusNode()ed after prev node focus diff tree returns new root', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableGroup2.getRootFocusableNode(),
|
|
);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusTree()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node prior focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the more recent tree was removed, there's no tree currently focused.
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node recently focused returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the most recent tree still exists, it still has focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
});
|
|
|
|
test('nested tree focusTree()ed with no prev focus returns nested root', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
|
|
this.focusManager.focusTree(this.testFocusableNestedGroup4);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedGroup4.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed with no prev focus returns focused node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedGroup4Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedGroup4Node1,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed after parent focused returns focused node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedGroup4Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedGroup4Node1,
|
|
);
|
|
});
|
|
});
|
|
suite('CSS classes', function () {
|
|
test('registered tree focusTree()ed no prev focus root elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
const rootElem = this.testFocusableGroup1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed prev node focused original elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
// The original node retains active focus since the tree already holds focus (per
|
|
// focusTree's contract).
|
|
const nodeElem = this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree prev focused new root elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
const rootElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed diff tree node prev focused new root elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
const rootElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered root focusNode()ed no prev focus returns root elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableGroup1.getRootFocusableNode(),
|
|
);
|
|
|
|
const rootElem = this.testFocusableGroup1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed no prev focus node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
const nodeElem = this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus same tree old node elem has no focus property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node2);
|
|
|
|
const prevNodeElem =
|
|
this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus same tree new node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node2);
|
|
|
|
const newNodeElem = this.testFocusableGroup1Node2.getFocusableElement();
|
|
assert.includesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus diff tree old node elem has passive property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
const prevNodeElem =
|
|
this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focusNode()ed after prev node focus diff tree new node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
const newNodeElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree root focusNode()ed after prev node focus diff tree new root has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.focusNode(
|
|
this.testFocusableGroup2.getRootFocusableNode(),
|
|
);
|
|
|
|
const rootElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusTree()ed with no prev focus removes focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators.
|
|
const rootElem = this.testFocusableGroup1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with no prev focus removes focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators.
|
|
const nodeElem = this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node prior removes focus from removed tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators. However, the old node
|
|
// should still have passive indication.
|
|
const otherNodeElem =
|
|
this.testFocusableGroup2Node1.getFocusableElement();
|
|
const removedNodeElem =
|
|
this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focusNode()ed with prev node recently removes focus from removed tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators. However, the new node
|
|
// should still have active indication.
|
|
const otherNodeElem =
|
|
this.testFocusableGroup2Node1.getFocusableElement();
|
|
const removedNodeElem =
|
|
this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('focusNode() multiple nodes in same tree with switches ensure passive focus has gone', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node2);
|
|
|
|
// When switching back to the first tree, ensure the original passive node is no longer
|
|
// passive now that the new node is active.
|
|
const node1 = this.testFocusableGroup1Node1.getFocusableElement();
|
|
const node2 = this.testFocusableGroup1Node2.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
node1.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
node2.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree focusTree()ed other tree node passively focused tree node now has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
|
|
// The original node in the tree should be moved from passive to active focus per the
|
|
// contract of focusTree). Also, the root of the tree should have no focus indication.
|
|
const nodeElem = this.testFocusableGroup1Node1.getFocusableElement();
|
|
const rootElem = this.testFocusableGroup1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('focus on root, node in diff tree, then node in first tree; root should have focus gone', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
const nodeElem = this.testFocusableGroup1Node1.getFocusableElement();
|
|
const rootElem = this.testFocusableGroup1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree focusTree()ed with no prev root has active focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
|
|
this.focusManager.focusTree(this.testFocusableNestedGroup4);
|
|
|
|
const rootElem = this.testFocusableNestedGroup4
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed with no prev focus node has active focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedGroup4Node1);
|
|
|
|
const nodeElem =
|
|
this.testFocusableNestedGroup4Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed after parent focused prev has passive node has active', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableNestedGroup4Node1);
|
|
|
|
const prevNodeElem =
|
|
this.testFocusableGroup2Node1.getFocusableElement();
|
|
const currNodeElem =
|
|
this.testFocusableNestedGroup4Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
currNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('DOM focus() switching in SVG tree', function () {
|
|
suite('getFocusedTree()', function () {
|
|
test('registered root focus()ed no prev focus returns tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableGroup1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test("registered node focus()ed no prev focus returns node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test("registered subnode focus()ed no prev focus returns node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1.child1').tabIndex =
|
|
-1;
|
|
|
|
document.getElementById('testFocusableGroup1.node1.child1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus returns same tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node2').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup1.node2').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test("registered node focus()ed after prev node focus diff tree returns new node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
});
|
|
|
|
test("registered tree root focus()ed after prev node focus diff tree returns new node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup2').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
});
|
|
|
|
test("non-registered node subelement focus()ed returns node's tree", function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById(
|
|
'testFocusableGroup1.node2.unregisteredChild1',
|
|
).tabIndex = -1;
|
|
|
|
document
|
|
.getElementById('testFocusableGroup1.node2.unregisteredChild1')
|
|
.focus();
|
|
|
|
// The tree of the unregistered child element should take focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup1,
|
|
);
|
|
});
|
|
|
|
test('non-registered tree focus()ed returns null', function () {
|
|
document.getElementById('testUnregisteredFocusableGroup3').tabIndex =
|
|
-1;
|
|
|
|
document.getElementById('testUnregisteredFocusableGroup3').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('non-registered tree node focus()ed returns null', function () {
|
|
document.getElementById(
|
|
'testUnregisteredFocusableGroup3.node1',
|
|
).tabIndex = -1;
|
|
|
|
document
|
|
.getElementById('testUnregisteredFocusableGroup3.node1')
|
|
.focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('non-registered tree node focus()ed after registered node focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById(
|
|
'testUnregisteredFocusableGroup3.node1',
|
|
).tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document
|
|
.getElementById('testUnregisteredFocusableGroup3.node1')
|
|
.focus();
|
|
|
|
// Attempting to focus a now removed tree should result in nothing being
|
|
// focused since the removed tree can have DOM focus, but that focus is
|
|
// ignored by FocusManager.
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node prior focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the more recent tree was removed, there's no tree currently focused.
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node recently focused returns new tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the most recent tree still exists, it still has focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node after unregistering returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
// Attempting to focus a now removed tree should result in nothing being
|
|
// focused since the removed tree can have DOM focus, but that focus is
|
|
// ignored by FocusManager.
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
});
|
|
|
|
test('nested tree focusTree()ed with no prev focus returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
document.getElementById('testFocusableNestedGroup4').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableNestedGroup4').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedGroup4,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed with no prev focus returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
document.getElementById('testFocusableNestedGroup4.node1').tabIndex =
|
|
-1;
|
|
|
|
document.getElementById('testFocusableNestedGroup4.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedGroup4,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focusNode()ed after parent focused returns nested tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableNestedGroup4.node1').tabIndex =
|
|
-1;
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
document.getElementById('testFocusableNestedGroup4.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedGroup4,
|
|
);
|
|
});
|
|
});
|
|
suite('getFocusedNode()', function () {
|
|
test('registered root focus()ed no prev focus returns root node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableGroup1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed no prev focus returns node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node1,
|
|
);
|
|
});
|
|
|
|
test('registered subnode focus()ed no prev focus returns subnode', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1.child1').tabIndex =
|
|
-1;
|
|
|
|
document.getElementById('testFocusableGroup1.node1.child1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node1Child1,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node2').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup1.node2').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node2,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus diff tree returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
});
|
|
|
|
test('registered tree root focus()ed after prev node focus diff tree returns new root', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup2').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('non-registered node subelement focus()ed returns nearest node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById(
|
|
'testFocusableGroup1.node2.unregisteredChild1',
|
|
).tabIndex = -1;
|
|
|
|
document
|
|
.getElementById('testFocusableGroup1.node2.unregisteredChild1')
|
|
.focus();
|
|
|
|
// The nearest node of the unregistered child element should take focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node2,
|
|
);
|
|
});
|
|
|
|
test('non-registered tree focus()ed returns null', function () {
|
|
document.getElementById('testUnregisteredFocusableGroup3').tabIndex =
|
|
-1;
|
|
|
|
document.getElementById('testUnregisteredFocusableGroup3').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('non-registered tree node focus()ed returns null', function () {
|
|
document.getElementById(
|
|
'testUnregisteredFocusableGroup3.node1',
|
|
).tabIndex = -1;
|
|
|
|
document
|
|
.getElementById('testUnregisteredFocusableGroup3.node1')
|
|
.focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('non-registered tree node focus()ed after registered node focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById(
|
|
'testUnregisteredFocusableGroup3.node1',
|
|
).tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document
|
|
.getElementById('testUnregisteredFocusableGroup3.node1')
|
|
.focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unfocusable element focus()ed after registered node focused returns original node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testUnfocusableElement').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node1,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node prior focused returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the more recent tree was removed, there's no tree currently focused.
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node recently focused returns new node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the most recent tree still exists, it still has focus.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node after unregistering returns null', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
// Attempting to focus a now removed tree should result in nothing being
|
|
// focused since the removed tree can have DOM focus, but that focus is
|
|
// ignored by FocusManager.
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
});
|
|
|
|
test('nested tree focus()ed with no prev focus returns nested root', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
document.getElementById('testFocusableNestedGroup4').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableNestedGroup4').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedGroup4.getRootFocusableNode(),
|
|
);
|
|
});
|
|
|
|
test('nested tree node focus()ed with no prev focus returns focused node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
document.getElementById('testFocusableNestedGroup4.node1').tabIndex =
|
|
-1;
|
|
|
|
document.getElementById('testFocusableNestedGroup4.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedGroup4Node1,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focus()ed after parent focused returns focused node', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableNestedGroup4.node1').tabIndex =
|
|
-1;
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
document.getElementById('testFocusableNestedGroup4.node1').focus();
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedGroup4Node1,
|
|
);
|
|
});
|
|
|
|
test('after focus() after trying to focusNode() an unfocusable node updates returns focus()ed node', function () {
|
|
this.testFocusableGroup1Node1.canBeFocused = () => false;
|
|
document.getElementById('testFocusableGroup1.node2').tabIndex = -1;
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
document.getElementById('testFocusableGroup1.node2').focus();
|
|
|
|
// focus()ing a new node should overwrite a failed attempt to focusNode() an unfocusable
|
|
// node. This verifies that DOM focus syncing is properly reenabled by FocusManager.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node2,
|
|
);
|
|
});
|
|
|
|
test('after focus() after trying to focusNode() the same node twice returns focus()ed node', function () {
|
|
document.getElementById('testFocusableGroup1.node2').tabIndex = -1;
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
// Intentionally try to focus the same node twice.
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
this.focusManager.focusNode(this.testFocusableGroup1Node1);
|
|
|
|
document.getElementById('testFocusableGroup1.node2').focus();
|
|
|
|
// focus()ing a new node should overwrite a failed attempt to focusNode() the same node
|
|
// twice. This verifies that DOM focus syncing is properly reenabled by FocusManager.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup1Node2,
|
|
);
|
|
});
|
|
});
|
|
suite('CSS classes', function () {
|
|
test('registered root focus()ed no prev focus returns root elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableGroup1').focus();
|
|
|
|
const rootElem = this.testFocusableGroup1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed no prev focus node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
const nodeElem = this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus same tree old node elem has no focus property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node2').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup1.node2').focus();
|
|
|
|
const prevNodeElem =
|
|
this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus same tree new node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node2').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup1.node2').focus();
|
|
|
|
const newNodeElem = this.testFocusableGroup1Node2.getFocusableElement();
|
|
assert.includesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus diff tree old node elem has passive property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
const prevNodeElem =
|
|
this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered node focus()ed after prev node focus diff tree new node elem has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
const newNodeElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
newNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree root focus()ed after prev node focus diff tree new root has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup2').focus();
|
|
|
|
const rootElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('non-registered node subelement focus()ed nearest node has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById(
|
|
'testFocusableGroup1.node2.unregisteredChild1',
|
|
).tabIndex = -1;
|
|
|
|
document
|
|
.getElementById('testFocusableGroup1.node2.unregisteredChild1')
|
|
.focus();
|
|
|
|
// The nearest node of the unregistered child element should be actively focused.
|
|
const nodeElem = this.testFocusableGroup1Node2.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('non-registered tree focus()ed has no focus', function () {
|
|
document.getElementById('testUnregisteredFocusableGroup3').tabIndex =
|
|
-1;
|
|
|
|
document.getElementById('testUnregisteredFocusableGroup3').focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
const rootElem = document.getElementById(
|
|
'testUnregisteredFocusableGroup3',
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('non-registered tree node focus()ed has no focus', function () {
|
|
document.getElementById(
|
|
'testUnregisteredFocusableGroup3.node1',
|
|
).tabIndex = -1;
|
|
|
|
document
|
|
.getElementById('testUnregisteredFocusableGroup3.node1')
|
|
.focus();
|
|
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
const nodeElem = document.getElementById(
|
|
'testUnregisteredFocusableGroup3.node1',
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unfocusable element focus()ed after registered node focused original node has active focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
document.getElementById('testUnfocusableElement').focus();
|
|
|
|
// The original node should be unchanged, and the unregistered node should not have any
|
|
// focus indicators.
|
|
const nodeElem = document.getElementById('testFocusableGroup1.node1');
|
|
const attemptedNewNodeElem = document.getElementById(
|
|
'testUnfocusableElement',
|
|
);
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
attemptedNewNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
attemptedNewNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus removes focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators.
|
|
const rootElem = this.testFocusableGroup1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with no prev focus removes focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators.
|
|
const nodeElem = this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node prior removes focus from removed tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators. However, the old node
|
|
// should still have passive indication.
|
|
const otherNodeElem =
|
|
this.testFocusableGroup2Node1.getFocusableElement();
|
|
const removedNodeElem =
|
|
this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node recently removes focus from removed tree', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
// Since the tree was unregistered it no longer has focus indicators. However, the new node
|
|
// should still have active indication.
|
|
const otherNodeElem =
|
|
this.testFocusableGroup2Node1.getFocusableElement();
|
|
const removedNodeElem =
|
|
this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('unregistered tree focus()ed with prev node after unregistering removes active indicator', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
this.focusManager.unregisterTree(this.testFocusableGroup1);
|
|
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
// Attempting to focus a now removed tree should remove active.
|
|
const otherNodeElem =
|
|
this.testFocusableGroup2Node1.getFocusableElement();
|
|
const removedNodeElem =
|
|
this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
otherNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
removedNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('focus() multiple nodes in same tree with switches ensure passive focus has gone', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node2').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup1.node2').focus();
|
|
|
|
// When switching back to the first tree, ensure the original passive node is no longer
|
|
// passive now that the new node is active.
|
|
const node1 = this.testFocusableGroup1Node1.getFocusableElement();
|
|
const node2 = this.testFocusableGroup1Node2.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
node1.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
node2.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('registered tree focus()ed other tree node passively focused tree node now has active property', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup1').focus();
|
|
|
|
// Directly refocusing a tree's root should have functional parity with focusTree(). That
|
|
// means the tree's previous node should now have active focus again and its root should
|
|
// have no focus indication.
|
|
const rootElem = this.testFocusableGroup1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
const nodeElem = this.testFocusableGroup1Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('focus on root, node in diff tree, then node in first tree; root should have focus gone', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup1);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup1').focus();
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup1.node1').focus();
|
|
|
|
const nodeElem = this.testFocusableGroup1Node1.getFocusableElement();
|
|
const rootElem = this.testFocusableGroup1
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree focus()ed with no prev root has active focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
document.getElementById('testFocusableNestedGroup4').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableNestedGroup4').focus();
|
|
|
|
const rootElem = this.testFocusableNestedGroup4
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focus()ed with no prev focus node has active focus', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
document.getElementById('testFocusableNestedGroup4.node1').tabIndex =
|
|
-1;
|
|
|
|
document.getElementById('testFocusableNestedGroup4.node1').focus();
|
|
|
|
const nodeElem =
|
|
this.testFocusableNestedGroup4Node1.getFocusableElement();
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('nested tree node focus()ed after parent focused prev has passive node has active', function () {
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.registerTree(this.testFocusableNestedGroup4);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableNestedGroup4.node1').tabIndex =
|
|
-1;
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
document.getElementById('testFocusableNestedGroup4.node1').focus();
|
|
|
|
const prevNodeElem =
|
|
this.testFocusableGroup2Node1.getFocusableElement();
|
|
const currNodeElem =
|
|
this.testFocusableNestedGroup4Node1.getFocusableElement();
|
|
assert.notIncludesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
currNodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currNodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
/* High-level focus/defocusing tests. */
|
|
suite('Defocusing and refocusing', function () {
|
|
test('Defocusing actively focused root HTML tree switches to passive highlight', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
document.getElementById('testUnregisteredFocusableTree3').tabIndex = -1;
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3').focus();
|
|
|
|
const rootNode = this.testFocusableTree2.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('Defocusing actively focused HTML tree node switches to passive highlight', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
document.getElementById('testUnregisteredFocusableTree3').tabIndex = -1;
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3').focus();
|
|
|
|
const nodeElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('Defocusing actively focused HTML subtree node switches to passive highlight', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
this.focusManager.focusNode(this.testFocusableNestedTree4Node1);
|
|
document.getElementById('testUnregisteredFocusableTree3').tabIndex = -1;
|
|
|
|
document.getElementById('testUnregisteredFocusableTree3').focus();
|
|
|
|
const nodeElem = this.testFocusableNestedTree4Node1.getFocusableElement();
|
|
assert.isNull(this.focusManager.getFocusedTree());
|
|
assert.isNull(this.focusManager.getFocusedNode());
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('Refocusing actively focused root HTML tree restores to active highlight', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
document.getElementById('testUnregisteredFocusableTree3').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2').tabIndex = -1;
|
|
document.getElementById('testUnregisteredFocusableTree3').focus();
|
|
|
|
document.getElementById('testFocusableTree2').focus();
|
|
|
|
const rootNode = this.testFocusableTree2.getRootFocusableNode();
|
|
const rootElem = rootNode.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
assert.strictEqual(this.focusManager.getFocusedNode(), rootNode);
|
|
assert.notIncludesClass(
|
|
rootElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('Refocusing actively focused HTML tree node restores to active highlight', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
document.getElementById('testUnregisteredFocusableTree3').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testUnregisteredFocusableTree3').focus();
|
|
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
const nodeElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('Refocusing actively focused HTML subtree node restores to active highlight', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableNestedTree4);
|
|
this.focusManager.focusNode(this.testFocusableNestedTree4Node1);
|
|
document.getElementById('testUnregisteredFocusableTree3').tabIndex = -1;
|
|
document.getElementById('testFocusableNestedTree4.node1').tabIndex = -1;
|
|
document.getElementById('testUnregisteredFocusableTree3').focus();
|
|
|
|
document.getElementById('testFocusableNestedTree4.node1').focus();
|
|
|
|
const nodeElem = this.testFocusableNestedTree4Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableNestedTree4,
|
|
);
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableNestedTree4Node1,
|
|
);
|
|
assert.notIncludesClass(
|
|
nodeElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
});
|
|
|
|
/* Combined HTML/SVG tree focus tests. */
|
|
|
|
suite('HTML/SVG focus tree switching', function () {
|
|
suite('Focus HTML tree then SVG tree', function () {
|
|
test('HTML focusTree()ed then SVG focusTree()ed correctly updates getFocusedTree() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
const prevElem = this.testFocusableTree2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
const currElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('HTML focusTree()ed then SVG focusNode()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
const prevElem = this.testFocusableTree2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
const currElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('HTML focusTree()ed then SVG DOM focus()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
const prevElem = this.testFocusableTree2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
const currElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('HTML focusNode()ed then SVG focusTree()ed correctly updates getFocusedTree() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
const prevElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('HTML focusNode()ed then SVG focusNode()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
const prevElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('HTML focusNode()ed then SVG DOM focus()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
const prevElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('HTML DOM focus()ed then SVG focusTree()ed correctly updates getFocusedTree() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
const prevElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('HTML DOM focus()ed then SVG focusNode()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
const prevElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('HTML DOM focus()ed then SVG DOM focus()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
const prevElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
});
|
|
suite('Focus SVG tree then HTML tree', function () {
|
|
test('SVG focusTree()ed then HTML focusTree()ed correctly updates getFocusedTree() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
const prevElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
const currElem = this.testFocusableTree2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('SVG focusTree()ed then HTML focusNode()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
const prevElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
const currElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('SVG focusTree()ed then HTML DOM focus()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
const prevElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
const currElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('SVG focusNode()ed then HTML focusTree()ed correctly updates getFocusedTree() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
const prevElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableTree2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('SVG focusNode()ed then HTML focusNode()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
const prevElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('SVG focusNode()ed then HTML DOM focus()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
const prevElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('SVG DOM focus()ed then HTML focusTree()ed correctly updates getFocusedTree() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
|
|
const prevElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableTree2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableTree2,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('SVG DOM focus()ed then HTML focusNode()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
const prevElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('SVG DOM focus()ed then HTML DOM focus()ed correctly updates getFocusedNode() and indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableTree2.node1').tabIndex = -1;
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
document.getElementById('testFocusableTree2.node1').focus();
|
|
|
|
const prevElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
const currElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
assert.strictEqual(document.activeElement, currElem);
|
|
assert.includesClass(
|
|
currElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
currElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.notIncludesClass(
|
|
prevElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.includesClass(
|
|
prevElem.classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
/* Ephemeral focus tests. */
|
|
|
|
suite('takeEphemeralFocus()', function () {
|
|
setup(function () {
|
|
// Ensure ephemeral-specific elements are focusable.
|
|
document.getElementById('nonTreeElementForEphemeralFocus').tabIndex = -1;
|
|
document.getElementById('nonTreeGroupForEphemeralFocus').tabIndex = -1;
|
|
});
|
|
teardown(function () {
|
|
// Ensure ephemeral-specific elements have their tab indexes reset for a clean state.
|
|
document
|
|
.getElementById('nonTreeElementForEphemeralFocus')
|
|
.removeAttribute('tabindex');
|
|
document
|
|
.getElementById('nonTreeGroupForEphemeralFocus')
|
|
.removeAttribute('tabindex');
|
|
});
|
|
|
|
test('with no focused node does not change states', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeElementForEphemeralFocus',
|
|
);
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
// Taking focus without an existing node having focus should change no focus indicators.
|
|
const activeElems = Array.from(
|
|
document.querySelectorAll(ACTIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
const passiveElems = Array.from(
|
|
document.querySelectorAll(PASSIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
assert.isEmpty(activeElems);
|
|
assert.isEmpty(passiveElems);
|
|
});
|
|
|
|
test('with focused node changes focused node to passive', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeElementForEphemeralFocus',
|
|
);
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
// Taking focus without an existing node having focus should change no focus indicators.
|
|
const activeElems = Array.from(
|
|
document.querySelectorAll(ACTIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
const passiveElems = Array.from(
|
|
document.querySelectorAll(PASSIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
assert.isEmpty(activeElems);
|
|
assert.strictEqual(passiveElems.length, 1);
|
|
assert.includesClass(
|
|
this.testFocusableTree2Node1.getFocusableElement().classList,
|
|
FocusManager.PASSIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
});
|
|
|
|
test('focuses provided HTML element', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeElementForEphemeralFocus',
|
|
);
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
assert.strictEqual(document.activeElement, ephemeralElement);
|
|
});
|
|
|
|
test('focuses provided SVG element', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeGroupForEphemeralFocus',
|
|
);
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
assert.strictEqual(document.activeElement, ephemeralElement);
|
|
});
|
|
|
|
test('twice for without finishing previous throws error', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
const ephemeralGroupElement = document.getElementById(
|
|
'nonTreeGroupForEphemeralFocus',
|
|
);
|
|
const ephemeralDivElement = document.getElementById(
|
|
'nonTreeElementForEphemeralFocus',
|
|
);
|
|
this.focusManager.takeEphemeralFocus(ephemeralGroupElement);
|
|
|
|
const errorMsgRegex =
|
|
/Attempted to take ephemeral focus when it's already held+?/;
|
|
assert.throws(
|
|
() => this.focusManager.takeEphemeralFocus(ephemeralDivElement),
|
|
errorMsgRegex,
|
|
);
|
|
});
|
|
|
|
test('then focusTree() changes getFocusedTree() but not active state', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeGroupForEphemeralFocus',
|
|
);
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
const activeElems = Array.from(
|
|
document.querySelectorAll(ACTIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
assert.isEmpty(activeElems);
|
|
});
|
|
|
|
test('then focusNode() changes getFocusedNode() but not active state', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeGroupForEphemeralFocus',
|
|
);
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
const activeElems = Array.from(
|
|
document.querySelectorAll(ACTIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
assert.isEmpty(activeElems);
|
|
});
|
|
|
|
test('then DOM refocus changes getFocusedNode() but not active state', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeGroupForEphemeralFocus',
|
|
);
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
// Force focus to change via the DOM.
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
|
|
// The focus() state change will affect getFocusedNode() but it will not cause the node to now
|
|
// be active.
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
const activeElems = Array.from(
|
|
document.querySelectorAll(ACTIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
assert.isEmpty(activeElems);
|
|
});
|
|
|
|
test('then finish ephemeral callback with no node does not change indicators', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeElementForEphemeralFocus',
|
|
);
|
|
const finishFocusCallback =
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
finishFocusCallback();
|
|
|
|
// Finishing ephemeral focus without a previously focused node should not change indicators.
|
|
const activeElems = Array.from(
|
|
document.querySelectorAll(ACTIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
const passiveElems = Array.from(
|
|
document.querySelectorAll(PASSIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
assert.isEmpty(activeElems);
|
|
assert.isEmpty(passiveElems);
|
|
});
|
|
|
|
test('again after finishing previous empheral focus should focus new element', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
const ephemeralGroupElement = document.getElementById(
|
|
'nonTreeGroupForEphemeralFocus',
|
|
);
|
|
const ephemeralDivElement = document.getElementById(
|
|
'nonTreeElementForEphemeralFocus',
|
|
);
|
|
const finishFocusCallback = this.focusManager.takeEphemeralFocus(
|
|
ephemeralGroupElement,
|
|
);
|
|
|
|
finishFocusCallback();
|
|
this.focusManager.takeEphemeralFocus(ephemeralDivElement);
|
|
|
|
// An exception should not be thrown and the new element should receive focus.
|
|
assert.strictEqual(document.activeElement, ephemeralDivElement);
|
|
});
|
|
|
|
test('calling ephemeral callback twice throws error', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeElementForEphemeralFocus',
|
|
);
|
|
const finishFocusCallback =
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
finishFocusCallback();
|
|
|
|
const errorMsgRegex =
|
|
/Attempted to finish ephemeral focus twice for element+?/;
|
|
assert.throws(() => finishFocusCallback(), errorMsgRegex);
|
|
});
|
|
|
|
test('then finish ephemeral callback should restore focused node', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeGroupForEphemeralFocus',
|
|
);
|
|
const finishFocusCallback =
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
finishFocusCallback();
|
|
|
|
// The original focused node should be restored.
|
|
const nodeElem = this.testFocusableTree2Node1.getFocusableElement();
|
|
const activeElems = Array.from(
|
|
document.querySelectorAll(ACTIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableTree2Node1,
|
|
);
|
|
assert.strictEqual(activeElems.length, 1);
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.strictEqual(document.activeElement, nodeElem);
|
|
});
|
|
|
|
test('then focusTree() and finish ephemeral callback correctly sets new active state', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusTree(this.testFocusableTree2);
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeGroupForEphemeralFocus',
|
|
);
|
|
const finishFocusCallback =
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
this.focusManager.focusTree(this.testFocusableGroup2);
|
|
finishFocusCallback();
|
|
|
|
// The tree's root should now be the active element since focus changed between the start and
|
|
// end of the ephemeral flow.
|
|
const rootElem = this.testFocusableGroup2
|
|
.getRootFocusableNode()
|
|
.getFocusableElement();
|
|
const activeElems = Array.from(
|
|
document.querySelectorAll(ACTIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedTree(),
|
|
this.testFocusableGroup2,
|
|
);
|
|
assert.strictEqual(activeElems.length, 1);
|
|
assert.includesClass(
|
|
rootElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.strictEqual(document.activeElement, rootElem);
|
|
});
|
|
|
|
test('then focusNode() and finish ephemeral callback correctly sets new active state', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeGroupForEphemeralFocus',
|
|
);
|
|
const finishFocusCallback =
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
this.focusManager.focusNode(this.testFocusableGroup2Node1);
|
|
finishFocusCallback();
|
|
|
|
// The tree's root should now be the active element since focus changed between the start and
|
|
// end of the ephemeral flow.
|
|
const nodeElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
const activeElems = Array.from(
|
|
document.querySelectorAll(ACTIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
assert.strictEqual(activeElems.length, 1);
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.strictEqual(document.activeElement, nodeElem);
|
|
});
|
|
|
|
test('then DOM focus change and finish ephemeral callback correctly sets new active state', function () {
|
|
this.focusManager.registerTree(this.testFocusableTree2);
|
|
this.focusManager.registerTree(this.testFocusableGroup2);
|
|
this.focusManager.focusNode(this.testFocusableTree2Node1);
|
|
document.getElementById('testFocusableGroup2.node1').tabIndex = -1;
|
|
const ephemeralElement = document.getElementById(
|
|
'nonTreeGroupForEphemeralFocus',
|
|
);
|
|
const finishFocusCallback =
|
|
this.focusManager.takeEphemeralFocus(ephemeralElement);
|
|
|
|
document.getElementById('testFocusableGroup2.node1').focus();
|
|
finishFocusCallback();
|
|
|
|
// The tree's root should now be the active element since focus changed between the start and
|
|
// end of the ephemeral flow.
|
|
const nodeElem = this.testFocusableGroup2Node1.getFocusableElement();
|
|
const activeElems = Array.from(
|
|
document.querySelectorAll(ACTIVE_FOCUS_NODE_CSS_SELECTOR),
|
|
);
|
|
assert.strictEqual(
|
|
this.focusManager.getFocusedNode(),
|
|
this.testFocusableGroup2Node1,
|
|
);
|
|
assert.strictEqual(activeElems.length, 1);
|
|
assert.includesClass(
|
|
nodeElem.classList,
|
|
FocusManager.ACTIVE_FOCUS_NODE_CSS_CLASS_NAME,
|
|
);
|
|
assert.strictEqual(document.activeElement, nodeElem);
|
|
});
|
|
});
|
|
});
|