Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!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>