Event-dispatch-click.html (13174B)
1 <!doctype html> 2 <title>Synthetic click event "magic"</title> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <div id=log></div> 6 <div id=dump style=display:none></div> 7 <script> 8 var dump = document.getElementById("dump") 9 10 async_test(function(t) { 11 var input = document.createElement("input") 12 input.type = "checkbox" 13 dump.appendChild(input) 14 input.onclick = t.step_func_done(function() { 15 assert_true(input.checked) 16 }) 17 input.click() 18 }, "basic with click()") 19 20 async_test(function(t) { 21 var input = document.createElement("input") 22 input.type = "checkbox" 23 dump.appendChild(input) 24 input.onclick = t.step_func_done(function() { 25 assert_true(input.checked) 26 }) 27 input.dispatchEvent(new MouseEvent("click", {bubbles:true})) // equivalent to the above 28 }, "basic with dispatchEvent()") 29 30 async_test(function(t) { 31 var input = document.createElement("input") 32 input.type = "checkbox" 33 dump.appendChild(input) 34 input.onclick = t.step_func_done(function() { 35 assert_false(input.checked) 36 }) 37 input.dispatchEvent(new Event("click", {bubbles:true})) // no MouseEvent 38 }, "basic with wrong event class") 39 40 async_test(function(t) { 41 var input = document.createElement("input") 42 input.type = "checkbox" 43 dump.appendChild(input) 44 var child = input.appendChild(new Text("does not matter")) 45 child.dispatchEvent(new MouseEvent("click")) // does not bubble 46 assert_false(input.checked) 47 t.done() 48 }, "look at parents only when event bubbles") 49 50 async_test(function(t) { 51 var input = document.createElement("input") 52 input.type = "checkbox" 53 dump.appendChild(input) 54 input.onclick = t.step_func_done(function() { 55 assert_true(input.checked) 56 }) 57 var child = input.appendChild(new Text("does not matter")) 58 child.dispatchEvent(new MouseEvent("click", {bubbles:true})) 59 }, "look at parents when event bubbles") 60 61 async_test(function(t) { 62 var input = document.createElement("input") 63 input.type = "checkbox" 64 dump.appendChild(input) 65 input.onclick = t.step_func(function() { 66 assert_false(input.checked, "input pre-click must not be triggered") 67 }) 68 var child = input.appendChild(document.createElement("input")) 69 child.type = "checkbox" 70 child.onclick = t.step_func(function() { 71 assert_true(child.checked, "child pre-click must be triggered") 72 }) 73 child.dispatchEvent(new MouseEvent("click", {bubbles:true})) 74 t.done() 75 }, "pick the first with activation behavior <input type=checkbox>") 76 77 async_test(function(t) { // as above with <a> 78 window.hrefComplete = t.step_func(function(a) { 79 assert_equals(a, 'child'); 80 t.done(); 81 }); 82 var link = document.createElement("a") 83 link.href = "javascript:hrefComplete('link')" // must not be triggered 84 dump.appendChild(link) 85 var child = link.appendChild(document.createElement("a")) 86 child.href = "javascript:hrefComplete('child')" 87 child.dispatchEvent(new MouseEvent("click", {bubbles:true})) 88 }, "pick the first with activation behavior <a href>") 89 90 async_test(function(t) { 91 var input = document.createElement("input") 92 input.type = "radio" 93 dump.appendChild(input) 94 input.onclick = t.step_func(function() { 95 assert_false(input.checked, "input pre-click must not be triggered") 96 }) 97 var child = input.appendChild(document.createElement("input")) 98 child.type = "radio" 99 child.onclick = t.step_func(function() { 100 assert_true(child.checked, "child pre-click must be triggered") 101 }) 102 child.dispatchEvent(new MouseEvent("click", {bubbles:true})) 103 t.done() 104 }, "pick the first with activation behavior <input type=radio>") 105 106 async_test(function(t) { 107 var input = document.createElement("input") 108 input.type = "checkbox" 109 dump.appendChild(input) 110 var clickEvent = new MouseEvent("click") 111 input.onchange = t.step_func_done(function() { 112 assert_false(clickEvent.defaultPrevented) 113 assert_true(clickEvent.returnValue) 114 assert_equals(clickEvent.eventPhase, 0) 115 assert_equals(clickEvent.currentTarget, null) 116 assert_equals(clickEvent.target, input) 117 assert_equals(clickEvent.srcElement, input) 118 assert_equals(clickEvent.composedPath().length, 0) 119 }) 120 input.dispatchEvent(clickEvent) 121 }, "event state during post-click handling") 122 123 async_test(function(t) { 124 var input = document.createElement("input") 125 input.type = "checkbox" 126 dump.appendChild(input) 127 var clickEvent = new MouseEvent("click") 128 var finalTarget = document.createElement("doesnotmatter") 129 finalTarget.onclick = t.step_func_done(function() { 130 assert_equals(clickEvent.target, finalTarget) 131 assert_equals(clickEvent.srcElement, finalTarget) 132 }) 133 input.onchange = t.step_func(function() { 134 finalTarget.dispatchEvent(clickEvent) 135 }) 136 input.dispatchEvent(clickEvent) 137 }, "redispatch during post-click handling") 138 139 async_test(function(t) { 140 var input = document.createElement("input") 141 input.type = "checkbox" 142 dump.appendChild(input) 143 var child = input.appendChild(document.createElement("input")) 144 child.type = "checkbox" 145 child.disabled = true 146 child.click() 147 assert_false(input.checked) 148 assert_false(child.checked) 149 t.done() 150 }, "disabled checkbox still has activation behavior") 151 152 async_test(function(t) { 153 var state = "start" 154 155 var form = document.createElement("form") 156 form.onsubmit = t.step_func(() => { 157 if(state == "start" || state == "checkbox") { 158 state = "failure" 159 } else if(state == "form") { 160 state = "done" 161 } 162 return false 163 }) 164 dump.appendChild(form) 165 var button = form.appendChild(document.createElement("button")) 166 button.type = "submit" 167 var checkbox = button.appendChild(document.createElement("input")) 168 checkbox.type = "checkbox" 169 checkbox.onclick = t.step_func(() => { 170 if(state == "start") { 171 assert_unreached() 172 } else if(state == "checkbox") { 173 assert_true(checkbox.checked) 174 } 175 }) 176 checkbox.disabled = true 177 checkbox.click() 178 assert_equals(state, "start") 179 180 state = "checkbox" 181 checkbox.disabled = false 182 checkbox.click() 183 assert_equals(state, "checkbox") 184 185 state = "form" 186 button.click() 187 assert_equals(state, "done") 188 189 t.done() 190 }, "disabled checkbox still has activation behavior, part 2") 191 192 async_test(function(t) { 193 var state = "start" 194 195 var form = document.createElement("form") 196 form.onsubmit = t.step_func(() => { 197 if(state == "start" || state == "radio") { 198 state = "failure" 199 } else if(state == "form") { 200 state = "done" 201 } 202 return false 203 }) 204 dump.appendChild(form) 205 var button = form.appendChild(document.createElement("button")) 206 button.type = "submit" 207 var radio = button.appendChild(document.createElement("input")) 208 radio.type = "radio" 209 radio.onclick = t.step_func(() => { 210 if(state == "start") { 211 assert_unreached() 212 } else if(state == "radio") { 213 assert_true(radio.checked) 214 } 215 }) 216 radio.disabled = true 217 radio.click() 218 assert_equals(state, "start") 219 220 state = "radio" 221 radio.disabled = false 222 radio.click() 223 assert_equals(state, "radio") 224 225 state = "form" 226 button.click() 227 assert_equals(state, "done") 228 229 t.done() 230 }, "disabled radio still has activation behavior") 231 232 async_test(function(t) { 233 var input = document.createElement("input") 234 input.type = "checkbox" 235 input.onclick = t.step_func_done(function() { 236 assert_true(input.checked) 237 }) 238 input.click() 239 }, "disconnected checkbox should be checked") 240 241 async_test(function(t) { 242 var input = document.createElement("input") 243 input.type = "radio" 244 input.onclick = t.step_func_done(function() { 245 assert_true(input.checked) 246 }) 247 input.click() 248 }, "disconnected radio should be checked") 249 250 async_test(t => { 251 const input = document.createElement('input'); 252 input.type = 'checkbox'; 253 input.onclick = t.step_func_done(() => { 254 assert_true(input.checked); 255 }); 256 input.dispatchEvent(new MouseEvent('click')); 257 }, `disconnected checkbox should be checked from dispatchEvent(new MouseEvent('click'))`); 258 259 async_test(t => { 260 const input = document.createElement('input'); 261 input.type = 'radio'; 262 input.onclick = t.step_func_done(() => { 263 assert_true(input.checked); 264 }); 265 input.dispatchEvent(new MouseEvent('click')); 266 }, `disconnected radio should be checked from dispatchEvent(new MouseEvent('click'))`); 267 268 test(() => { 269 const input = document.createElement("input"); 270 input.type = "checkbox"; 271 input.disabled = true; 272 input.dispatchEvent(new MouseEvent("click")); 273 assert_true(input.checked); 274 }, `disabled checkbox should be checked from dispatchEvent(new MouseEvent("click"))`); 275 276 test(() => { 277 const input = document.createElement("input"); 278 input.type = "radio"; 279 input.disabled = true; 280 input.dispatchEvent(new MouseEvent("click")); 281 assert_true(input.checked); 282 }, `disabled radio should be checked from dispatchEvent(new MouseEvent("click"))`); 283 284 async_test(t => { 285 const input = document.createElement("input"); 286 input.type = "checkbox"; 287 input.disabled = true; 288 input.onclick = t.step_func_done(); 289 input.dispatchEvent(new MouseEvent("click")); 290 }, `disabled checkbox should fire onclick`); 291 292 async_test(t => { 293 const input = document.createElement("input"); 294 input.type = "radio"; 295 input.disabled = true; 296 input.onclick = t.step_func_done(); 297 input.dispatchEvent(new MouseEvent("click")); 298 }, `disabled radio should fire onclick`); 299 300 async_test(t => { 301 const input = document.createElement("input"); 302 input.type = "checkbox"; 303 input.disabled = true; 304 input.onclick = t.step_func(ev => { 305 assert_true(input.checked); 306 ev.preventDefault(); 307 queueMicrotask(t.step_func_done(() => { 308 assert_false(input.checked); 309 })); 310 }); 311 input.dispatchEvent(new MouseEvent("click", { cancelable: true })); 312 }, `disabled checkbox should get legacy-canceled-activation behavior`); 313 314 async_test(t => { 315 const input = document.createElement("input"); 316 input.type = "radio"; 317 input.disabled = true; 318 input.onclick = t.step_func(ev => { 319 assert_true(input.checked); 320 ev.preventDefault(); 321 queueMicrotask(t.step_func_done(() => { 322 assert_false(input.checked); 323 })); 324 }); 325 input.dispatchEvent(new MouseEvent("click", { cancelable: true })); 326 }, `disabled radio should get legacy-canceled-activation behavior`); 327 328 test(t => { 329 const input = document.createElement("input"); 330 input.type = "checkbox"; 331 input.disabled = true; 332 const ev = new MouseEvent("click", { cancelable: true }); 333 ev.preventDefault(); 334 input.dispatchEvent(ev); 335 assert_false(input.checked); 336 }, `disabled checkbox should get legacy-canceled-activation behavior 2`); 337 338 test(t => { 339 const input = document.createElement("input"); 340 input.type = "radio"; 341 input.disabled = true; 342 const ev = new MouseEvent("click", { cancelable: true }); 343 ev.preventDefault(); 344 input.dispatchEvent(ev); 345 assert_false(input.checked); 346 }, `disabled radio should get legacy-canceled-activation behavior 2`); 347 348 for (const type of ["checkbox", "radio"]) { 349 for (const handler of ["oninput", "onchange"]) { 350 async_test(t => { 351 const input = document.createElement("input"); 352 input.type = type; 353 input.onclick = t.step_func(ev => { 354 input.disabled = true; 355 }); 356 input[handler] = t.step_func(ev => { 357 assert_equals(input.checked, true); 358 t.done(); 359 }); 360 dump.append(input); 361 input.click(); 362 }, `disabling ${type} in onclick listener shouldn't suppress ${handler}`); 363 } 364 } 365 366 async_test(function(t) { 367 var form = document.createElement("form") 368 var didSubmit = false 369 form.onsubmit = t.step_func(() => { 370 didSubmit = true 371 return false 372 }) 373 var input = form.appendChild(document.createElement("input")) 374 input.type = "submit" 375 input.click() 376 assert_false(didSubmit) 377 t.done() 378 }, "disconnected form should not submit") 379 380 async_test(t => { 381 const form = document.createElement("form"); 382 form.onsubmit = t.step_func(ev => { 383 ev.preventDefault(); 384 assert_unreached("The form is unexpectedly submitted."); 385 }); 386 dump.append(form); 387 const input = form.appendChild(document.createElement("input")); 388 input.type = "submit" 389 input.disabled = true; 390 input.dispatchEvent(new MouseEvent("click", { cancelable: true })); 391 t.done(); 392 }, "disabled submit button should not activate"); 393 394 async_test(t => { 395 const form = document.createElement("form"); 396 form.onsubmit = t.step_func(ev => { 397 ev.preventDefault(); 398 assert_unreached("The form is unexpectedly submitted."); 399 }); 400 dump.append(form); 401 const input = form.appendChild(document.createElement("input")); 402 input.onclick = t.step_func(() => { 403 input.disabled = true; 404 }); 405 input.type = "submit" 406 input.dispatchEvent(new MouseEvent("click", { cancelable: true })); 407 t.done(); 408 }, "submit button should not activate if the event listener disables it"); 409 410 async_test(t => { 411 const form = document.createElement("form"); 412 form.onsubmit = t.step_func(ev => { 413 ev.preventDefault(); 414 assert_unreached("The form is unexpectedly submitted."); 415 }); 416 dump.append(form); 417 const input = form.appendChild(document.createElement("input")); 418 input.onclick = t.step_func(() => { 419 input.type = "submit" 420 input.disabled = true; 421 }); 422 input.click(); 423 t.done(); 424 }, "submit button that morphed from checkbox should not activate"); 425 </script>