test_bug935876.html (15365B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=935876 5 --> 6 <head> 7 <meta charset="utf-8"> 8 <title>Test for Bug 935876</title> 9 <script src="/tests/SimpleTest/SimpleTest.js"></script> 10 <script src="/tests/SimpleTest/EventUtils.js"></script> 11 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 12 </head> 13 <body> 14 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=935876">Mozilla Bug 935876</a> 15 <p id="display"></p> 16 <div> 17 <select id="listbox" size="3"> 18 <option selected>1</option> 19 <option>2</option> 20 <option>3</option> 21 <option>4</option> 22 <option>5</option> 23 <option>6</option> 24 <option>7</option> 25 </select> 26 <select id="multipleListbox" size="3" multiple> 27 <option selected>1</option> 28 <option>2</option> 29 <option>3</option> 30 <option>4</option> 31 <option>5</option> 32 <option>6</option> 33 <option>7</option> 34 </select> 35 <select id="combobox"> 36 <option selected>1</option> 37 <option>2</option> 38 <option>3</option> 39 <option>4</option> 40 <option>5</option> 41 <option>6</option> 42 <option>7</option> 43 </select> 44 </div> 45 <pre id="test"> 46 </pre> 47 <script type="application/javascript"> 48 SimpleTest.waitForExplicitFinish(); 49 50 const kIsWin = navigator.platform.indexOf("Win") == 0; 51 const kIsMac = navigator.platform.indexOf("Mac") == 0; 52 const kIsAndroid = navigator.appVersion.indexOf("Android") != 0; 53 54 function runTests() 55 { 56 var doPreventDefault = false; 57 function onKeydown(aEvent) 58 { 59 if (doPreventDefault) { 60 aEvent.preventDefault(); 61 } 62 } 63 64 var keyPressEventFired = false; 65 function onKeypress(aEvent) 66 { 67 keyPressEventFired = true; 68 } 69 70 var keyDownEventConsumedByJS = false; 71 var keyDownEventConsumed = false; 72 function onkeydownInSystemEventGroup(aEvent) 73 { 74 keyDownEventConsumedByJS = aEvent.defaultPrevented; 75 // If defaultPrevented is true via SpecialPowers, that means default was 76 // prevented, possibly in a non-content-visible way (e.g. by a system 77 // group handler). 78 keyDownEventConsumed = SpecialPowers.wrap(aEvent).defaultPrevented; 79 } 80 81 function reset() 82 { 83 keyPressEventFired = false; 84 keyDownEventConsumedByJS = false; 85 keyDownEventConsumed = false; 86 } 87 88 function check(aExpectingKeydownConsumed, aIsPrintableKey, aDescription) 89 { 90 if (doPreventDefault) { 91 ok(!keyPressEventFired, "keypress event shouldn't be fired for " + aDescription + 92 " if preventDefault() of keydown event was called"); 93 ok(keyDownEventConsumedByJS, "keydown event of " + aDescription + 94 " should be consumed in content level if preventDefault() of keydown event is called"); 95 ok(keyDownEventConsumed, "keydown event of " + aDescription + 96 " should be consumed in system level if preventDefault() of keydown event is called"); 97 } else if (aExpectingKeydownConsumed) { 98 ok(!keyPressEventFired, "keypress event shouldn't be fired for " + aDescription); 99 ok(!keyDownEventConsumedByJS, "keydown event of " + aDescription + " shouldn't be consumed in content level"); 100 ok(keyDownEventConsumed, "keydown event of " + aDescription + " should be consumed in system level"); 101 } else { 102 if (aIsPrintableKey) { 103 ok(keyPressEventFired, "keypress event should be fired for printable key, " + aDescription); 104 } else { 105 ok(!keyPressEventFired, "keypress event shouldn't be fired for non-printable key, " + aDescription); 106 } 107 ok(!keyDownEventConsumedByJS, "keydown event of " + aDescription + " shouldn't be consumed in content level"); 108 ok(!keyDownEventConsumed, "keydown event of " + aDescription + " should be consumed in system level"); 109 } 110 } 111 112 var listbox = document.getElementById("listbox"); 113 listbox.addEventListener("keydown", onKeydown); 114 listbox.addEventListener("keypress", onKeypress); 115 SpecialPowers.wrap(listbox).addEventListener("keydown", onkeydownInSystemEventGroup, { mozSystemGroup: true }); 116 117 listbox.focus(); 118 119 [ false, true ].forEach(function (consume) { 120 doPreventDefault = consume; 121 for (var i = 0; i < listbox.options.length + 1; i++) { 122 reset() 123 synthesizeKey("KEY_ArrowDown"); 124 check(true, false, "DownArrow key on listbox #" + i); 125 } 126 127 for (var i = 0; i < listbox.options.length + 1; i++) { 128 reset() 129 synthesizeKey("KEY_ArrowUp"); 130 check(true, false, "'ArrowUp' key on listbox #" + i); 131 } 132 133 for (var i = 0; i < listbox.options.length + 1; i++) { 134 reset() 135 synthesizeKey("KEY_ArrowRight"); 136 check(true, false, "'ArrowRight' key on listbox #" + i); 137 } 138 139 for (var i = 0; i < listbox.options.length + 1; i++) { 140 reset() 141 synthesizeKey("KEY_ArrowLeft"); 142 check(true, false, "'ArrowLeft' key on listbox #" + i); 143 } 144 145 for (var i = 0; i < 4; i++) { 146 reset() 147 synthesizeKey("KEY_PageDown"); 148 check(true, false, "'PageDown' key on listbox #" + i); 149 } 150 151 for (var i = 0; i < 4; i++) { 152 reset() 153 synthesizeKey("KEY_PageUp"); 154 check(true, false, "'PageUp' key on listbox #" + i); 155 } 156 157 for (var i = 0; i < 2; i++) { 158 reset() 159 synthesizeKey("KEY_End"); 160 check(true, false, "'End' key on listbox #" + i); 161 } 162 163 for (var i = 0; i < 2; i++) { 164 reset() 165 synthesizeKey("KEY_Home"); 166 check(true, false, "'Home' key on listbox #" + i); 167 } 168 169 reset() 170 synthesizeKey("KEY_Enter"); 171 check(false, true, "'Enter' key on listbox"); 172 173 reset() 174 synthesizeKey("KEY_Escape"); 175 check(false, false, "'Escape' key on listbox"); 176 177 reset() 178 synthesizeKey("KEY_F4"); 179 check(false, false, "F4 key on listbox"); 180 181 reset() 182 sendString("a"); 183 check(false, true, "'A' key on listbox"); 184 }); 185 186 listbox.removeEventListener("keydown", onKeydown); 187 listbox.removeEventListener("keypress", onKeypress); 188 SpecialPowers.wrap(listbox).removeEventListener("keydown", onkeydownInSystemEventGroup, { mozSystemGroup: true }); 189 190 191 var multipleListbox = document.getElementById("multipleListbox"); 192 multipleListbox.addEventListener("keydown", onKeydown); 193 multipleListbox.addEventListener("keypress", onKeypress); 194 SpecialPowers.wrap(multipleListbox).addEventListener("keydown", onkeydownInSystemEventGroup, { mozSystemGroup: true }); 195 196 multipleListbox.focus(); 197 198 [ false, true ].forEach(function (consume) { 199 doPreventDefault = consume; 200 for (var i = 0; i < multipleListbox.options.length + 1; i++) { 201 reset() 202 synthesizeKey("KEY_ArrowDown"); 203 check(true, false, "'ArrowDown' key on multiple listbox #" + i); 204 } 205 206 for (var i = 0; i < multipleListbox.options.length + 1; i++) { 207 reset() 208 synthesizeKey("KEY_ArrowUp"); 209 check(true, false, "'ArrowUp' key on multiple listbox #" + i); 210 } 211 212 for (var i = 0; i < multipleListbox.options.length + 1; i++) { 213 reset() 214 synthesizeKey("KEY_ArrowRight"); 215 check(true, false, "'ArrowRight' key on multiple listbox #" + i); 216 } 217 218 for (var i = 0; i < multipleListbox.options.length + 1; i++) { 219 reset() 220 synthesizeKey("KEY_ArrowLeft"); 221 check(true, false, "'ArrowLeft' key on multiple listbox #" + i); 222 } 223 224 for (var i = 0; i < 4; i++) { 225 reset() 226 synthesizeKey("KEY_PageDown"); 227 check(true, false, "'PageDown' key on multiple listbox #" + i); 228 } 229 230 for (var i = 0; i < 4; i++) { 231 reset() 232 synthesizeKey("KEY_PageUp"); 233 check(true, false, "'PageUp' key on multiple listbox #" + i); 234 } 235 236 for (var i = 0; i < 2; i++) { 237 reset() 238 synthesizeKey("KEY_End"); 239 check(true, false, "'End' key on multiple listbox #" + i); 240 } 241 242 for (var i = 0; i < 2; i++) { 243 reset() 244 synthesizeKey("KEY_Home"); 245 check(true, false, "'Home' key on multiple listbox #" + i); 246 } 247 248 reset() 249 synthesizeKey("KEY_Enter"); 250 check(true, true, "'Enter' key on multiple listbox"); 251 252 reset() 253 synthesizeKey("KEY_Escape"); 254 check(false, false, "'Escape' key on multiple listbox"); 255 256 reset() 257 synthesizeKey("KEY_F4"); 258 check(false, false, "'F4' key on multiple listbox"); 259 260 reset() 261 sendString("a"); 262 check(false, true, "'A' key on multiple listbox"); 263 }); 264 265 multipleListbox.removeEventListener("keydown", onKeydown); 266 multipleListbox.removeEventListener("keypress", onKeypress); 267 SpecialPowers.wrap(multipleListbox).removeEventListener("keydown", onkeydownInSystemEventGroup, { mozSystemGroup: true }); 268 269 270 var combobox = document.getElementById("combobox"); 271 combobox.addEventListener("keydown", onKeydown); 272 combobox.addEventListener("keypress", onKeypress); 273 SpecialPowers.wrap(combobox).addEventListener("keydown", onkeydownInSystemEventGroup, { mozSystemGroup: true }); 274 275 combobox.focus(); 276 277 [ false, true ].forEach(function (consume) { 278 doPreventDefault = consume; 279 if (!kIsMac) { 280 for (var i = 0; i < combobox.options.length + 1; i++) { 281 reset() 282 synthesizeKey("KEY_ArrowDown"); 283 check(true, false, "'ArrowDown' key on combobox #" + i); 284 } 285 286 for (var i = 0; i < combobox.options.length + 1; i++) { 287 reset() 288 synthesizeKey("KEY_ArrowUp"); 289 check(true, false, "'ArrowUp' key on combobox #" + i); 290 } 291 } else { 292 todo(false, "Make this test work on OSX"); 293 } 294 295 for (var i = 0; i < combobox.options.length + 1; i++) { 296 reset() 297 synthesizeKey("KEY_ArrowRight"); 298 check(true, false, "'ArrowRight' key on combobox #" + i); 299 } 300 301 for (var i = 0; i < combobox.options.length + 1; i++) { 302 reset() 303 synthesizeKey("KEY_ArrowLeft"); 304 check(true, false, "'ArrowLeft' key on combobox #" + i); 305 } 306 307 for (var i = 0; i < 4; i++) { 308 reset() 309 synthesizeKey("KEY_PageDown"); 310 check(true, false, "'PageDown' key on combobox #" + i); 311 } 312 313 for (var i = 0; i < 4; i++) { 314 reset() 315 synthesizeKey("KEY_PageUp"); 316 check(true, false, "'PageUp' key on combobox #" + i); 317 } 318 319 for (var i = 0; i < 2; i++) { 320 reset() 321 synthesizeKey("KEY_End"); 322 check(true, false, "'End' key on combobox #" + i); 323 } 324 325 for (var i = 0; i < 2; i++) { 326 reset() 327 synthesizeKey("KEY_Home"); 328 check(true, false, "'Home' key on combobox #" + i); 329 } 330 331 reset() 332 synthesizeKey("KEY_Enter"); 333 check(false, true, "'Enter' key on combobox"); 334 335 reset() 336 synthesizeKey("KEY_Escape"); 337 check(false, false, "'Escape' key on combobox"); 338 339 if (!kIsWin) { 340 reset() 341 synthesizeKey("KEY_F4"); 342 check(false, false, "'F4' key on combobox"); 343 } 344 345 reset() 346 sendString("a"); 347 check(false, true, "'A' key on combobox"); 348 }); 349 350 function finish() 351 { 352 combobox.removeEventListener("keydown", onKeydown); 353 combobox.removeEventListener("keypress", onKeypress); 354 SpecialPowers.wrap(combobox).removeEventListener("keydown", onkeydownInSystemEventGroup, { mozSystemGroup: true }); 355 SimpleTest.finish(); 356 } 357 358 // Mac uses native popup for dropdown. Let's skip the tests for popup 359 // since it's not handled in nsListControlFrame. 360 // Similarly, Android doesn't use popup for dropdown. 361 if (kIsMac || kIsAndroid) { 362 finish(); 363 return; 364 } 365 366 function testDropDown(aCallback) 367 { 368 testOpenDropDown(function () { 369 reset() 370 synthesizeKey("KEY_ArrowDown", {altKey: true}); 371 }, function () { 372 check(true, false, "Alt + DownArrow key on combobox at opening dropdown"); 373 374 for (var i = 0; i < combobox.options.length + 1; i++) { 375 reset() 376 synthesizeKey("KEY_ArrowDown"); 377 check(true, false, "'ArrowDown' key on combobox during dropdown open #" + i); 378 } 379 380 for (var i = 0; i < combobox.options.length + 1; i++) { 381 reset() 382 synthesizeKey("KEY_ArrowUp"); 383 check(true, false, "'ArrowUp' key on combobox during dropdown open #" + i); 384 } 385 386 for (var i = 0; i < combobox.options.length + 1; i++) { 387 reset() 388 synthesizeKey("KEY_ArrowRight"); 389 check(true, false, "'ArrowRight' key on combobox during dropdown open #" + i); 390 } 391 392 for (var i = 0; i < combobox.options.length + 1; i++) { 393 reset() 394 synthesizeKey("KEY_ArrowLeft"); 395 check(true, false, "'ArrowLeft' key on combobox during dropdown open #" + i); 396 } 397 398 for (var i = 0; i < 4; i++) { 399 reset() 400 synthesizeKey("KEY_PageDown"); 401 check(true, false, "'PageDown' key on combobox during dropdown open #" + i); 402 } 403 404 for (var i = 0; i < 4; i++) { 405 reset() 406 synthesizeKey("KEY_PageUp"); 407 check(true, false, "'PageUp' key on combobox during dropdown open #" + i); 408 } 409 410 for (var i = 0; i < 2; i++) { 411 reset() 412 synthesizeKey("KEY_End"); 413 check(true, false, "'End' key on combobox during dropdown open #" + i); 414 } 415 416 for (var i = 0; i < 2; i++) { 417 reset() 418 synthesizeKey("KEY_Home"); 419 check(true, false, "'Home' key on combobox during dropdown open #" + i); 420 } 421 422 testCloseDropDown(function () { 423 reset() 424 synthesizeKey("KEY_Enter"); 425 }, function () { 426 testOpenDropDown(function () { 427 check(true, true, "'Enter' key on combobox at closing dropdown"); 428 429 synthesizeKey("KEY_ArrowUp", {altKey: true}); 430 }, function () { 431 check(true, false, "'Alt' + 'ArrowUp' key on combobox at opening dropdown"); 432 433 testCloseDropDown(function () { 434 reset() 435 synthesizeKey("KEY_Escape"); 436 }, function () { 437 check(true, false, "'Escape' key on combobox at closing dropdown"); 438 439 // F4 key opens/closes dropdown only on Windows. So, other platforms 440 // don't need to do anymore. 441 if (!kIsWin) { 442 aCallback(); 443 return; 444 } 445 446 testOpenDropDown(function () { 447 reset() 448 synthesizeKey("KEY_F4"); 449 }, function () { 450 check(true, false, "'F4' key on combobox at opening dropdown on Windows"); 451 452 testCloseDropDown(function () { 453 reset() 454 synthesizeKey("KEY_F4"); 455 }, function () { 456 check(true, false, "'F4' key on combobox at closing dropdown on Windows"); 457 458 aCallback(); 459 return; 460 }); 461 }); 462 }); 463 }); 464 }); 465 }); 466 } 467 468 doPreventDefault = false; 469 testDropDown(function () { 470 // Even if keydown event is consumed by JS, opening/closing dropdown 471 // should work for a11y and security (e.g., cannot close dropdown causes 472 // staying top-most window on the screen). If it's blocked by JS, this 473 // test would cause permanent timeout. 474 doPreventDefault = true; 475 testDropDown(finish); 476 }); 477 } 478 479 function testOpenDropDown(aTest, aOnOpenDropDown) 480 { 481 document.addEventListener("popupshowing", function (aEvent) { 482 document.removeEventListener(aEvent.type, arguments.callee); 483 setTimeout(aOnOpenDropDown, 0); 484 }); 485 aTest(); 486 } 487 488 function testCloseDropDown(aTest, aOnCloseDropDown) 489 { 490 document.addEventListener("popuphiding", function (aEvent) { 491 document.removeEventListener(aEvent.type, arguments.callee); 492 setTimeout(aOnCloseDropDown, 0) 493 }); 494 aTest(); 495 } 496 497 SimpleTest.waitForFocus(runTests); 498 </script> 499 </body> 500 </html>