test_input_number_mouse_events.html (10438B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=935501 5 --> 6 <head> 7 <title>Test mouse events for number</title> 8 <script src="/tests/SimpleTest/SimpleTest.js"></script> 9 <script src="/tests/SimpleTest/EventUtils.js"></script> 10 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 11 <meta charset="UTF-8"> 12 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 13 <style> 14 input { 15 margin: 0; 16 border: 0; 17 padding: 0; 18 width: 200px; 19 box-sizing: border-box; 20 } 21 </style> 22 </head> 23 <body> 24 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=935501">Mozilla Bug 935501</a> 25 <p id="display"></p> 26 <div id="content"> 27 <input id="input" type="number"> 28 </div> 29 <pre id="test"> 30 <script> 31 32 const { AppConstants } = SpecialPowers.ChromeUtils.importESModule( 33 "resource://gre/modules/AppConstants.sys.mjs" 34 ); 35 36 /** 37 * Test for Bug 935501 38 * This test checks how the value of <input type=number> changes in response to 39 * various mouse events. 40 */ 41 SimpleTest.waitForExplicitFinish(); 42 SimpleTest.requestFlakyTimeout("untriaged"); 43 SimpleTest.waitForFocus(function() { 44 test(); 45 }); 46 47 const kIsWin = AppConstants.platform == "win"; 48 const kIsLinux = AppConstants.platform == "linux"; 49 50 var input = document.getElementById("input"); 51 var inputRect = input.getBoundingClientRect(); 52 53 // Points over the input's spin-up and spin-down buttons (as offsets from the 54 // top-left of the input's bounding client rect): 55 const SPIN_UP_X = inputRect.width - 3; 56 const SPIN_UP_Y = 3; 57 const SPIN_DOWN_X = inputRect.width - 3; 58 const SPIN_DOWN_Y = inputRect.height - 3; 59 60 function checkInputEvent(aEvent, aDescription) { 61 // Probably, key operation should fire "input" event with InputEvent interface. 62 // See https://github.com/w3c/input-events/issues/88 63 ok(aEvent instanceof InputEvent, `"input" event should be dispatched with InputEvent interface on input element whose type is number ${aDescription}`); 64 is(aEvent.cancelable, false, `"input" event should be never cancelable on input element whose type is number ${aDescription}`); 65 is(aEvent.bubbles, true, `"input" event should always bubble on input element whose type is number ${aDescription}`); 66 info(`Data: ${aEvent.data}, value: ${aEvent.target.value}`); 67 } 68 69 function test() { 70 input.value = 0; 71 72 // Test click on spin-up button: 73 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" }); 74 is(input.value, "1", "Test step-up on mousedown on spin-up button"); 75 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" }); 76 is(input.value, "1", "Test mouseup on spin-up button"); 77 78 // Test click on spin-down button: 79 synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" }); 80 is(input.value, "0", "Test step-down on mousedown on spin-down button"); 81 synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" }); 82 is(input.value, "0", "Test mouseup on spin-down button"); 83 84 // Test clicks with modifiers that mean we should ignore the click: 85 var modifiersIgnore = ["altGrKey", "fnKey"]; 86 if (kIsWin || kIsLinux) { 87 modifiersIgnore.push("metaKey"); 88 } 89 for (var modifier of modifiersIgnore) { 90 input.value = 0; 91 var eventParams = { type: "mousedown" }; 92 eventParams[modifier] = true; 93 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, eventParams); 94 is(input.value, "0", "We should ignore mousedown on spin-up button with modifier " + modifier); 95 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" }); 96 } 97 98 // Test clicks with modifiers that mean we should allow the click: 99 var modifiersAllow = ["shiftKey", "ctrlKey", "altKey"]; 100 if (!modifiersIgnore.includes("metaKey")) { 101 modifiersAllow.push("metaKey"); 102 } 103 for (var modifier of modifiersAllow) { 104 input.value = 0; 105 var eventParams = { type: "mousedown" }; 106 eventParams[modifier] = true; 107 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, eventParams); 108 is(input.value, "1", "We should allow mousedown on spin-up button with modifier " + modifier); 109 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" }); 110 } 111 112 // Test step="any" behavior: 113 input.value = 0; 114 var oldStep = input.step; 115 input.step = "any"; 116 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" }); 117 is(input.value, "1", "Test step-up on mousedown on spin-up button with step='any'"); 118 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" }); 119 is(input.value, "1", "Test mouseup on spin-up button with step='any'"); 120 synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" }); 121 is(input.value, "0", "Test step-down on mousedown on spin-down button with step='any'"); 122 synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" }); 123 is(input.value, "0", "Test mouseup on spin-down button with step='any'"); 124 input.step = oldStep; // restore 125 126 // Test that preventDefault() works: 127 function preventDefault(e) { 128 e.preventDefault(); 129 } 130 input.value = 1; 131 input.addEventListener("mousedown", preventDefault); 132 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, {}); 133 is(input.value, "1", "Test that preventDefault() works for click on spin-up button"); 134 synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, {}); 135 is(input.value, "1", "Test that preventDefault() works for click on spin-down button"); 136 input.removeEventListener("mousedown", preventDefault); 137 138 // Test for bug 1707070. 139 input.style.paddingRight = "30px"; 140 input.getBoundingClientRect(); // flush layout 141 142 input.value = 0; 143 synthesizeMouse(input, SPIN_UP_X - 30, SPIN_UP_Y, { type: "mousedown" }); 144 is(input.value, "1", "Spinner down works on with padding (mousedown)"); 145 synthesizeMouse(input, SPIN_UP_X - 30, SPIN_UP_Y, { type: "mouseup" }); 146 is(input.value, "1", "Spinner down works with padding (mouseup)"); 147 148 synthesizeMouse(input, SPIN_DOWN_X - 30, SPIN_DOWN_Y, { type: "mousedown" }); 149 is(input.value, "0", "Spinner works with padding (mousedown)"); 150 synthesizeMouse(input, SPIN_DOWN_X - 30, SPIN_DOWN_Y, { type: "mouseup" }); 151 is(input.value, "0", "Spinner works with padding (mouseup)"); 152 153 input.style.paddingRight = ""; 154 input.getBoundingClientRect(); // flush layout 155 156 // Run the spin tests: 157 runNextSpinTest(); 158 } 159 160 function runNextSpinTest() { 161 var nextTest = spinTests.shift(); 162 if (!nextTest) { 163 SimpleTest.finish(); 164 return; 165 } 166 nextTest(); 167 } 168 169 function waitForTick() { 170 return new Promise(SimpleTest.executeSoon); 171 } 172 173 const SETTIMEOUT_DELAY = 500; 174 175 var spinTests = [ 176 // Test spining when the mouse button is kept depressed on the spin-up 177 // button, then moved over the spin-down button: 178 function() { 179 var inputEventCount = 0; 180 input.value = 0; 181 input.addEventListener("input", async function(evt) { 182 ++inputEventCount; 183 checkInputEvent(evt, "#1"); 184 if (inputEventCount == 3) { 185 is(input.value, "3", "Testing spin-up button"); 186 await waitForTick(); 187 synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousemove" }); 188 } else if (inputEventCount == 6) { 189 is(input.value, "0", "Testing spin direction is reversed after mouse moves from spin-up button to spin-down button"); 190 input.removeEventListener("input", arguments.callee); 191 await waitForTick(); 192 synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" }); 193 runNextSpinTest(); 194 } 195 }); 196 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" }); 197 }, 198 199 // Test spining when the mouse button is kept depressed on the spin-down 200 // button, then moved over the spin-up button: 201 function() { 202 var inputEventCount = 0; 203 input.value = 0; 204 input.addEventListener("input", async function(evt) { 205 ++inputEventCount; 206 checkInputEvent(evt, "#2"); 207 if (inputEventCount == 3) { 208 is(input.value, "-3", "Testing spin-down button"); 209 await waitForTick(); 210 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousemove" }); 211 } else if (inputEventCount == 6) { 212 is(input.value, "0", "Testing spin direction is reversed after mouse moves from spin-down button to spin-up button"); 213 input.removeEventListener("input", arguments.callee); 214 await waitForTick(); 215 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" }); 216 runNextSpinTest(); 217 } 218 }); 219 synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" }); 220 }, 221 222 // Test that the spin is stopped when the mouse button is depressod on the 223 // spin-up button, then moved outside both buttons once the spin starts: 224 function() { 225 var inputEventCount = 0; 226 input.value = 0; 227 input.addEventListener("input", async function(evt) { 228 ++inputEventCount; 229 checkInputEvent(evt, "#3"); 230 if (inputEventCount == 3) { 231 await waitForTick(); 232 synthesizeMouse(input, -1, -1, { type: "mousemove" }); 233 var eventHandler = arguments.callee; 234 setTimeout(function() { 235 is(input.value, "3", "Testing moving the mouse outside the spin buttons stops the spin"); 236 is(inputEventCount, 3, "Testing moving the mouse outside the spin buttons stops the spin input events"); 237 input.removeEventListener("input", eventHandler); 238 synthesizeMouse(input, -1, -1, { type: "mouseup" }); 239 runNextSpinTest(); 240 }, SETTIMEOUT_DELAY); 241 } 242 }); 243 synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" }); 244 }, 245 246 // Test that changing the input type in the middle of a spin cancels the spin: 247 function() { 248 var inputEventCount = 0; 249 input.value = 0; 250 input.addEventListener("input", function(evt) { 251 ++inputEventCount; 252 checkInputEvent(evt, "#4"); 253 if (inputEventCount == 3) { 254 input.type = "text" 255 var eventHandler = arguments.callee; 256 setTimeout(function() { 257 is(input.value, "-3", "Testing changing input type during a spin stops the spin"); 258 is(inputEventCount, 3, "Testing changing input type during a spin stops the spin input events"); 259 input.removeEventListener("input", eventHandler); 260 synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" }); 261 input.type = "number"; // restore 262 runNextSpinTest(); 263 }, SETTIMEOUT_DELAY); 264 } 265 }); 266 synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" }); 267 } 268 ]; 269 </script> 270 </pre> 271 </body> 272 </html>