-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
App history: basic focusReset support
Based on the draft at WICG/navigation-api#201. This includes handling multiple conflicting focusReset options, with a console warning if necessary. Limitations, to be addressed in future commits: * This does not take into account autofocus="" elements. * This will reset focus even if the user has moved focus in the meantime. Bug: 1183545 Change-Id: I1eae4fc58af653fa7e463a1346a9bebc9536a59f Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3441109 Reviewed-by: Nate Chapin <japhet@chromium.org> Commit-Queue: Domenic Denicola <domenic@chromium.org> Cr-Commit-Position: refs/heads/main@{#970838}
- Loading branch information
1 parent
af3b994
commit e6bbf05
Showing
3 changed files
with
176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<!doctype html> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
|
||
<script type="module"> | ||
import { testFocusWasReset, testFocusWasNotReset } from "./resources/helpers.mjs"; | ||
|
||
test(() => { | ||
let throwAssertionHappened = false; | ||
|
||
appHistory.addEventListener("navigate", e => { | ||
assert_throws_js(TypeError, () => { | ||
e.transitionWhile(Promise.resolve(), { focusReset: "invalid" }); | ||
}); | ||
throwAssertionHappened = true; | ||
}, { once: true }); | ||
|
||
appHistory.navigate("#1"); | ||
assert_true(throwAssertionHappened); | ||
}, "Invalid values for focusReset throw"); | ||
|
||
testFocusWasNotReset(() => { | ||
// Intentionally left blank. | ||
}, "Does not reset the focus when no navigate handler is present"); | ||
|
||
testFocusWasReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve()); | ||
}, { once: true }); | ||
}, "Resets the focus when no focusReset option is provided"); | ||
|
||
testFocusWasReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve()); | ||
}, { once: true }); | ||
}, "Resets the focus when focusReset is explicitly set to undefined"); | ||
|
||
testFocusWasReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(new Promise(r => t.step_timeout(r, 5))); | ||
}, { once: true }); | ||
}, "Resets the focus when no focusReset option is provided (nontrivial fulfilled promise)"); | ||
|
||
testFocusWasReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.reject()); | ||
}, { once: true }); | ||
}, "Resets the focus when no focusReset option is provided (rejected promise)"); | ||
|
||
testFocusWasReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile( | ||
Promise.resolve(), | ||
{ focusReset: "after-transition" } | ||
); | ||
}, { once: true }); | ||
}, "Resets the focus when focusReset is explicitly set to 'after-transition'"); | ||
|
||
testFocusWasNotReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve(), { focusReset: "manual" }); | ||
}); | ||
}, "Does not reset the focus when focusReset is set to 'manual'"); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<!doctype html> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
|
||
<script type="module"> | ||
import { testFocusWasReset, testFocusWasNotReset } from "./resources/helpers.mjs"; | ||
|
||
testFocusWasReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve()); | ||
}, { once: true }); | ||
|
||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve(), { focusReset: "after-transition" }); | ||
}, { once: true }); | ||
}, "(not provided) + after-transition"); | ||
|
||
testFocusWasNotReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve()); | ||
}, { once: true }); | ||
|
||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve(), { focusReset: "manual" }); | ||
}, { once: true }); | ||
}, "(not provided) + manual"); | ||
|
||
testFocusWasNotReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve(), { focusReset: "after-transition" }); | ||
}, { once: true }); | ||
|
||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve(), { focusReset: "manual" }); | ||
}, { once: true }); | ||
}, "after-transition + manual"); | ||
|
||
testFocusWasReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve(), { focusReset: "after-transition" }); | ||
}, { once: true }); | ||
|
||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve()); | ||
}, { once: true }); | ||
}, "after-transition + (not provided)"); | ||
|
||
testFocusWasReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve(), { focusReset: "manual" }); | ||
}, { once: true }); | ||
|
||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve(), { focusReset: "after-transition" }); | ||
}, { once: true }); | ||
}, "manual + after-transition"); | ||
|
||
testFocusWasNotReset(t => { | ||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve(), { focusReset: "manual" }); | ||
}, { once: true }); | ||
|
||
appHistory.addEventListener("navigate", e => { | ||
e.transitionWhile(Promise.resolve()); | ||
}, { once: true }); | ||
}, "manual + (not provided)"); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Usage note: if you use these more than once in a given file, be sure to | ||
// clean up any navigate event listeners, e.g. by using { once: true }, between | ||
// tests. | ||
|
||
export function testFocusWasReset(setupFunc, description) { | ||
promise_test(async t => { | ||
setupFunc(t); | ||
|
||
const button = document.body.appendChild(document.createElement("button")); | ||
t.add_cleanup(() => { button.remove(); }); | ||
|
||
assert_equals(document.activeElement, document.body, "Start on body"); | ||
button.focus(); | ||
assert_equals(document.activeElement, button, "focus() worked"); | ||
|
||
const { committed, finished } = appHistory.navigate("#" + location.hash.substring(1) + "1"); | ||
|
||
await committed; | ||
assert_equals(document.activeElement, button, "Focus stays on the button during the transition"); | ||
|
||
await finished.catch(() => {}); | ||
assert_equals(document.activeElement, document.body, "Focus reset after the transition"); | ||
}, description); | ||
} | ||
|
||
export function testFocusWasNotReset(setupFunc, description) { | ||
promise_test(async t => { | ||
setupFunc(t); | ||
|
||
const button = document.body.appendChild(document.createElement("button")); | ||
t.add_cleanup(() => { button.remove(); }); | ||
|
||
assert_equals(document.activeElement, document.body, "Start on body"); | ||
button.focus(); | ||
assert_equals(document.activeElement, button, "focus() worked"); | ||
|
||
const { committed, finished } = appHistory.navigate("#" + location.hash.substring(1) + "1"); | ||
|
||
await committed; | ||
assert_equals(document.activeElement, button, "Focus stays on the button during the transition"); | ||
|
||
await finished.catch(() => {}); | ||
assert_equals(document.activeElement, button, "Focus stays on the button after the transition"); | ||
}, description); | ||
} |