dialog-focus-shadow.html (9866B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>dialog focus delegation</title> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <body> 7 8 <!-- 9 We focus this one between each test, to ensure that for non-modal dialogs, 10 if there is no focus delegate, it stays focused (instead of causing focus to reset to the body). 11 --> 12 <button id="focus-between-tests">Focus between tests</button> 13 14 <dialog data-description="No autofocus, no delegatesFocus, no siblings"> 15 <template class="turn-into-shadow-tree"> 16 <button disabled>Non-focusable</button> 17 <button>Focusable</button> 18 <button disabled>Non-focusable</button> 19 </template> 20 </dialog> 21 22 <dialog data-description="No autofocus, no delegatesFocus, sibling before"> 23 <button class="focus-me">Focusable</button> 24 <template class="turn-into-shadow-tree"> 25 <button disabled>Non-focusable</button> 26 <button>Focusable</button> 27 <button disabled>Non-focusable</button> 28 </template> 29 </dialog> 30 31 <dialog data-description="No autofocus, no delegatesFocus, sibling after"> 32 <template class="turn-into-shadow-tree"> 33 <button disabled>Non-focusable</button> 34 <button>Focusable</button> 35 <button disabled>Non-focusable</button> 36 </template> 37 <button class="focus-me">Focusable</button> 38 </dialog> 39 40 <dialog data-description="No autofocus, yes delegatesFocus, no siblings"> 41 <template class="turn-into-shadow-tree delegates-focus"> 42 <button disabled>Non-focusable</button> 43 <button class="focus-me">Focusable</button> 44 <button disabled>Non-focusable</button> 45 </template> 46 </dialog> 47 48 <dialog data-description="No autofocus, yes delegatesFocus, sibling before"> 49 <button class="focus-me">Focusable</button> 50 <template class="turn-into-shadow-tree delegates-focus"> 51 <button disabled>Non-focusable</button> 52 <button>Focusable</button> 53 <button disabled>Non-focusable</button> 54 </template> 55 </dialog> 56 57 <dialog data-description="No autofocus, yes delegatesFocus, sibling after"> 58 <template class="turn-into-shadow-tree delegates-focus"> 59 <button disabled>Non-focusable</button> 60 <button class="focus-me">Focusable</button> 61 <button disabled>Non-focusable</button> 62 </template> 63 <button>Focusable</button> 64 </dialog> 65 66 <dialog data-description="Autofocus before, no delegatesFocus"> 67 <button autofocus class="focus-me">Focusable</button> 68 <template class="turn-into-shadow-tree"> 69 <button disabled>Non-focusable</button> 70 <button>Focusable</button> 71 <button disabled>Non-focusable</button> 72 </template> 73 </dialog> 74 75 <dialog data-description="Autofocus before, yes delegatesFocus"> 76 <button autofocus class="focus-me">Focusable</button> 77 <template class="turn-into-shadow-tree delegates-focus"> 78 <button disabled>Non-focusable</button> 79 <button>Focusable</button> 80 <button disabled>Non-focusable</button> 81 </template> 82 </dialog> 83 84 <dialog data-description="Autofocus after, no delegatesFocus"> 85 <template class="turn-into-shadow-tree"> 86 <button disabled>Non-focusable</button> 87 <button>Focusable</button> 88 <button disabled>Non-focusable</button> 89 </template> 90 <button autofocus class="focus-me">Focusable</button> 91 </dialog> 92 93 <dialog data-description="Autofocus after, yes delegatesFocus"> 94 <template class="turn-into-shadow-tree delegates-focus"> 95 <button disabled>Non-focusable</button> 96 <button>Focusable</button> 97 <button disabled>Non-focusable</button> 98 </template> 99 <button autofocus class="focus-me">Focusable</button> 100 </dialog> 101 102 <dialog data-description="Autofocus on shadow host, yes delegatesFocus, no siblings"> 103 <template class="turn-into-shadow-tree delegates-focus autofocus"> 104 <button disabled>Non-focusable</button> 105 <button class="focus-me">Focusable</button> 106 <button disabled>Non-focusable</button> 107 </template> 108 </dialog> 109 110 <dialog data-description="Autofocus on shadow host, yes delegatesFocus, sibling before"> 111 <button>Focusable</button> 112 <template class="turn-into-shadow-tree delegates-focus autofocus"> 113 <button disabled>Non-focusable</button> 114 <button class="focus-me">Focusable</button> 115 <button disabled>Non-focusable</button> 116 </template> 117 </dialog> 118 119 <dialog data-description="Autofocus on shadow host, yes delegatesFocus, sibling after"> 120 <template class="turn-into-shadow-tree delegates-focus autofocus"> 121 <button disabled>Non-focusable</button> 122 <button class="focus-me">Focusable</button> 123 <button disabled>Non-focusable</button> 124 </template> 125 <button>Focusable</button> 126 </dialog> 127 128 <dialog data-description="Autofocus on shadow host, no delegatesFocus, no siblings"> 129 <template class="turn-into-shadow-tree autofocus"> 130 <button disabled>Non-focusable</button> 131 <button>Focusable</button> 132 <button disabled>Non-focusable</button> 133 </template> 134 </dialog> 135 136 <dialog data-description="Autofocus on shadow host, no delegatesFocus, sibling before"> 137 <button class="focus-me">Focusable</button> 138 <template class="turn-into-shadow-tree autofocus"> 139 <button disabled>Non-focusable</button> 140 <button>Focusable</button> 141 <button disabled>Non-focusable</button> 142 </template> 143 </dialog> 144 145 <dialog data-description="Autofocus on shadow host, no delegatesFocus, sibling after"> 146 <template class="turn-into-shadow-tree autofocus"> 147 <button disabled>Non-focusable</button> 148 <button>Focusable</button> 149 <button disabled>Non-focusable</button> 150 </template> 151 <button class="focus-me">Focusable</button> 152 </dialog> 153 154 <dialog data-description="Autofocus inside shadow tree, yes delegatesFocus, no siblings"> 155 <template class="turn-into-shadow-tree delegates-focus"> 156 <button>Focusable</button> 157 <button autofocus class="focus-me">Focusable</button> 158 <button disabled>Non-focusable</button> 159 </template> 160 </dialog> 161 162 <dialog data-description="Autofocus inside shadow tree, yes delegatesFocus, sibling before"> 163 <button class="focus-me">Focusable</button> 164 <template class="turn-into-shadow-tree delegates-focus"> 165 <button>Focusable</button> 166 <button autofocus>Focusable</button> 167 <button disabled>Non-focusable</button> 168 </template> 169 </dialog> 170 171 <dialog data-description="Autofocus inside shadow tree, yes delegatesFocus, sibling after"> 172 <template class="turn-into-shadow-tree delegates-focus"> 173 <button>Focusable</button> 174 <button autofocus class="focus-me">Focusable</button> 175 <button disabled>Non-focusable</button> 176 </template> 177 <button>Focusable</button> 178 </dialog> 179 180 <dialog data-description="Autofocus inside shadow tree, no delegatesFocus, no siblings"> 181 <template class="turn-into-shadow-tree"> 182 <button>Focusable</button> 183 <button autofocus>Focusable</button> 184 <button disabled>Non-focusable</button> 185 </template> 186 </dialog> 187 188 <dialog data-description="Autofocus inside shadow tree, no delegatesFocus, sibling before"> 189 <button class="focus-me">Focusable</button> 190 <template class="turn-into-shadow-tree"> 191 <button>Focusable</button> 192 <button autofocus>Focusable</button> 193 <button disabled>Non-focusable</button> 194 </template> 195 </dialog> 196 197 <dialog data-description="Autofocus inside shadow tree, no delegatesFocus, sibling after"> 198 <template class="turn-into-shadow-tree"> 199 <button>Focusable</button> 200 <button autofocus>Focusable</button> 201 <button disabled>Non-focusable</button> 202 </template> 203 <button class="focus-me">Focusable</button> 204 </dialog> 205 206 <dialog data-description="Two shadow trees, both delegatesFocus, first tree doesn't have autofocus element, second does"> 207 <template class="turn-into-shadow-tree delegates-focus"> 208 <button disabled>Non-focusable</button> 209 <button class="focus-me">Focusable</button> 210 <button disabled>Non-focusable</button> 211 </template> 212 <template class="turn-into-shadow-tree delegates-focus"> 213 <button autofocus>Focusable</button> 214 </template> 215 </dialog> 216 217 <dialog data-description="No autofocus, no delegatesFocus, slotted target"> 218 <template class="turn-into-shadow-tree"> 219 <button>Focusable</button> 220 <slot></slot> 221 <button>Focusable</button> 222 </template> 223 <button class="focus-me">Focusable</button> 224 </dialog> 225 226 <dialog data-description="Shadowroot on child, no autofocus, no delegatesFocus"> 227 <div> 228 <template class="turn-into-shadow-tree"> 229 <button>Focusable</button> 230 </template> 231 </div> 232 <button class="focus-me">Focusable</button> 233 </dialog> 234 235 <script> 236 for (const template of document.querySelectorAll(".turn-into-shadow-tree")) { 237 const div = document.createElement("div"); 238 div.attachShadow({ mode: "open", delegatesFocus: template.classList.contains("delegates-focus") }); 239 240 if (template.classList.contains("autofocus")) { 241 div.setAttribute("autofocus", true); 242 } 243 div.shadowRoot.append(template.content); 244 template.replaceWith(div); 245 } 246 247 const focusBetweenTests = document.querySelector("#focus-between-tests"); 248 249 for (const dialog of document.querySelectorAll("dialog")) { 250 for (const method of ["show", "showModal"]) { 251 test(t => { 252 focusBetweenTests.focus(); 253 254 dialog[method](); 255 t.add_cleanup(() => dialog.close()); 256 257 const expectedFocusOutsideShadowTree = dialog.querySelector(".focus-me"); 258 if (expectedFocusOutsideShadowTree) { 259 assert_equals(document.activeElement, expectedFocusOutsideShadowTree); 260 } else { 261 const shadowHost = dialog.querySelector("div"); 262 const expectedFocusInsideShadowTree = shadowHost.shadowRoot.querySelector(".focus-me"); 263 if (expectedFocusInsideShadowTree) { 264 assert_equals(document.activeElement, shadowHost); 265 assert_equals(shadowHost.shadowRoot.activeElement, expectedFocusInsideShadowTree); 266 } else { 267 // There is no focus delegate. The dialog element should be focused. 268 assert_equals(document.activeElement, dialog); 269 } 270 } 271 }, `${method}: ${dialog.dataset.description}`); 272 } 273 } 274 </script>