focus-navigation-with-delegatesFocus.html (9283B)
1 <!DOCTYPE html> 2 <meta name="timeout" content="long"> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script src="/resources/testdriver.js"></script> 6 <script src="/resources/testdriver-vendor.js"></script> 7 <script src="/resources/testdriver-actions.js"></script> 8 <script src="resources/shadow-dom.js"></script> 9 <script src="resources/focus-utils.js"></script> 10 11 <p>This tests TAB focus navigation with delegatesFocus flag on shadow hosts</p> 12 <pre id="console"></pre> 13 <div id="sandbox"></div> 14 <script> 15 16 function prepareDOMTree(parent, mode, tabindex, delegatesFocus) { 17 parent.innerHTML = ` 18 <div id="testform"> 19 <input id="input-before"> 20 <div id="host-div"> 21 <input id="inner-input"> 22 </div> 23 <input id="input-after"> 24 </div> 25 `; 26 const hostDiv = document.getElementById('host-div'); 27 const shadowRoot = hostDiv.attachShadow({ mode, delegatesFocus }); 28 29 const inputBefore = document.getElementById('input-before'); 30 const innerInput = document.getElementById('inner-input'); 31 const inputAfter = document.getElementById('input-after'); 32 shadowRoot.appendChild(innerInput); 33 34 if (tabindex !== null) 35 hostDiv.tabIndex = tabindex; 36 37 return { 38 hostDiv, 39 shadowRoot, 40 inputBefore, 41 innerInput, 42 inputAfter, 43 }; 44 45 } 46 47 promise_test(async () => { 48 const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', null, false); 49 assert_false(shadowRoot.delegatesFocus); 50 assert_equals(hostDiv.tabIndex, -1); 51 52 const elements = [ 53 'input-before', 54 'host-div/inner-input', 55 'input-after', 56 ]; 57 58 await assert_focus_navigation_bidirectional(elements); 59 }, 'Testing tab navigation order with mode open, no tabindex and delegatesFocus=false.'); 60 61 promise_test(async () => { 62 const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', null, true); 63 assert_true(shadowRoot.delegatesFocus); 64 assert_equals(hostDiv.tabIndex, -1); 65 66 const elements = [ 67 'input-before', 68 'host-div/inner-input', 69 'input-after', 70 ]; 71 72 await assert_focus_navigation_bidirectional(elements); 73 }, 'Testing tab navigation order with mode open, no tabindex and delegatesFocus=true.'); 74 75 promise_test(async () => { 76 const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', 0, false); 77 assert_false(shadowRoot.delegatesFocus); 78 assert_equals(hostDiv.tabIndex, 0); 79 80 const elements = [ 81 'input-before', 82 'host-div', 83 'host-div/inner-input', 84 'input-after', 85 ]; 86 87 await assert_focus_navigation_bidirectional(elements); 88 }, 'Testing tab navigation order with mode open, tabindex=0 and delegatesFocus=false.'); 89 90 promise_test(async () => { 91 const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', 0, true); 92 assert_true(shadowRoot.delegatesFocus); 93 assert_equals(hostDiv.tabIndex, 0); 94 95 const elements = [ 96 'input-before', 97 // 'host-div', // should skip host when delegatesFocus=true 98 'host-div/inner-input', 99 'input-after', 100 ]; 101 102 await assert_focus_navigation_bidirectional(elements); 103 }, 'Testing tab navigation order with mode open, tabindex=0 and delegatesFocus=true.'); 104 105 promise_test(async () => { 106 const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', -1, false); 107 assert_false(shadowRoot.delegatesFocus); 108 assert_equals(hostDiv.tabIndex, -1); 109 110 const elements = [ 111 'input-before', 112 'input-after', 113 ]; 114 115 await assert_focus_navigation_bidirectional(elements); 116 }, 'Testing tab navigation order with mode open, tabindex=-1 and delegatesFocus=false.'); 117 118 promise_test(async () => { 119 const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', -1, true); 120 assert_true(shadowRoot.delegatesFocus); 121 assert_equals(hostDiv.tabIndex, -1); 122 123 const elements = [ 124 'input-before', 125 // 'host-div/inner-input', // The whole shadow tree should be skipped 126 'input-after', 127 ]; 128 129 await assert_focus_navigation_bidirectional(elements); 130 }, 'Testing tab navigation order with mode open, tabindex=-1 and delegatesFocus=true.'); 131 132 promise_test(async () => { 133 const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', 1, false); 134 assert_false(shadowRoot.delegatesFocus); 135 assert_equals(hostDiv.tabIndex, 1); 136 137 const elements = [ 138 'host-div', 139 'host-div/inner-input', 140 'input-before', 141 'input-after', 142 ]; 143 144 await assert_focus_navigation_bidirectional(elements); 145 }, 'Testing tab navigation order with mode open, tabindex=1 and delegatesFocus=false.'); 146 147 promise_test(async () => { 148 const { shadowRoot, hostDiv } = prepareDOMTree(sandbox, 'open', 1, true); 149 assert_true(shadowRoot.delegatesFocus); 150 assert_equals(hostDiv.tabIndex, 1); 151 152 const elements = [ 153 // 'host-div', // should skip host when delegatesFocus=true 154 'host-div/inner-input', 155 'input-before', 156 'input-after', 157 ]; 158 159 await assert_focus_navigation_bidirectional(elements); 160 }, 'Testing tab navigation order with mode open, tabindex=1 and delegatesFocus=true.'); 161 162 163 promise_test(async () => { 164 const { 165 hostDiv, 166 shadowRoot, 167 inputBefore, 168 innerInput, 169 inputAfter, 170 } = prepareDOMTree(sandbox, 'closed', null, false); 171 assert_false(shadowRoot.delegatesFocus); 172 assert_equals(hostDiv.tabIndex, -1); 173 174 const elements = [ 175 [inputBefore], 176 [innerInput, shadowRoot], 177 [inputAfter], 178 ]; 179 180 await assert_focus_navigation_bidirectional_with_shadow_root(elements, false); 181 }, 'Testing tab navigation order with mode closed, no tabindex and delegatesFocus=false.'); 182 183 promise_test(async () => { 184 const { 185 hostDiv, 186 shadowRoot, 187 inputBefore, 188 innerInput, 189 inputAfter, 190 } = prepareDOMTree(sandbox, 'closed', null, true); 191 assert_true(shadowRoot.delegatesFocus); 192 assert_equals(hostDiv.tabIndex, -1); 193 194 const elements = [ 195 [inputBefore], 196 [innerInput, shadowRoot], 197 [inputAfter], 198 ]; 199 200 await assert_focus_navigation_bidirectional_with_shadow_root(elements, false); 201 }, 'Testing tab navigation order with mode closed, no tabindex and delegatesFocus=true.'); 202 203 promise_test(async () => { 204 const { 205 hostDiv, 206 shadowRoot, 207 inputBefore, 208 innerInput, 209 inputAfter, 210 } = prepareDOMTree(sandbox, 'closed', 0, false); 211 assert_false(shadowRoot.delegatesFocus); 212 assert_equals(hostDiv.tabIndex, 0); 213 214 const elements = [ 215 [inputBefore], 216 [hostDiv], 217 [innerInput, shadowRoot], 218 [inputAfter], 219 ]; 220 221 await assert_focus_navigation_bidirectional_with_shadow_root(elements, false); 222 }, 'Testing tab navigation order with mode closed, tabindex=0 and delegatesFocus=false.'); 223 224 promise_test(async () => { 225 const { 226 hostDiv, 227 shadowRoot, 228 inputBefore, 229 innerInput, 230 inputAfter, 231 } = prepareDOMTree(sandbox, 'closed', 0, true); 232 assert_true(shadowRoot.delegatesFocus); 233 assert_equals(hostDiv.tabIndex, 0); 234 235 const elements = [ 236 [inputBefore], 237 // [hostDiv], // should skip host when delegatesFocus=true 238 [innerInput, shadowRoot], 239 [inputAfter], 240 ]; 241 242 await assert_focus_navigation_bidirectional_with_shadow_root(elements, false); 243 }, 'Testing tab navigation order with mode closed, tabindex=0 and delegatesFocus=true.'); 244 245 promise_test(async () => { 246 const { 247 hostDiv, 248 shadowRoot, 249 inputBefore, 250 innerInput, 251 inputAfter, 252 } = prepareDOMTree(sandbox, 'closed', -1, false); 253 assert_false(shadowRoot.delegatesFocus); 254 assert_equals(hostDiv.tabIndex, -1); 255 256 const elements = [ 257 [inputBefore], 258 [inputAfter], 259 ]; 260 261 await assert_focus_navigation_bidirectional_with_shadow_root(elements, false); 262 }, 'Testing tab navigation order with mode closed, tabindex=-1 and delegatesFocus=false.'); 263 264 promise_test(async () => { 265 const { 266 hostDiv, 267 shadowRoot, 268 inputBefore, 269 innerInput, 270 inputAfter, 271 } = prepareDOMTree(sandbox, 'closed', -1, true); 272 assert_true(shadowRoot.delegatesFocus); 273 assert_equals(hostDiv.tabIndex, -1); 274 275 const elements = [ 276 [inputBefore], 277 // [innerInput, shadowRoot], // The whole shadow tree should be skipped 278 [inputAfter], 279 ]; 280 281 await assert_focus_navigation_bidirectional_with_shadow_root(elements, false); 282 }, 'Testing tab navigation order with mode closed, tabindex=-1 and delegatesFocus=true.'); 283 284 promise_test(async () => { 285 const { 286 hostDiv, 287 shadowRoot, 288 inputBefore, 289 innerInput, 290 inputAfter, 291 } = prepareDOMTree(sandbox, 'closed', 1, false); 292 assert_false(shadowRoot.delegatesFocus); 293 assert_equals(hostDiv.tabIndex, 1); 294 295 const elements = [ 296 [hostDiv], 297 [innerInput, shadowRoot], 298 [inputBefore], 299 [inputAfter], 300 ]; 301 302 await assert_focus_navigation_bidirectional_with_shadow_root(elements, false); 303 }, 'Testing tab navigation order with mode closed, tabindex=1 and delegatesFocus=false.'); 304 305 promise_test(async () => { 306 const { 307 hostDiv, 308 shadowRoot, 309 inputBefore, 310 innerInput, 311 inputAfter, 312 } = prepareDOMTree(sandbox, 'closed', 1, true); 313 assert_true(shadowRoot.delegatesFocus); 314 assert_equals(hostDiv.tabIndex, 1); 315 316 const elements = [ 317 // [hostDiv], // should skip host when delegatesFocus=true 318 [innerInput, shadowRoot], 319 [inputBefore], 320 [inputAfter], 321 ]; 322 323 await assert_focus_navigation_bidirectional_with_shadow_root(elements, false); 324 }, 'Testing tab navigation order with mode closed, tabindex=1 and delegatesFocus=true.'); 325 326 327 </script>