test_bug603008.html 18 KB

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