test_bug603008.html (17716B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=508906 5 --> 6 <head> 7 <title>Test for Bug 603008</title> 8 <script src="/tests/SimpleTest/SimpleTest.js"></script> 9 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 10 </head> 11 <body> 12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=508906">Mozilla Bug 603008</a> 13 <p id="display"></p> 14 <div id="content" style="display: none"> 15 16 </div> 17 <pre id="test"> 18 <script class="testbody" type="application/javascript"> 19 20 /** Test for Bug 306008 - Touch* Events */ 21 22 let tests = [], testTarget, parent; 23 24 let touch = { 25 id: 0, 26 point: {x: 0, y: 0}, 27 radius: {x: 0, y: 0}, 28 rotation: 0, 29 force: 0.5, 30 target: null 31 } 32 33 function nextTest() { 34 if (tests.length) 35 SimpleTest.executeSoon(tests.shift()); 36 } 37 38 function random() { 39 return Math.floor(Math.random() * 100); 40 } 41 42 function checkEvent(aFakeEvent) { 43 return function(aEvent) { 44 is(aFakeEvent.ctrlKey, aEvent.ctrlKey, "Correct ctrlKey"); 45 is(aFakeEvent.altKey, aEvent.altKey, "Correct altKey"); 46 is(aFakeEvent.shiftKey, aEvent.shiftKey, "Correct shiftKey"); 47 is(aFakeEvent.metaKey, aEvent.metaKey, "Correct metaKey"); 48 checkTouches(aFakeEvent.touches, aEvent.touches); 49 checkTouches(aFakeEvent.targetTouches, aEvent.targetTouches); 50 checkTouches(aFakeEvent.changedTouches, aEvent.changedTouches); 51 } 52 } 53 54 function checkTouches(aTouches1, aTouches2) { 55 is(aTouches1.length, aTouches2.length, "Correct touches length"); 56 for (var i = 0; i < aTouches1.length; i++) { 57 checkTouch(aTouches1[i], aTouches2[i]); 58 } 59 } 60 61 function checkTouch(aFakeTouch, aTouch) { 62 is(aFakeTouch.identifier, aTouch.identifier, "Touch has correct identifier"); 63 is(aFakeTouch.target, aTouch.target, "Touch has correct target"); 64 is(aFakeTouch.page.x, aTouch.pageX, "Touch has correct pageX"); 65 is(aFakeTouch.page.y, aTouch.pageY, "Touch has correct pageY"); 66 is(aFakeTouch.page.x + Math.round(window.mozInnerScreenX), aTouch.screenX, "Touch has correct screenX"); 67 is(aFakeTouch.page.y + Math.round(window.mozInnerScreenY), aTouch.screenY, "Touch has correct screenY"); 68 is(aFakeTouch.page.x, aTouch.clientX, "Touch has correct clientX"); 69 is(aFakeTouch.page.y, aTouch.clientY, "Touch has correct clientY"); 70 is(aFakeTouch.radius.x, aTouch.radiusX, "Touch has correct radiusX"); 71 is(aFakeTouch.radius.y, aTouch.radiusY, "Touch has correct radiusY"); 72 is(aFakeTouch.rotationAngle, aTouch.rotationAngle, "Touch has correct rotationAngle"); 73 is(aFakeTouch.force, aTouch.force, "Touch has correct force"); 74 } 75 76 function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) { 77 var ids = [], xs=[], ys=[], rxs = [], rys = [], 78 rotations = [], forces = [], tiltXs = [], tiltYs = [], twists = []; 79 80 for (var touchType of ["touches", "changedTouches", "targetTouches"]) { 81 for (var i = 0; i < aEvent[touchType].length; i++) { 82 if (!ids.includes(aEvent[touchType][i].identifier)) { 83 ids.push(aEvent[touchType][i].identifier); 84 xs.push(aEvent[touchType][i].page.x); 85 ys.push(aEvent[touchType][i].page.y); 86 rxs.push(aEvent[touchType][i].radius.x); 87 rys.push(aEvent[touchType][i].radius.y); 88 rotations.push(aEvent[touchType][i].rotationAngle); 89 forces.push(aEvent[touchType][i].force); 90 tiltXs.push(0); 91 tiltYs.push(0); 92 twists.push(0); 93 } 94 } 95 } 96 return windowUtils.sendTouchEvent(aType, 97 ids, xs, ys, rxs, rys, 98 rotations, forces, tiltXs, tiltYs, twists, 99 aModifiers); 100 } 101 102 function touchEvent(aOptions) { 103 if (!aOptions) { 104 aOptions = {}; 105 } 106 this.ctrlKey = aOptions.ctrlKey || false; 107 this.altKey = aOptions.altKey || false; 108 this.shiftKey = aOptions.shiftKey || false; 109 this.metaKey = aOptions.metaKey || false; 110 this.touches = aOptions.touches || []; 111 this.targetTouches = aOptions.targetTouches || []; 112 this.changedTouches = aOptions.changedTouches || []; 113 } 114 115 function testtouch(aOptions) { 116 if (!aOptions) 117 aOptions = {}; 118 this.identifier = aOptions.identifier || 0; 119 this.target = aOptions.target || 0; 120 this.page = aOptions.page || {x: 0, y: 0}; 121 this.radius = aOptions.radius || {x: 0, y: 0}; 122 this.rotationAngle = aOptions.rotationAngle || 0; 123 this.force = aOptions.force || 1; 124 } 125 126 function testSingleTouch(name) { 127 let cwu = SpecialPowers.getDOMWindowUtils(window); 128 let target = document.getElementById("testTarget"); 129 let target2 = document.getElementById("testTarget2"); 130 let bcr = target.getBoundingClientRect(); 131 let bcr2 = target2.getBoundingClientRect(); 132 133 let touch1 = new testtouch({ 134 page: {x: Math.round(bcr.left + bcr.width/2), 135 y: Math.round(bcr.top + bcr.height/2)}, 136 target 137 }); 138 let event = new touchEvent({ 139 touches: [touch1], 140 targetTouches: [touch1], 141 changedTouches: [touch1] 142 }); 143 144 // test touchstart event fires correctly 145 var checkFunction = checkEvent(event); 146 window.addEventListener("touchstart", checkFunction); 147 sendTouchEvent(cwu, "touchstart", event, 0); 148 window.removeEventListener("touchstart", checkFunction); 149 150 // test touchmove event fires correctly 151 event.touches[0].page.x -= 1; 152 event.targetTouches[0].page.x -= 1; 153 event.changedTouches[0].page.x -= 1; 154 checkFunction = checkEvent(event); 155 window.addEventListener("touchmove", checkFunction); 156 sendTouchEvent(cwu, "touchmove", event, 0); 157 window.removeEventListener("touchmove", checkFunction); 158 159 // test touchend event fires correctly 160 event.touches = []; 161 event.targetTouches = []; 162 checkFunction = checkEvent(event); 163 window.addEventListener("touchend", checkFunction); 164 sendTouchEvent(cwu, "touchend", event, 0); 165 window.removeEventListener("touchend", checkFunction); 166 167 nextTest(); 168 } 169 170 function testSingleTouch2(name) { 171 // firing a touchstart that includes only one touch will evict any touches in the queue with touchend messages 172 let cwu = SpecialPowers.getDOMWindowUtils(window); 173 let target = document.getElementById("testTarget"); 174 let target2 = document.getElementById("testTarget2"); 175 let bcr = target.getBoundingClientRect(); 176 let bcr2 = target2.getBoundingClientRect(); 177 178 let touch1 = new testtouch({ 179 identifier: 0, 180 page: {x: Math.round(bcr.left + bcr.width/2), 181 y: Math.round(bcr.top + bcr.height/2)}, 182 target 183 }); 184 let event1 = new touchEvent({ 185 touches: [touch1], 186 targetTouches: [touch1], 187 changedTouches: [touch1] 188 }); 189 let touch2 = new testtouch({ 190 identifier: 1, 191 page: {x: Math.round(bcr2.left + bcr2.width/2), 192 y: Math.round(bcr2.top + bcr2.height/2)}, 193 target: target2 194 }); 195 let event2 = new touchEvent({ 196 touches: [touch2], 197 targetTouches: [touch2], 198 changedTouches: [touch2] 199 }); 200 201 // test touchstart event fires correctly 202 var checkFunction1 = checkEvent(event1); 203 window.addEventListener("touchstart", checkFunction1); 204 sendTouchEvent(cwu, "touchstart", event1, 0); 205 window.removeEventListener("touchstart", checkFunction1); 206 207 event1.touches = []; 208 event1.targetTouches = []; 209 checkFunction1 = checkEvent(event1); 210 var checkFunction2 = checkEvent(event2); 211 212 window.addEventListener("touchend", checkFunction1); 213 window.addEventListener("touchstart", checkFunction2); 214 sendTouchEvent(cwu, "touchstart", event2, 0); 215 window.removeEventListener("touchend", checkFunction1); 216 window.removeEventListener("touchstart", checkFunction2); 217 218 sendTouchEvent(cwu, "touchstart", event1, 0); 219 220 nextTest(); 221 } 222 223 224 function testMultiTouch(name) { 225 let cwu = SpecialPowers.getDOMWindowUtils(window); 226 let target1 = document.getElementById("testTarget"); 227 let target2 = document.getElementById("testTarget2"); 228 let bcr = target1.getBoundingClientRect(); 229 let bcr2 = target2.getBoundingClientRect(); 230 231 let touch1 = new testtouch({ 232 identifier: 0, 233 page: {x: Math.round(bcr.left + bcr.width/2), 234 y: Math.round(bcr.top + bcr.height/2)}, 235 target: target1 236 }); 237 let touch2 = new testtouch({ 238 identifier: 1, 239 page: {x: Math.round(bcr2.left + bcr2.width/2), 240 y: Math.round(bcr2.top + bcr2.height/2)}, 241 target: target2 242 }); 243 let event = new touchEvent({ 244 touches: [touch1], 245 targetTouches: [touch1], 246 changedTouches: [touch1] 247 }); 248 249 // test touchstart event fires correctly 250 var checkFunction = checkEvent(event); 251 window.addEventListener("touchstart", checkFunction); 252 sendTouchEvent(cwu, "touchstart", event, 0); 253 window.removeEventListener("touchstart", checkFunction); 254 255 event.touches.push(touch2); 256 event.targetTouches = [touch2]; 257 event.changedTouches = [touch2]; 258 window.addEventListener("touchstart", checkFunction); 259 sendTouchEvent(cwu, "touchstart", event, 0); 260 window.removeEventListener("touchstart", checkFunction); 261 262 // test moving one touch point 263 event.touches[0].page.x -= 1; 264 event.targetTouches = [event.touches[0]]; 265 event.changedTouches = [event.touches[0]]; 266 window.addEventListener("touchmove", checkFunction); 267 sendTouchEvent(cwu, "touchmove", event, 0); 268 window.removeEventListener("touchmove", checkFunction); 269 270 // test moving both touch points -- two touchmove events should fire, one on each target 271 event.touches[0].page.x -= 1; 272 event.touches[1].page.x -= 1; 273 event.targetTouches = event.touches; 274 event.changedTouches = event.touches; 275 var touchMoveEvents = 0; 276 var checkFunction2 = function(aEvent) { 277 is(event.ctrlKey, aEvent.ctrlKey, "Correct ctrlKey"); 278 is(event.altKey, aEvent.altKey, "Correct altKey"); 279 is(event.shiftKey, aEvent.shiftKey, "Correct shiftKey"); 280 is(event.metaKey, aEvent.metaKey, "Correct metaKey"); 281 checkTouches(event.touches, aEvent.touches); 282 checkTouches(event.changedTouches, aEvent.changedTouches); 283 if (aEvent.targetTouches[0].target == target1) { 284 checkTouches([event.touches[0]], aEvent.targetTouches); 285 } else if (aEvent.targetTouches[0].target == target2) { 286 checkTouches([event.touches[1]], aEvent.targetTouches); 287 } else 288 ok(false, "Event target is incorrect: " + event.targetTouches[0].target.nodeName + "#" + event.targetTouches[0].target.id); 289 touchMoveEvents++; 290 }; 291 window.addEventListener("touchmove", checkFunction2); 292 sendTouchEvent(cwu, "touchmove", event, 0); 293 is(touchMoveEvents, 2, "Correct number of touchmove events fired"); 294 window.removeEventListener("touchmove", checkFunction2); 295 296 // test removing just one finger 297 var expected = new touchEvent({ 298 touches: [touch2], 299 targetTouches: [], 300 changedTouches: [touch1] 301 }); 302 checkFunction = checkEvent(expected); 303 304 event.touches = []; 305 event.targetTouches = []; 306 event.changedTouches = [touch1]; 307 308 // test removing the other finger 309 window.addEventListener("touchend", checkFunction); 310 sendTouchEvent(cwu, "touchend", event, 0); 311 window.removeEventListener("touchend", checkFunction); 312 313 event.touches = []; 314 event.targetTouches = []; 315 event.changedTouches = [touch2]; 316 checkFunction = checkEvent(event); 317 window.addEventListener("touchend", checkFunction); 318 sendTouchEvent(cwu, "touchend", event, 0); 319 window.removeEventListener("touchend", checkFunction); 320 321 nextTest(); 322 } 323 324 function testTouchChanged() { 325 let cwu = SpecialPowers.getDOMWindowUtils(window); 326 let target1 = document.getElementById("testTarget"); 327 let bcr = target1.getBoundingClientRect(); 328 329 let touch1 = new testtouch({ 330 identifier: 0, 331 page: {x: Math.round(bcr.left + bcr.width/2), 332 y: Math.round(bcr.top + bcr.height/2)}, 333 target: target1 334 }); 335 let event = new touchEvent({ 336 touches: [touch1], 337 targetTouches: [touch1], 338 changedTouches: [touch1] 339 }); 340 341 var checkFunction = checkEvent(event); 342 sendTouchEvent(cwu, "touchstart", event, 0); 343 344 var moveEvents = 0; 345 function onMove(aEvent) { 346 moveEvents++; 347 } 348 349 window.addEventListener("touchmove", onMove); 350 351 // the first touchmove should always fire an event 352 sendTouchEvent(cwu, "touchmove", event, 0); 353 354 // changing nothing should not fire a touchmove event 355 sendTouchEvent(cwu, "touchmove", event, 0); 356 357 // test moving x 358 event.touches[0].page.x -= 1; 359 sendTouchEvent(cwu, "touchmove", event, 0); 360 361 // test moving y 362 event.touches[0].page.y -= 1; 363 sendTouchEvent(cwu, "touchmove", event, 0); 364 365 // test changing y radius 366 event.touches[0].radius.y += 1; 367 sendTouchEvent(cwu, "touchmove", event, 0); 368 369 // test changing x radius 370 event.touches[0].radius.x += 1; 371 sendTouchEvent(cwu, "touchmove", event, 0); 372 373 // test changing rotationAngle 374 event.touches[0].rotationAngle += 1; 375 sendTouchEvent(cwu, "touchmove", event, 0); 376 377 // test changing force 378 event.touches[0].force += 1; 379 sendTouchEvent(cwu, "touchmove", event, 0); 380 381 // changing nothing again 382 sendTouchEvent(cwu, "touchmove", event, 0); 383 384 is(moveEvents, 7, "Six move events fired"); 385 386 window.removeEventListener("touchmove", onMove); 387 sendTouchEvent(cwu, "touchend", event, 0); 388 nextTest(); 389 } 390 391 function testPreventDefault() { 392 let cwu = SpecialPowers.getDOMWindowUtils(window); 393 let target = document.getElementById("testTarget"); 394 let target2 = document.getElementById("testTarget2"); 395 let bcr = target.getBoundingClientRect(); 396 let bcr2 = target2.getBoundingClientRect(); 397 398 let touch1 = new testtouch({ 399 page: {x: bcr.left + bcr.width/2, 400 y: bcr.top + bcr.height/2}, 401 target 402 }); 403 let event = new touchEvent({ 404 touches: [touch1], 405 targetTouches: [touch1], 406 changedTouches: [touch1] 407 }); 408 409 let preventFunction = function(aEvent) { 410 aEvent.preventDefault(); 411 } 412 413 let subTests = [ 414 [{ name: "touchstart", prevent: false }, 415 { name: "touchmove", prevent: false }, 416 { name: "touchmove", prevent: false }, 417 { name: "touchend", prevent: false }], 418 [{ name: "touchstart", prevent: true, doPrevent: true }, 419 { name: "touchmove", prevent: false }, 420 { name: "touchmove", prevent: false }, 421 { name: "touchend", prevent: false }], 422 [{ name: "touchstart", prevent: false }, 423 { name: "touchmove", prevent: true, doPrevent: true }, 424 { name: "touchmove", prevent: false }, 425 { name: "touchend", prevent: false }], 426 [{ name: "touchstart", prevent: false }, 427 { name: "touchmove", prevent: false }, 428 { name: "touchmove", prevent: false, doPrevent: true }, 429 { name: "touchend", prevent: false }], 430 [{ name: "touchstart", prevent: false }, 431 { name: "touchmove", prevent: false }, 432 { name: "touchmove", prevent: false }, 433 { name: "touchend", prevent: true, doPrevent: true }] 434 ]; 435 436 var dotest = function(aTest) { 437 if (aTest.doPrevent) { 438 target.addEventListener(aTest.name, preventFunction); 439 } 440 441 if (aTest.name == "touchmove") { 442 touch1.page.x++; 443 event.touches[0] = touch1; 444 } 445 446 is(sendTouchEvent(cwu, aTest.name, event, 0), aTest.prevent, "Got correct status"); 447 448 if (aTest.doPrevent) 449 target.removeEventListener(aTest.name, preventFunction); 450 } 451 452 for (var i = 0; i < subTests.length; i++) { 453 for (var j = 0; j < subTests[i].length; j++) { 454 dotest(subTests[i][j]); 455 } 456 } 457 458 nextTest(); 459 } 460 461 function testRemovingElement() { 462 let cwu = SpecialPowers.getDOMWindowUtils(window); 463 let target = document.getElementById("testTarget"); 464 let bcr = document.getElementById("testTarget").getBoundingClientRect(); 465 466 let touch1 = new testtouch({ 467 page: {x: bcr.left + bcr.width/2, 468 y: bcr.top + bcr.height/2}, 469 }); 470 let e = new touchEvent({ 471 touches: [touch1], 472 targetTouches: [touch1], 473 changedTouches: [touch1] 474 }); 475 476 var touchEvents = 0; 477 var removeTarget = function(aEvent) { 478 aEvent.target.remove(); 479 }; 480 481 var checkTarget = function(aEvent) { 482 is(aEvent.target, target, "Event has correct target"); 483 touchEvents++; 484 }; 485 486 target.addEventListener("touchstart", removeTarget); 487 target.addEventListener("touchmove", checkTarget); 488 target.addEventListener("touchend", checkTarget); 489 490 sendTouchEvent(cwu, "touchstart", e, 0); 491 492 e.touches[0].page.x++; 493 sendTouchEvent(cwu, "touchmove", e, 0); 494 sendTouchEvent(cwu, "touchend", e, 0); 495 496 target.removeEventListener("touchstart", removeTarget); 497 target.removeEventListener("touchmove", checkTarget); 498 target.removeEventListener("touchend", checkTarget); 499 500 is(touchEvents, 2, "Check target was called twice"); 501 502 nextTest(); 503 } 504 505 function testNAC() { 506 let cwu = SpecialPowers.getDOMWindowUtils(window); 507 let target = document.getElementById("testTarget3"); 508 let bcr = target.getBoundingClientRect(); 509 510 let touch1 = new testtouch({ 511 page: {x: Math.round(bcr.left + bcr.width/2), 512 y: Math.round(bcr.top + bcr.height/2)}, 513 target 514 }); 515 let event = new touchEvent({ 516 touches: [touch1], 517 targetTouches: [touch1], 518 changedTouches: [touch1] 519 }); 520 521 // test touchstart event fires correctly 522 var checkFunction = checkEvent(event); 523 window.addEventListener("touchstart", checkFunction); 524 sendTouchEvent(cwu, "touchstart", event, 0); 525 window.removeEventListener("touchstart", checkFunction); 526 527 sendTouchEvent(cwu, "touchend", event, 0); 528 529 nextTest(); 530 } 531 532 function doTest() { 533 tests.push(testSingleTouch); 534 tests.push(testSingleTouch2); 535 tests.push(testMultiTouch); 536 tests.push(testPreventDefault); 537 tests.push(testTouchChanged); 538 tests.push(testRemovingElement); 539 tests.push(testNAC); 540 541 tests.push(function() { 542 SimpleTest.finish(); 543 }); 544 545 nextTest(); 546 } 547 548 SimpleTest.waitForExplicitFinish(); 549 addLoadEvent(doTest); 550 551 </script> 552 </pre> 553 <div id="parent"> 554 <span id="testTarget" style="padding: 5px; border: 1px solid black;">testTarget</span> 555 <span id="testTarget2" style="padding: 5px; border: 1px solid blue;">testTarget</span> 556 <input type="text" id="testTarget3"> 557 </div> 558 </body> 559 </html>