1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
<!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>
|