Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 54 additions & 17 deletions navigation-api/focus-reset/autofocus.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<meta name="variant" content="?delayed-checkpoint">
<meta name="variant" content="?same-checkpoint">

<button autofocus id="initialAutofocusTarget">Initial autofocus target</button>

<script type="module">

const delayed = location.search === "?delayed-checkpoint";

function createExpected(t, decoy, autofocusTarget) {
const handler = delayed ? { handler: () => new Promise(r => t.step_timeout(r, 0)) } : {};
const expectedDecoy = delayed ? decoy : autofocusTarget;
const decoyMessage = delayed ? "Focus moves to the autofocused button after the transition" : "Focus stays on the non-autofocused button after the transition";
const expectedBody = delayed ? document.body : expectedDecoy;
const bodyMessage = delayed ? "Focus gets reset after the transition" : "Focus moves to the autofocused button after the transition";

return { handler, expectedDecoy, decoyMessage, expectedBody, bodyMessage };
}

promise_setup(async () => {
// Get the overall autofocus processed flag to flip to true, so that
// we only test the navigation API-specific stuff.
Expand All @@ -22,14 +37,15 @@
decoy.focus();
assert_equals(document.activeElement, decoy, "focus() worked");

const { handler, expectedDecoy, decoyMessage } = createExpected(t, decoy, autofocusTarget);
navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept(handler);
}, { 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");
assert_equals(document.activeElement, expectedDecoy, decoyMessage);

await finished;
assert_equals(document.activeElement, autofocusTarget, "Focus moves to the autofocused button after the transition");
Expand All @@ -43,14 +59,15 @@
decoy.focus();
assert_equals(document.activeElement, decoy, "focus() worked");

const { handler, expectedDecoy, decoyMessage } = createExpected(t, decoy, autofocusTarget);
navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept(handler);
}, { 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");
assert_equals(document.activeElement, expectedDecoy, decoyMessage);

await finished;
assert_equals(document.activeElement, autofocusTarget, "Focus moves to the first autofocused button after the transition");
Expand All @@ -64,19 +81,20 @@
decoy.focus();
assert_equals(document.activeElement, decoy, "focus() worked");

const { handler, expectedDecoy, decoyMessage, expectedBody, bodyMessage } = createExpected(t, decoy, autofocusTarget);
navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept(handler);
}, { 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");
assert_equals(document.activeElement, expectedDecoy, decoyMessage);

autofocusTarget.disabled = true;

await finished;
assert_equals(document.activeElement, document.body, "Focus gets reset after the transition");
assert_equals(document.activeElement, expectedBody, bodyMessage);
}, "An element with autofocus, present before navigation but disabled before finished, does not get focused");

promise_test(async t => {
Expand All @@ -87,19 +105,20 @@
decoy.focus();
assert_equals(document.activeElement, decoy, "focus() worked");

const { handler, expectedDecoy, decoyMessage, expectedBody, bodyMessage } = createExpected(t, decoy, autofocusTarget);
navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept(handler);
}, { 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");
assert_equals(document.activeElement, expectedDecoy, decoyMessage);

autofocusTarget.autofocus = false;

await finished;
assert_equals(document.activeElement, document.body, "Focus gets reset after the transition");
assert_equals(document.activeElement, expectedBody, bodyMessage);
}, "An element with autofocus, present before navigation but with its autofocus attribute removed before finished, does not get focused");

promise_test(async t => {
Expand All @@ -110,8 +129,9 @@
decoy.focus();
assert_equals(document.activeElement, decoy, "focus() worked");

const { handler } = createExpected(t, decoy, autofocusTarget);
navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept(handler);
}, { once: true });

const { committed, finished } = navigation.navigate("#1");
Expand All @@ -122,29 +142,45 @@
decoy.disabled = true;

await finished;
assert_equals(document.activeElement, autofocusTarget, "Focus moves to the second autofocused button after the transition");

if (delayed) {
assert_equals(document.activeElement, autofocusTarget, "Focus moves to the second autofocused button after the transition");
} else {
assert_equals(document.activeElement, decoy, "Focus stays on the initially-focused button during the transition");
}
}, "Two elements with autofocus, present before navigation, but the first gets disabled; the second gets focused");

promise_test(async t => {
if (delayed) {
assert_true(delayed, "This is only relevant for non-finished ")
return;
}
const decoy = createAndAppend(t);

assert_equals(document.activeElement, document.body, "Start on body");
decoy.focus();
assert_equals(document.activeElement, decoy, "focus() worked");

const { handler } = createExpected(t, decoy, document.body);
navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept(() => {
t.step_timeout(handler, 0)
});
}, { 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");
assert_equals(document.activeElement, document.body, "Focus gets reset after the transition");

const autofocusTarget = createAndAppend(t, { autofocus: true });

await finished;
assert_equals(document.activeElement, autofocusTarget, "Focus moves to the autofocused button after the transition");
assert_equals(document.activeElement, document.body, "Focus gets reset after the transition");

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 between committed and finished, gets focused");

promise_test(async t => {
Expand All @@ -154,14 +190,15 @@
decoy.focus();
assert_equals(document.activeElement, decoy, "focus() worked");

const { handler } = createExpected(t, decoy, document.body);
navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept(handler);
}, { 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");
assert_equals(document.activeElement, delayed ? decoy : document.body, delayed ? "Focus stays on the non-autofocused button during the transition" : "Focus gets reset after the transition");

await finished;
assert_equals(document.activeElement, document.body, "Focus gets reset after the transition");
Expand Down
8 changes: 4 additions & 4 deletions navigation-api/focus-reset/basic.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@

testFocusWasReset(t => {
navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept({ handler: () => new Promise(r => t.step_timeout(r, 0)) });
}, { once: true });
}, "Resets the focus when no focusReset option is provided");

testFocusWasReset(t => {
navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept({ handler: () => new Promise(r => t.step_timeout(r, 0)) });
}, { once: true });
}, "Resets the focus when focusReset is explicitly set to undefined");

Expand All @@ -45,13 +45,13 @@

testFocusWasReset(t => {
navigation.addEventListener("navigate", e => {
e.intercept({ handler: () => Promise.reject() });
e.intercept({ handler: () => new Promise((_, r) => t.step_timeout(r, 0)) });
}, { once: true });
}, "Resets the focus when no focusReset option is provided (rejected promise)");

testFocusWasReset(t => {
navigation.addEventListener("navigate", e => {
e.intercept({ focusReset: "after-transition" });
e.intercept({ handler: () => new Promise(r => t.step_timeout(r, 0)), focusReset: "after-transition" });
}, { once: true });
}, "Resets the focus when focusReset is explicitly set to 'after-transition'");

Expand Down
6 changes: 3 additions & 3 deletions navigation-api/focus-reset/multiple-intercept.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

testFocusWasReset(t => {
navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept({ handler: () => new Promise(r => t.step_timeout(r, 0)) });
}, { once: true });

navigation.addEventListener("navigate", e => {
Expand Down Expand Up @@ -43,13 +43,13 @@
}, { once: true });

navigation.addEventListener("navigate", e => {
e.intercept();
e.intercept({ handler: () => new Promise(r => t.step_timeout(r, 0)) });
}, { once: true });
}, "after-transition + (not provided)");

testFocusWasReset(t => {
navigation.addEventListener("navigate", e => {
e.intercept({ focusReset: "manual" });
e.intercept({ handler: () => new Promise(r => t.step_timeout(r, 0)), focusReset: "manual" });
}, { once: true });

navigation.addEventListener("navigate", e => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@
["navigate", "", null],
["currententrychange", "#1", { from, navigationType: "push" }],
["handler run", "#1", { from, navigationType: "push" }],
["promise microtask", "#1", { from, navigationType: "push" }],
["AbortSignal abort", "#1", { from, navigationType: "push" }],
["navigateerror", "#1", { from, navigationType: "push" }],
["promise microtask", "#1", null],
["transition.finished rejected", "#1", null],
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
["navigate", "", null],
["currententrychange", "#1", { from, navigationType: "push" }],
["handler run", "#1", { from, navigationType: "push" }],
["promise microtask", "#1", { from, navigationType: "push" }],
["navigatesuccess", "#1", { from, navigationType: "push" }],
["promise microtask", "#1", null],
["transition.finished fulfilled", "#1", null],
]);
}, "event and promise ordering for <a download> intercepted by intercept()");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@
["navigate", "", null],
["currententrychange", "#1", { from, navigationType: "push" }],
["handler run", "#1", { from, navigationType: "push" }],
["promise microtask", "#1", { from, navigationType: "push" }],
["AbortSignal abort", "#1", { from, navigationType: "push" }],
["navigateerror", "#1", { from, navigationType: "push" }],
["promise microtask", "#1", null],
["transition.finished rejected", "#1", null],
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
["navigate", "", null],
["currententrychange", "#1", { from, navigationType: "push" }],
["handler run", "#1", { from, navigationType: "push" }],
["promise microtask", "#1", { from, navigationType: "push" }],
["navigatesuccess", "#1", { from, navigationType: "push" }],
["promise microtask", "#1", null],
["transition.finished fulfilled", "#1", null],
]);
}, "event and promise ordering for location.href setter intercepted by intercept()");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,19 @@
["navigate", "", null],
["currententrychange", "#1", { from: fromStart, navigationType: "push" }],
["handler run", "#1", { from: fromStart, navigationType: "push" }],
["committed fulfilled 1", "#1", { from: fromStart, navigationType: "push" }],
["transition.committed fulfilled 1", "#1", { from: fromStart, navigationType: "push" }],
["promise microtask", "#1", { from: fromStart, navigationType: "push" }],
["navigatesuccess", "#1", { from: fromStart, navigationType: "push" }],
["committed fulfilled 1", "#1", null],
["transition.committed fulfilled 1", "#1", null],
["promise microtask", "#1", null],
["finished fulfilled 1", "#1", null],
["transition.finished fulfilled", "#1", null],

["navigate", "#1", null],
["currententrychange", "#2", { from: fromHash1, navigationType: "push" }],
["handler run", "#2", { from: fromHash1, navigationType: "push" }],
["committed fulfilled 2", "#2", { from: fromHash1, navigationType: "push" }],
["transition.committed fulfilled 2", "#2", { from: fromHash1, navigationType: "push" }],
["navigatesuccess", "#2", { from: fromHash1, navigationType: "push" }],
["committed fulfilled 2", "#2", null],
["transition.committed fulfilled 2", "#2", null],
["finished fulfilled 2", "#2", null],
["transition.finished fulfilled", "#2", null]
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
["navigate", "", null],
["currententrychange", "#1", { from, navigationType: "push" }],
["handler run", "#1", { from, navigationType: "push" }],
["committed fulfilled", "#1", { from, navigationType: "push" }],
["transition.committed fulfilled", "#1", { from, navigationType: "push" }],
["promise microtask", "#1", { from, navigationType: "push" }],
["navigatesuccess", "#1", { from, navigationType: "push" }],
["committed fulfilled", "#1", null],
["transition.committed fulfilled", "#1", null],
["promise microtask", "#1", null],
["finished fulfilled", "#1", null],
["transition.finished fulfilled", "#1", null],
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@
["navigate", "", null],
["currententrychange", "#1", { from, navigationType: "push" }],
["handler run", "#1", { from, navigationType: "push" }],
["committed fulfilled", "#1", { from, navigationType: "push" }],
["transition.committed fulfilled", "#1", { from, navigationType: "push" }],
["promise microtask", "#1", { from, navigationType: "push" }],
["AbortSignal abort", "#1", { from, navigationType: "push" }],
["navigateerror", "#1", { from, navigationType: "push" }],
["committed fulfilled", "#1", null],
["transition.committed fulfilled", "#1", null],
["promise microtask", "#1", null],
["finished rejected", "#1", null],
["transition.finished rejected", "#1", null],
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
/* event name, location.hash value, navigation.transition properties */
["navigate", "", null],
["currententrychange", "#1", null],
["navigatesuccess", "#1", null],
["committed fulfilled", "#1", null],
["promise microtask", "#1", null],
["navigatesuccess", "#1", null],
["finished fulfilled", "#1", null],
]);
}, "event and promise ordering for same-document navigation.navigate()");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@
["navigate", "", null],
["currententrychange", "", { from, navigationType: "reload" }],
["handler run", "", { from, navigationType: "reload" }],
["committed fulfilled", "", { from, navigationType: "reload" }],
["transition.committed fulfilled", "", { from, navigationType: "reload" }],
["promise microtask", "", { from, navigationType: "reload" }],
["AbortSignal abort", "", { from, navigationType: "reload" }],
["navigateerror", "", { from, navigationType: "reload" }],
["committed fulfilled", "", null],
["transition.committed fulfilled", "", null],
["promise microtask", "", null],
["finished rejected", "", null],
["transition.finished rejected", "", null],
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
["navigate", "", null],
["currententrychange", "", { from, navigationType: "reload" }],
["handler run", "", { from, navigationType: "reload" }],
["committed fulfilled", "", { from, navigationType: "reload" }],
["transition.committed fulfilled", "", { from, navigationType: "reload" }],
["promise microtask", "", { from, navigationType: "reload" }],
["navigatesuccess", "", { from, navigationType: "reload" }],
["committed fulfilled", "", null],
["transition.committed fulfilled", "", null],
["promise microtask", "", null],
["finished fulfilled", "", null],
["transition.finished fulfilled", "", null],
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@
["navigate", "", null],
["currententrychange", "", { from, navigationType: "reload" }],
["handler run", "", { from, navigationType: "reload" }],
["committed fulfilled", "", { from, navigationType: "reload" }],
["transition.committed fulfilled", "", { from, navigationType: "reload" }],
["promise microtask", "", { from, navigationType: "reload" }],
["navigatesuccess", "", { from, navigationType: "reload" }],
["committed fulfilled", "", null],
["transition.committed fulfilled", "", null],
["promise microtask", "", null],
["finished fulfilled", "", null],
["transition.finished fulfilled", "", null],
]);
Expand Down
Loading