327 lines
9.1 KiB
HTML
327 lines
9.1 KiB
HTML
<!DOCTYPE html>
|
|
<meta name="timeout" content="long">
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="/resources/testdriver.js"></script>
|
|
<script src="/resources/testdriver-vendor.js"></script>
|
|
<script src="/resources/testdriver-actions.js"></script>
|
|
<script src="resources/shadow-dom.js"></script>
|
|
<script src="resources/focus-utils.js"></script>
|
|
|
|
<p>This tests TAB focus navigation with delegatesFocus flag on shadow hosts</p>
|
|
<pre id="console"></pre>
|
|
<div id="sandbox"></div>
|
|
<script>
|
|
|
|
function prepareDOMTree(parent, mode, tabindex, delegatesFocus) {
|
|
parent.innerHTML = `
|
|
<div id="testform">
|
|
<input id="input-before">
|
|
<div id="host-div">
|
|
<input id="inner-input">
|
|
</div>
|
|
<input id="input-after">
|
|
</div>
|
|
`;
|
|
const hostDiv = document.getElementById('host-div');
|
|
const shadowRoot = hostDiv.attachShadow({ mode, delegatesFocus });
|
|
|
|
const inputBefore = document.getElementById('input-before');
|
|
const innerInput = document.getElementById('inner-input');
|
|
const inputAfter = document.getElementById('input-after');
|
|
shadowRoot.appendChild(innerInput);
|
|
|
|
if (tabindex !== null)
|
|
hostDiv.tabIndex = tabindex;
|
|
|
|
return {
|
|
hostDiv,
|
|
shadowRoot,
|
|
inputBefore,
|
|
innerInput,
|
|
inputAfter,
|
|
};
|
|
|
|
}
|
|
|
|
promise_test(async () => {
|
|
const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', null, false);
|
|
assert_false(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, -1);
|
|
|
|
const elements = [
|
|
'input-before',
|
|
'host-div/inner-input',
|
|
'input-after',
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional(elements);
|
|
}, 'Testing tab navigation order with mode open, no tabindex and delegatesFocus=false.');
|
|
|
|
promise_test(async () => {
|
|
const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', null, true);
|
|
assert_true(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, -1);
|
|
|
|
const elements = [
|
|
'input-before',
|
|
'host-div/inner-input',
|
|
'input-after',
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional(elements);
|
|
}, 'Testing tab navigation order with mode open, no tabindex and delegatesFocus=true.');
|
|
|
|
promise_test(async () => {
|
|
const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', 0, false);
|
|
assert_false(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, 0);
|
|
|
|
const elements = [
|
|
'input-before',
|
|
'host-div',
|
|
'host-div/inner-input',
|
|
'input-after',
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional(elements);
|
|
}, 'Testing tab navigation order with mode open, tabindex=0 and delegatesFocus=false.');
|
|
|
|
promise_test(async () => {
|
|
const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', 0, true);
|
|
assert_true(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, 0);
|
|
|
|
const elements = [
|
|
'input-before',
|
|
// 'host-div', // should skip host when delegatesFocus=true
|
|
'host-div/inner-input',
|
|
'input-after',
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional(elements);
|
|
}, 'Testing tab navigation order with mode open, tabindex=0 and delegatesFocus=true.');
|
|
|
|
promise_test(async () => {
|
|
const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', -1, false);
|
|
assert_false(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, -1);
|
|
|
|
const elements = [
|
|
'input-before',
|
|
'input-after',
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional(elements);
|
|
}, 'Testing tab navigation order with mode open, tabindex=-1 and delegatesFocus=false.');
|
|
|
|
promise_test(async () => {
|
|
const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', -1, true);
|
|
assert_true(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, -1);
|
|
|
|
const elements = [
|
|
'input-before',
|
|
// 'host-div/inner-input', // The whole shadow tree should be skipped
|
|
'input-after',
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional(elements);
|
|
}, 'Testing tab navigation order with mode open, tabindex=-1 and delegatesFocus=true.');
|
|
|
|
promise_test(async () => {
|
|
const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', 1, false);
|
|
assert_false(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, 1);
|
|
|
|
const elements = [
|
|
'host-div',
|
|
'host-div/inner-input',
|
|
'input-before',
|
|
'input-after',
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional(elements);
|
|
}, 'Testing tab navigation order with mode open, tabindex=1 and delegatesFocus=false.');
|
|
|
|
promise_test(async () => {
|
|
const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', 1, true);
|
|
assert_true(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, 1);
|
|
|
|
const elements = [
|
|
// 'host-div', // should skip host when delegatesFocus=true
|
|
'host-div/inner-input',
|
|
'input-before',
|
|
'input-after',
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional(elements);
|
|
}, 'Testing tab navigation order with mode open, tabindex=1 and delegatesFocus=true.');
|
|
|
|
|
|
promise_test(async () => {
|
|
const {
|
|
hostDiv,
|
|
shadowRoot,
|
|
inputBefore,
|
|
innerInput,
|
|
inputAfter,
|
|
} = prepareDOMTree(sandbox, 'closed', null, false);
|
|
assert_false(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, -1);
|
|
|
|
const elements = [
|
|
[inputBefore],
|
|
[innerInput, shadowRoot],
|
|
[inputAfter],
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional_with_shadow_root(elements, false);
|
|
}, 'Testing tab navigation order with mode closed, no tabindex and delegatesFocus=false.');
|
|
|
|
promise_test(async () => {
|
|
const {
|
|
hostDiv,
|
|
shadowRoot,
|
|
inputBefore,
|
|
innerInput,
|
|
inputAfter,
|
|
} = prepareDOMTree(sandbox, 'closed', null, true);
|
|
assert_true(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, -1);
|
|
|
|
const elements = [
|
|
[inputBefore],
|
|
[innerInput, shadowRoot],
|
|
[inputAfter],
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional_with_shadow_root(elements, false);
|
|
}, 'Testing tab navigation order with mode closed, no tabindex and delegatesFocus=true.');
|
|
|
|
promise_test(async () => {
|
|
const {
|
|
hostDiv,
|
|
shadowRoot,
|
|
inputBefore,
|
|
innerInput,
|
|
inputAfter,
|
|
} = prepareDOMTree(sandbox, 'closed', 0, false);
|
|
assert_false(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, 0);
|
|
|
|
const elements = [
|
|
[inputBefore],
|
|
[hostDiv],
|
|
[innerInput, shadowRoot],
|
|
[inputAfter],
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional_with_shadow_root(elements, false);
|
|
}, 'Testing tab navigation order with mode closed, tabindex=0 and delegatesFocus=false.');
|
|
|
|
promise_test(async () => {
|
|
const {
|
|
hostDiv,
|
|
shadowRoot,
|
|
inputBefore,
|
|
innerInput,
|
|
inputAfter,
|
|
} = prepareDOMTree(sandbox, 'closed', 0, true);
|
|
assert_true(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, 0);
|
|
|
|
const elements = [
|
|
[inputBefore],
|
|
// [hostDiv], // should skip host when delegatesFocus=true
|
|
[innerInput, shadowRoot],
|
|
[inputAfter],
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional_with_shadow_root(elements, false);
|
|
}, 'Testing tab navigation order with mode closed, tabindex=0 and delegatesFocus=true.');
|
|
|
|
promise_test(async () => {
|
|
const {
|
|
hostDiv,
|
|
shadowRoot,
|
|
inputBefore,
|
|
innerInput,
|
|
inputAfter,
|
|
} = prepareDOMTree(sandbox, 'closed', -1, false);
|
|
assert_false(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, -1);
|
|
|
|
const elements = [
|
|
[inputBefore],
|
|
[inputAfter],
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional_with_shadow_root(elements, false);
|
|
}, 'Testing tab navigation order with mode closed, tabindex=-1 and delegatesFocus=false.');
|
|
|
|
promise_test(async () => {
|
|
const {
|
|
hostDiv,
|
|
shadowRoot,
|
|
inputBefore,
|
|
innerInput,
|
|
inputAfter,
|
|
} = prepareDOMTree(sandbox, 'closed', -1, true);
|
|
assert_true(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, -1);
|
|
|
|
const elements = [
|
|
[inputBefore],
|
|
// [innerInput, shadowRoot], // The whole shadow tree should be skipped
|
|
[inputAfter],
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional_with_shadow_root(elements, false);
|
|
}, 'Testing tab navigation order with mode closed, tabindex=-1 and delegatesFocus=true.');
|
|
|
|
promise_test(async () => {
|
|
const {
|
|
hostDiv,
|
|
shadowRoot,
|
|
inputBefore,
|
|
innerInput,
|
|
inputAfter,
|
|
} = prepareDOMTree(sandbox, 'closed', 1, false);
|
|
assert_false(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, 1);
|
|
|
|
const elements = [
|
|
[hostDiv],
|
|
[innerInput, shadowRoot],
|
|
[inputBefore],
|
|
[inputAfter],
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional_with_shadow_root(elements, false);
|
|
}, 'Testing tab navigation order with mode closed, tabindex=1 and delegatesFocus=false.');
|
|
|
|
promise_test(async () => {
|
|
const {
|
|
hostDiv,
|
|
shadowRoot,
|
|
inputBefore,
|
|
innerInput,
|
|
inputAfter,
|
|
} = prepareDOMTree(sandbox, 'closed', 1, true);
|
|
assert_true(shadowRoot.delegatesFocus);
|
|
assert_equals(hostDiv.tabIndex, 1);
|
|
|
|
const elements = [
|
|
// [hostDiv], // should skip host when delegatesFocus=true
|
|
[innerInput, shadowRoot],
|
|
[inputBefore],
|
|
[inputAfter],
|
|
];
|
|
|
|
await assert_focus_navigation_bidirectional_with_shadow_root(elements, false);
|
|
}, 'Testing tab navigation order with mode closed, tabindex=1 and delegatesFocus=true.');
|
|
|
|
|
|
</script>
|