button-event-dispatch.html (9653B)
1 <!doctype html> 2 <meta charset="utf-8" /> 3 <meta name="author" title="Keith Cirkel" href="mailto:wpt@keithcirkel.co.uk" /> 4 <meta name="timeout" content="long" /> 5 <link rel="help" href="https://open-ui.org/components/invokers.explainer/" /> 6 <script src="/resources/testharness.js"></script> 7 <script src="/resources/testharnessreport.js"></script> 8 <script src="resources/invoker-utils.js"></script> 9 10 <div id="invokee"></div> 11 <button id="invokerbutton" commandfor="invokee" command="--custom-command"></button> 12 <input type="button" id="invalidbutton" commandfor="invokee" command="--custom-command"> 13 <form id="aform"></form> 14 15 <script> 16 aform.addEventListener('submit', (e) => (e.preventDefault())); 17 18 function resetState() { 19 invokerbutton.setAttribute("commandfor", "invokee"); 20 invokerbutton.setAttribute("command", "--custom-command"); 21 invokerbutton.removeAttribute("disabled"); 22 invokerbutton.removeAttribute("form"); 23 invokerbutton.removeAttribute("type"); 24 } 25 26 test(function (t) { 27 let event = null; 28 invokee.addEventListener("command", (e) => (event = e), { once: true }); 29 invokerbutton.click(); 30 assert_true(event instanceof CommandEvent, "event is CommandEvent"); 31 assert_equals(event.type, "command", "type"); 32 assert_equals(event.bubbles, false, "bubbles"); 33 assert_equals(event.composed, false, "composed"); 34 assert_equals(event.isTrusted, true, "isTrusted"); 35 assert_equals(event.command, "--custom-command", "command"); 36 assert_equals(event.target, invokee, "target"); 37 assert_equals(event.source, invokerbutton, "source"); 38 }, "event dispatches on click with addEventListener"); 39 40 test(function (t) { 41 let event = null; 42 t.add_cleanup(() => { 43 invokee.oncommand = null; 44 }); 45 invokee.oncommand = (e) => (event = e); 46 invokerbutton.click(); 47 assert_true(event instanceof CommandEvent, "event is CommandEvent"); 48 assert_equals(event.type, "command", "type"); 49 assert_equals(event.bubbles, false, "bubbles"); 50 assert_equals(event.composed, false, "composed"); 51 assert_equals(event.isTrusted, true, "isTrusted"); 52 assert_equals(event.command, "--custom-command", "command"); 53 assert_equals(event.target, invokee, "target"); 54 assert_equals(event.source, invokerbutton, "source"); 55 }, "event dispatches on click with oncommand property"); 56 57 // valid custom invokeactions 58 ["--foo", "--foo-", "--cAsE-cArRiEs", "--", "--a-", "--a-b", "---", "--show-picker"].forEach( 59 (command) => { 60 test(function (t) { 61 t.add_cleanup(resetState); 62 let event = null; 63 invokee.addEventListener("command", (e) => (event = e), { once: true }); 64 invokerbutton.command = command; 65 invokerbutton.click(); 66 assert_true(event instanceof CommandEvent, "event is CommandEvent"); 67 assert_equals(event.type, "command", "type"); 68 assert_equals(event.bubbles, false, "bubbles"); 69 assert_equals(event.composed, false, "composed"); 70 assert_equals(event.isTrusted, true, "isTrusted"); 71 assert_equals(event.command, command, "command"); 72 assert_equals(event.target, invokee, "target"); 73 assert_equals(event.source, invokerbutton, "source"); 74 }, `setting custom command property to ${command} (must include dash) sets event command`); 75 76 test(function (t) { 77 t.add_cleanup(resetState); 78 let event = null; 79 invokee.addEventListener("command", (e) => (event = e), { once: true }); 80 invokerbutton.setAttribute("command", command); 81 invokerbutton.click(); 82 assert_true(event instanceof CommandEvent, "event is CommandEvent"); 83 assert_equals(event.type, "command", "type"); 84 assert_equals(event.bubbles, false, "bubbles"); 85 assert_equals(event.composed, false, "composed"); 86 assert_equals(event.isTrusted, true, "isTrusted"); 87 assert_equals(event.command, command, "command"); 88 assert_equals(event.target, invokee, "target"); 89 assert_equals(event.source, invokerbutton, "source"); 90 }, `setting custom command attribute to ${command} (must include dash) sets event command`); 91 }, 92 ); 93 94 // invalid custom invokeactions 95 ["-foo", "-foo-", "foo-bar", "-foo bar", "—-emdash", "hidedocument"].forEach((command) => { 96 test(function (t) { 97 t.add_cleanup(resetState); 98 let event = null; 99 invokee.addEventListener("command", (e) => (event = e), { once: true }); 100 invokerbutton.command = command; 101 invokerbutton.click(); 102 assert_equals(event, null, "event should not have fired"); 103 }, `setting custom command property to ${command} (no dash) did not dispatch an event`); 104 105 test(function (t) { 106 t.add_cleanup(resetState); 107 let event = null; 108 invokee.addEventListener("command", (e) => (event = e), { once: true }); 109 invokerbutton.setAttribute("command", command); 110 invokerbutton.click(); 111 assert_equals(event, null, "event should not have fired"); 112 }, `setting custom command attribute to ${command} (no dash) did not dispatch an event`); 113 }); 114 115 test(function (t) { 116 let called = false; 117 invokerbutton.addEventListener( 118 "click", 119 (event) => { 120 event.preventDefault(); 121 }, 122 { once: true }, 123 ); 124 invokee.addEventListener( 125 "command", 126 (event) => { 127 called = true; 128 }, 129 { once: true }, 130 ); 131 invokerbutton.click(); 132 assert_false(called, "event was not called"); 133 }, "event does not dispatch if click:preventDefault is called"); 134 135 test(function (t) { 136 let event = null; 137 invokee.addEventListener("command", (e) => (event = e), { once: true }); 138 invalidbutton.click(); 139 assert_equals(event, null, "command should not have fired"); 140 }, "event does not dispatch on input[type=button]"); 141 142 test(function (t) { 143 t.add_cleanup(resetState); 144 let called = false; 145 invokee.addEventListener("command", (e) => (called = true), { once: true }); 146 invokerbutton.setAttribute("disabled", ""); 147 invokerbutton.click(); 148 assert_false(called, "event was not called"); 149 }, "event does not dispatch if invoker is disabled"); 150 151 test(function (t) { 152 t.add_cleanup(resetState); 153 let called = false; 154 invokee.addEventListener("command", (e) => (called = true), { once: true }); 155 invokerbutton.setAttribute("form", "aform"); 156 invokerbutton.removeAttribute("type"); 157 invokerbutton.click(); 158 assert_false(called, "event was not called"); 159 }, "event does NOT dispatch if button is form associated, with implicit type"); 160 161 test(function (t) { 162 t.add_cleanup(resetState); 163 let called = false; 164 invokee.addEventListener("command", (e) => (called = true), { once: true }); 165 invokerbutton.setAttribute("form", "aform"); 166 invokerbutton.setAttribute("type", "invalid"); 167 invokerbutton.click(); 168 assert_false(called, "event was not called"); 169 }, "event does NOT dispatch if button is form associated, with explicit type=invalid"); 170 171 test(function (t) { 172 t.add_cleanup(resetState); 173 let event; 174 invokee.addEventListener("command", (e) => (event = e), { once: true }); 175 invokerbutton.setAttribute("form", "aform"); 176 invokerbutton.setAttribute("type", "button"); 177 invokerbutton.click(); 178 assert_true(event instanceof CommandEvent, "event is CommandEvent"); 179 assert_equals(event.type, "command", "type"); 180 assert_equals(event.bubbles, false, "bubbles"); 181 assert_equals(event.composed, false, "composed"); 182 assert_equals(event.isTrusted, true, "isTrusted"); 183 assert_equals(event.command, "--custom-command", "command"); 184 assert_equals(event.target, invokee, "target"); 185 assert_equals(event.source, invokerbutton, "source"); 186 }, "event dispatches if button is form associated, with explicit type=button"); 187 188 test(function (t) { 189 t.add_cleanup(resetState); 190 let called = false; 191 invokee.addEventListener("command", (e) => (called = true), { once: true }); 192 invokerbutton.setAttribute("form", "aform"); 193 invokerbutton.setAttribute("type", "submit"); 194 invokerbutton.click(); 195 assert_false(called, "event was not called"); 196 }, "event does NOT dispatch if button is form associated, with explicit type=submit"); 197 198 test(function (t) { 199 t.add_cleanup(resetState); 200 let called = false; 201 invokee.addEventListener("command", (e) => (called = true), { once: true }); 202 invokerbutton.setAttribute("form", "aform"); 203 invokerbutton.setAttribute("type", "reset"); 204 invokerbutton.click(); 205 assert_false(called, "event was called"); 206 }, "event does NOT dispatch if button is form associated, with explicit type=reset"); 207 208 test(function (t) { 209 svgInvokee = document.createElementNS("http://www.w3.org/2000/svg", "svg"); 210 svgInvokee.setAttribute("id", "svg-invokee"); 211 t.add_cleanup(resetState); 212 document.body.append(svgInvokee); 213 assert_false(svgInvokee instanceof HTMLElement); 214 assert_true(svgInvokee instanceof Element); 215 let event = null; 216 svgInvokee.addEventListener("command", (e) => (event = e), { once: true }); 217 invokerbutton.setAttribute("commandfor", "svg-invokee"); 218 invokerbutton.setAttribute("command", "--custom-command"); 219 assert_equals(invokerbutton.commandForElement, svgInvokee); 220 invokerbutton.click(); 221 assert_not_equals(event, null, "event was called"); 222 assert_true(event instanceof CommandEvent, "event is CommandEvent"); 223 assert_equals(event.source, invokerbutton, "event.invoker is set to right element"); 224 assert_equals(event.target, svgInvokee, "event.target is set to right element"); 225 }, "event dispatches if invokee is non-HTML Element"); 226 </script>