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> 8var dump = document.getElementById("dump") 9 10async_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 20async_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 30async_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 40async_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 50async_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 61async_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 77async_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 90async_test(function(t) { 91 var input = document.createElement("input") 92 input.type = "checkbox" 93 dump.appendChild(input) 94 var clickEvent = new MouseEvent("click") 95 input.onchange = t.step_func_done(function() { 96 assert_false(clickEvent.defaultPrevented) 97 assert_true(clickEvent.returnValue) 98 assert_equals(clickEvent.eventPhase, 0) 99 assert_equals(clickEvent.currentTarget, null) 100 assert_equals(clickEvent.target, input) 101 assert_equals(clickEvent.srcElement, input) 102 assert_equals(clickEvent.composedPath().length, 0) 103 }) 104 input.dispatchEvent(clickEvent) 105}, "event state during post-click handling") 106 107async_test(function(t) { 108 var input = document.createElement("input") 109 input.type = "checkbox" 110 dump.appendChild(input) 111 var clickEvent = new MouseEvent("click") 112 var finalTarget = document.createElement("doesnotmatter") 113 finalTarget.onclick = t.step_func_done(function() { 114 assert_equals(clickEvent.target, finalTarget) 115 assert_equals(clickEvent.srcElement, finalTarget) 116 }) 117 input.onchange = t.step_func(function() { 118 finalTarget.dispatchEvent(clickEvent) 119 }) 120 input.dispatchEvent(clickEvent) 121}, "redispatch during post-click handling") 122 123async_test(function(t) { 124 var input = document.createElement("input") 125 input.type = "checkbox" 126 dump.appendChild(input) 127 var child = input.appendChild(document.createElement("input")) 128 child.type = "checkbox" 129 child.disabled = true 130 child.click() 131 assert_false(input.checked) 132 assert_false(child.checked) 133 t.done() 134}, "disabled checkbox still has activation behavior") 135 136async_test(function(t) { 137 var state = "start" 138 139 var form = document.createElement("form") 140 form.onsubmit = t.step_func(() => { 141 if(state == "start" || state == "checkbox") { 142 state = "failure" 143 } else if(state == "form") { 144 state = "done" 145 } 146 return false 147 }) 148 dump.appendChild(form) 149 var button = form.appendChild(document.createElement("button")) 150 button.type = "submit" 151 var checkbox = button.appendChild(document.createElement("input")) 152 checkbox.type = "checkbox" 153 checkbox.onclick = t.step_func(() => { 154 if(state == "start") { 155 assert_unreached() 156 } else if(state == "checkbox") { 157 assert_true(checkbox.checked) 158 } 159 }) 160 checkbox.disabled = true 161 checkbox.click() 162 assert_equals(state, "start") 163 164 state = "checkbox" 165 checkbox.disabled = false 166 checkbox.click() 167 assert_equals(state, "checkbox") 168 169 state = "form" 170 button.click() 171 assert_equals(state, "done") 172 173 t.done() 174}, "disabled checkbox still has activation behavior, part 2") 175 176async_test(function(t) { 177 var input = document.createElement("input") 178 input.type = "checkbox" 179 input.onclick = t.step_func_done(function() { 180 assert_true(input.checked) 181 }) 182 input.click() 183}, "disconnected checkbox should be checked") 184 185async_test(function(t) { 186 var input = document.createElement("input") 187 input.type = "radio" 188 input.onclick = t.step_func_done(function() { 189 assert_true(input.checked) 190 }) 191 input.click() 192}, "disconnected radio should be checked") 193 194async_test(t => { 195 const input = document.createElement('input'); 196 input.type = 'checkbox'; 197 input.onclick = t.step_func_done(() => { 198 assert_true(input.checked); 199 }); 200 input.dispatchEvent(new MouseEvent('click')); 201}, `disconnected checkbox should be checked from dispatchEvent(new MouseEvent('click'))`); 202 203async_test(t => { 204 const input = document.createElement('input'); 205 input.type = 'radio'; 206 input.onclick = t.step_func_done(() => { 207 assert_true(input.checked); 208 }); 209 input.dispatchEvent(new MouseEvent('click')); 210}, `disconnected radio should be checked from dispatchEvent(new MouseEvent('click'))`); 211 212test(() => { 213 const input = document.createElement("input"); 214 input.type = "checkbox"; 215 input.disabled = true; 216 input.dispatchEvent(new MouseEvent("click")); 217 assert_true(input.checked); 218}, `disabled checkbox should be checked from dispatchEvent(new MouseEvent("click"))`); 219 220test(() => { 221 const input = document.createElement("input"); 222 input.type = "radio"; 223 input.disabled = true; 224 input.dispatchEvent(new MouseEvent("click")); 225 assert_true(input.checked); 226}, `disabled radio should be checked from dispatchEvent(new MouseEvent("click"))`); 227 228async_test(t => { 229 const input = document.createElement("input"); 230 input.type = "checkbox"; 231 input.disabled = true; 232 input.onclick = t.step_func_done(); 233 input.dispatchEvent(new MouseEvent("click")); 234}, `disabled checkbox should fire onclick`); 235 236async_test(t => { 237 const input = document.createElement("input"); 238 input.type = "radio"; 239 input.disabled = true; 240 input.onclick = t.step_func_done(); 241 input.dispatchEvent(new MouseEvent("click")); 242}, `disabled radio should fire onclick`); 243 244async_test(t => { 245 const input = document.createElement("input"); 246 input.type = "checkbox"; 247 input.disabled = true; 248 input.onclick = t.step_func(ev => { 249 assert_true(input.checked); 250 ev.preventDefault(); 251 queueMicrotask(t.step_func_done(() => { 252 assert_false(input.checked); 253 })); 254 }); 255 input.dispatchEvent(new MouseEvent("click", { cancelable: true })); 256}, `disabled checkbox should get legacy-canceled-activation behavior`); 257 258async_test(t => { 259 const input = document.createElement("input"); 260 input.type = "radio"; 261 input.disabled = true; 262 input.onclick = t.step_func(ev => { 263 assert_true(input.checked); 264 ev.preventDefault(); 265 queueMicrotask(t.step_func_done(() => { 266 assert_false(input.checked); 267 })); 268 }); 269 input.dispatchEvent(new MouseEvent("click", { cancelable: true })); 270}, `disabled radio should get legacy-canceled-activation behavior`); 271 272test(t => { 273 const input = document.createElement("input"); 274 input.type = "checkbox"; 275 input.disabled = true; 276 const ev = new MouseEvent("click", { cancelable: true }); 277 ev.preventDefault(); 278 input.dispatchEvent(ev); 279 assert_false(input.checked); 280}, `disabled checkbox should get legacy-canceled-activation behavior 2`); 281 282test(t => { 283 const input = document.createElement("input"); 284 input.type = "radio"; 285 input.disabled = true; 286 const ev = new MouseEvent("click", { cancelable: true }); 287 ev.preventDefault(); 288 input.dispatchEvent(ev); 289 assert_false(input.checked); 290}, `disabled radio should get legacy-canceled-activation behavior 2`); 291 292for (const type of ["checkbox", "radio"]) { 293 for (const handler of ["oninput", "onchange"]) { 294 async_test(t => { 295 const input = document.createElement("input"); 296 input.type = type; 297 input.onclick = t.step_func(ev => { 298 input.disabled = true; 299 }); 300 input[handler] = t.step_func(ev => { 301 assert_equals(input.checked, true); 302 t.done(); 303 }); 304 dump.append(input); 305 input.click(); 306 }, `disabling ${type} in onclick listener shouldn't suppress ${handler}`); 307 } 308} 309 310async_test(function(t) { 311 var form = document.createElement("form") 312 var didSubmit = false 313 form.onsubmit = t.step_func(() => { 314 didSubmit = true 315 return false 316 }) 317 var input = form.appendChild(document.createElement("input")) 318 input.type = "submit" 319 input.click() 320 assert_false(didSubmit) 321 t.done() 322}, "disconnected form should not submit") 323 324async_test(t => { 325 const form = document.createElement("form"); 326 form.onsubmit = t.step_func(ev => { 327 ev.preventDefault(); 328 assert_unreached("The form is unexpectedly submitted."); 329 }); 330 dump.append(form); 331 const input = form.appendChild(document.createElement("input")); 332 input.type = "submit" 333 input.disabled = true; 334 input.dispatchEvent(new MouseEvent("click", { cancelable: true })); 335 t.done(); 336}, "disabled submit button should not activate"); 337 338async_test(t => { 339 const form = document.createElement("form"); 340 form.onsubmit = t.step_func(ev => { 341 ev.preventDefault(); 342 assert_unreached("The form is unexpectedly submitted."); 343 }); 344 dump.append(form); 345 const input = form.appendChild(document.createElement("input")); 346 input.onclick = t.step_func(() => { 347 input.disabled = true; 348 }); 349 input.type = "submit" 350 input.dispatchEvent(new MouseEvent("click", { cancelable: true })); 351 t.done(); 352}, "submit button should not activate if the event listener disables it"); 353 354async_test(t => { 355 const form = document.createElement("form"); 356 form.onsubmit = t.step_func(ev => { 357 ev.preventDefault(); 358 assert_unreached("The form is unexpectedly submitted."); 359 }); 360 dump.append(form); 361 const input = form.appendChild(document.createElement("input")); 362 input.onclick = t.step_func(() => { 363 input.type = "submit" 364 input.disabled = true; 365 }); 366 input.click(); 367 t.done(); 368}, "submit button that morphed from checkbox should not activate"); 369</script> 370