autofocus.html (6889B)
1 <!doctype html> 2 <script src="/resources/testharness.js"></script> 3 <script src="/resources/testharnessreport.js"></script> 4 5 <button autofocus id="initialAutofocusTarget">Initial autofocus target</button> 6 7 <script type="module"> 8 promise_setup(async () => { 9 // Get the overall autofocus processed flag to flip to true, so that 10 // we only test the navigation API-specific stuff. 11 await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r))); 12 assert_equals(document.activeElement, initialAutofocusTarget, "Non-navigation API autofocus was processed"); 13 initialAutofocusTarget.remove(); 14 assert_equals(document.activeElement, document.body); 15 }); 16 17 promise_test(async t => { 18 const decoy = createAndAppend(t); 19 const autofocusTarget = createAndAppend(t, { autofocus: true }); 20 21 assert_equals(document.activeElement, document.body, "Start on body"); 22 decoy.focus(); 23 assert_equals(document.activeElement, decoy, "focus() worked"); 24 25 navigation.addEventListener("navigate", e => { 26 e.intercept(); 27 }, { once: true }); 28 29 const { committed, finished } = navigation.navigate("#1"); 30 31 await committed; 32 assert_equals(document.activeElement, decoy, "Focus stays on the non-autofocused button during the transition"); 33 34 await finished; 35 assert_equals(document.activeElement, autofocusTarget, "Focus moves to the autofocused button after the transition"); 36 }, "An element with autofocus, present before navigation, gets focused"); 37 38 promise_test(async t => { 39 const autofocusTarget = createAndAppend(t, { autofocus: true }); 40 const decoy = createAndAppend(t, { autofocus: true }); 41 42 assert_equals(document.activeElement, document.body, "Start on body"); 43 decoy.focus(); 44 assert_equals(document.activeElement, decoy, "focus() worked"); 45 46 navigation.addEventListener("navigate", e => { 47 e.intercept(); 48 }, { once: true }); 49 50 const { committed, finished } = navigation.navigate("#1"); 51 52 await committed; 53 assert_equals(document.activeElement, decoy, "Focus stays on the initially-focused button during the transition"); 54 55 await finished; 56 assert_equals(document.activeElement, autofocusTarget, "Focus moves to the first autofocused button after the transition"); 57 }, "Two elements with autofocus, present before navigation; the first gets focused"); 58 59 promise_test(async t => { 60 const decoy = createAndAppend(t); 61 const autofocusTarget = createAndAppend(t, { autofocus: true }); 62 63 assert_equals(document.activeElement, document.body, "Start on body"); 64 decoy.focus(); 65 assert_equals(document.activeElement, decoy, "focus() worked"); 66 67 navigation.addEventListener("navigate", e => { 68 e.intercept(); 69 }, { once: true }); 70 71 const { committed, finished } = navigation.navigate("#1"); 72 73 await committed; 74 assert_equals(document.activeElement, decoy, "Focus stays on the non-autofocused button during the transition"); 75 76 autofocusTarget.disabled = true; 77 78 await finished; 79 assert_equals(document.activeElement, document.body, "Focus gets reset after the transition"); 80 }, "An element with autofocus, present before navigation but disabled before finished, does not get focused"); 81 82 promise_test(async t => { 83 const decoy = createAndAppend(t); 84 const autofocusTarget = createAndAppend(t, { autofocus: true }); 85 86 assert_equals(document.activeElement, document.body, "Start on body"); 87 decoy.focus(); 88 assert_equals(document.activeElement, decoy, "focus() worked"); 89 90 navigation.addEventListener("navigate", e => { 91 e.intercept(); 92 }, { once: true }); 93 94 const { committed, finished } = navigation.navigate("#1"); 95 96 await committed; 97 assert_equals(document.activeElement, decoy, "Focus stays on the non-autofocused button during the transition"); 98 99 autofocusTarget.autofocus = false; 100 101 await finished; 102 assert_equals(document.activeElement, document.body, "Focus gets reset after the transition"); 103 }, "An element with autofocus, present before navigation but with its autofocus attribute removed before finished, does not get focused"); 104 105 promise_test(async t => { 106 const decoy = createAndAppend(t, { autofocus: true }); 107 const autofocusTarget = createAndAppend(t, { autofocus: true }); 108 109 assert_equals(document.activeElement, document.body, "Start on body"); 110 decoy.focus(); 111 assert_equals(document.activeElement, decoy, "focus() worked"); 112 113 navigation.addEventListener("navigate", e => { 114 e.intercept(); 115 }, { once: true }); 116 117 const { committed, finished } = navigation.navigate("#1"); 118 119 await committed; 120 assert_equals(document.activeElement, decoy, "Focus stays on the initially-focused button during the transition"); 121 122 decoy.disabled = true; 123 124 await finished; 125 assert_equals(document.activeElement, autofocusTarget, "Focus moves to the second autofocused button after the transition"); 126 }, "Two elements with autofocus, present before navigation, but the first gets disabled; the second gets focused"); 127 128 promise_test(async t => { 129 const decoy = createAndAppend(t); 130 131 assert_equals(document.activeElement, document.body, "Start on body"); 132 decoy.focus(); 133 assert_equals(document.activeElement, decoy, "focus() worked"); 134 135 navigation.addEventListener("navigate", e => { 136 e.intercept(); 137 }, { once: true }); 138 139 const { committed, finished } = navigation.navigate("#1"); 140 141 await committed; 142 assert_equals(document.activeElement, decoy, "Focus stays on the non-autofocused button during the transition"); 143 144 const autofocusTarget = createAndAppend(t, { autofocus: true }); 145 146 await finished; 147 assert_equals(document.activeElement, autofocusTarget, "Focus moves to the autofocused button after the transition"); 148 }, "An element with autofocus, introduced between committed and finished, gets focused"); 149 150 promise_test(async t => { 151 const decoy = createAndAppend(t); 152 153 assert_equals(document.activeElement, document.body, "Start on body"); 154 decoy.focus(); 155 assert_equals(document.activeElement, decoy, "focus() worked"); 156 157 navigation.addEventListener("navigate", e => { 158 e.intercept(); 159 }, { once: true }); 160 161 const { committed, finished } = navigation.navigate("#1"); 162 163 await committed; 164 assert_equals(document.activeElement, decoy, "Focus stays on the non-autofocused button during the transition"); 165 166 await finished; 167 assert_equals(document.activeElement, document.body, "Focus gets reset after the transition"); 168 169 const autofocusTarget = createAndAppend(t, { autofocus: true }); 170 171 await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r))); 172 assert_equals(document.activeElement, document.body, "Focus stays reset two animation frames after the transition"); 173 }, "An element with autofocus, introduced after finished, does not get focused"); 174 175 function createAndAppend(t, props) { 176 const element = document.createElement("button"); 177 Object.assign(element, props); 178 179 document.body.append(element); 180 t.add_cleanup(() => { element.remove(); }); 181 182 return element; 183 } 184 </script>