185 lines
6.9 KiB
HTML
185 lines
6.9 KiB
HTML
<!doctype html>
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
|
|
<button autofocus id="initialAutofocusTarget">Initial autofocus target</button>
|
|
|
|
<script type="module">
|
|
promise_setup(async () => {
|
|
// Get the overall autofocus processed flag to flip to true, so that
|
|
// we only test the navigation API-specific stuff.
|
|
await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)));
|
|
assert_equals(document.activeElement, initialAutofocusTarget, "Non-navigation API autofocus was processed");
|
|
initialAutofocusTarget.remove();
|
|
assert_equals(document.activeElement, document.body);
|
|
});
|
|
|
|
promise_test(async t => {
|
|
const decoy = createAndAppend(t);
|
|
const autofocusTarget = createAndAppend(t, { autofocus: true });
|
|
|
|
assert_equals(document.activeElement, document.body, "Start on body");
|
|
decoy.focus();
|
|
assert_equals(document.activeElement, decoy, "focus() worked");
|
|
|
|
navigation.addEventListener("navigate", e => {
|
|
e.intercept();
|
|
}, { once: true });
|
|
|
|
const { committed, finished } = navigation.navigate("#1");
|
|
|
|
await committed;
|
|
assert_equals(document.activeElement, decoy, "Focus stays on the non-autofocused button during the transition");
|
|
|
|
await finished;
|
|
assert_equals(document.activeElement, autofocusTarget, "Focus moves to the autofocused button after the transition");
|
|
}, "An element with autofocus, present before navigation, gets focused");
|
|
|
|
promise_test(async t => {
|
|
const autofocusTarget = createAndAppend(t, { autofocus: true });
|
|
const decoy = createAndAppend(t, { autofocus: true });
|
|
|
|
assert_equals(document.activeElement, document.body, "Start on body");
|
|
decoy.focus();
|
|
assert_equals(document.activeElement, decoy, "focus() worked");
|
|
|
|
navigation.addEventListener("navigate", e => {
|
|
e.intercept();
|
|
}, { once: true });
|
|
|
|
const { committed, finished } = navigation.navigate("#1");
|
|
|
|
await committed;
|
|
assert_equals(document.activeElement, decoy, "Focus stays on the initially-focused button during the transition");
|
|
|
|
await finished;
|
|
assert_equals(document.activeElement, autofocusTarget, "Focus moves to the first autofocused button after the transition");
|
|
}, "Two elements with autofocus, present before navigation; the first gets focused");
|
|
|
|
promise_test(async t => {
|
|
const decoy = createAndAppend(t);
|
|
const autofocusTarget = createAndAppend(t, { autofocus: true });
|
|
|
|
assert_equals(document.activeElement, document.body, "Start on body");
|
|
decoy.focus();
|
|
assert_equals(document.activeElement, decoy, "focus() worked");
|
|
|
|
navigation.addEventListener("navigate", e => {
|
|
e.intercept();
|
|
}, { once: true });
|
|
|
|
const { committed, finished } = navigation.navigate("#1");
|
|
|
|
await committed;
|
|
assert_equals(document.activeElement, decoy, "Focus stays on the non-autofocused button during the transition");
|
|
|
|
autofocusTarget.disabled = true;
|
|
|
|
await finished;
|
|
assert_equals(document.activeElement, document.body, "Focus gets reset after the transition");
|
|
}, "An element with autofocus, present before navigation but disabled before finished, does not get focused");
|
|
|
|
promise_test(async t => {
|
|
const decoy = createAndAppend(t);
|
|
const autofocusTarget = createAndAppend(t, { autofocus: true });
|
|
|
|
assert_equals(document.activeElement, document.body, "Start on body");
|
|
decoy.focus();
|
|
assert_equals(document.activeElement, decoy, "focus() worked");
|
|
|
|
navigation.addEventListener("navigate", e => {
|
|
e.intercept();
|
|
}, { once: true });
|
|
|
|
const { committed, finished } = navigation.navigate("#1");
|
|
|
|
await committed;
|
|
assert_equals(document.activeElement, decoy, "Focus stays on the non-autofocused button during the transition");
|
|
|
|
autofocusTarget.autofocus = false;
|
|
|
|
await finished;
|
|
assert_equals(document.activeElement, document.body, "Focus gets reset after the transition");
|
|
}, "An element with autofocus, present before navigation but with its autofocus attribute removed before finished, does not get focused");
|
|
|
|
promise_test(async t => {
|
|
const decoy = createAndAppend(t, { autofocus: true });
|
|
const autofocusTarget = createAndAppend(t, { autofocus: true });
|
|
|
|
assert_equals(document.activeElement, document.body, "Start on body");
|
|
decoy.focus();
|
|
assert_equals(document.activeElement, decoy, "focus() worked");
|
|
|
|
navigation.addEventListener("navigate", e => {
|
|
e.intercept();
|
|
}, { once: true });
|
|
|
|
const { committed, finished } = navigation.navigate("#1");
|
|
|
|
await committed;
|
|
assert_equals(document.activeElement, decoy, "Focus stays on the initially-focused button during the transition");
|
|
|
|
decoy.disabled = true;
|
|
assert_equals(document.activeElement, document.body, "Disabling the initially-focused button temporarily resets focus to the body");
|
|
|
|
await finished;
|
|
assert_equals(document.activeElement, autofocusTarget, "Focus moves to the second autofocused button after the transition");
|
|
}, "Two elements with autofocus, present before navigation, but the first gets disabled; the second gets focused");
|
|
|
|
promise_test(async t => {
|
|
const decoy = createAndAppend(t);
|
|
|
|
assert_equals(document.activeElement, document.body, "Start on body");
|
|
decoy.focus();
|
|
assert_equals(document.activeElement, decoy, "focus() worked");
|
|
|
|
navigation.addEventListener("navigate", e => {
|
|
e.intercept();
|
|
}, { once: true });
|
|
|
|
const { committed, finished } = navigation.navigate("#1");
|
|
|
|
await committed;
|
|
assert_equals(document.activeElement, decoy, "Focus stays on the non-autofocused button during the transition");
|
|
|
|
const autofocusTarget = createAndAppend(t, { autofocus: true });
|
|
|
|
await finished;
|
|
assert_equals(document.activeElement, autofocusTarget, "Focus moves to the autofocused button after the transition");
|
|
}, "An element with autofocus, introduced between committed and finished, gets focused");
|
|
|
|
promise_test(async t => {
|
|
const decoy = createAndAppend(t);
|
|
|
|
assert_equals(document.activeElement, document.body, "Start on body");
|
|
decoy.focus();
|
|
assert_equals(document.activeElement, decoy, "focus() worked");
|
|
|
|
navigation.addEventListener("navigate", e => {
|
|
e.intercept();
|
|
}, { once: true });
|
|
|
|
const { committed, finished } = navigation.navigate("#1");
|
|
|
|
await committed;
|
|
assert_equals(document.activeElement, decoy, "Focus stays on the non-autofocused button during the transition");
|
|
|
|
await finished;
|
|
assert_equals(document.activeElement, document.body, "Focus gets reset after the transition");
|
|
|
|
const autofocusTarget = createAndAppend(t, { autofocus: true });
|
|
|
|
await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)));
|
|
assert_equals(document.activeElement, document.body, "Focus stays reset two animation frames after the transition");
|
|
}, "An element with autofocus, introduced after finished, does not get focused");
|
|
|
|
function createAndAppend(t, props) {
|
|
const element = document.createElement("button");
|
|
Object.assign(element, props);
|
|
|
|
document.body.append(element);
|
|
t.add_cleanup(() => { element.remove(); });
|
|
|
|
return element;
|
|
}
|
|
</script>
|