test.gesturehandler.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. const expect = chai.expect;
  2. import EventTargetMixin from '../core/util/eventtarget.js';
  3. import GestureHandler from '../core/input/gesturehandler.js';
  4. class DummyTarget extends EventTargetMixin {
  5. }
  6. describe('Gesture handler', function () {
  7. let target, handler;
  8. let gestures;
  9. let clock;
  10. let touches;
  11. before(function () {
  12. clock = sinon.useFakeTimers();
  13. });
  14. after(function () {
  15. clock.restore();
  16. });
  17. beforeEach(function () {
  18. target = new DummyTarget();
  19. gestures = sinon.spy();
  20. target.addEventListener('gesturestart', gestures);
  21. target.addEventListener('gesturemove', gestures);
  22. target.addEventListener('gestureend', gestures);
  23. touches = [];
  24. handler = new GestureHandler();
  25. handler.attach(target);
  26. });
  27. afterEach(function () {
  28. if (handler) {
  29. handler.detach();
  30. }
  31. target = null;
  32. gestures = null;
  33. });
  34. function touchStart(id, x, y) {
  35. let touch = { identifier: id,
  36. clientX: x, clientY: y };
  37. touches.push(touch);
  38. let ev = { type: 'touchstart',
  39. touches: touches,
  40. targetTouches: touches,
  41. changedTouches: [ touch ],
  42. stopPropagation: sinon.spy(),
  43. preventDefault: sinon.spy() };
  44. target.dispatchEvent(ev);
  45. }
  46. function touchMove(id, x, y) {
  47. let touch = touches.find(t => t.identifier === id);
  48. touch.clientX = x;
  49. touch.clientY = y;
  50. let ev = { type: 'touchmove',
  51. touches: touches,
  52. targetTouches: touches,
  53. changedTouches: [ touch ],
  54. stopPropagation: sinon.spy(),
  55. preventDefault: sinon.spy() };
  56. target.dispatchEvent(ev);
  57. }
  58. function touchEnd(id) {
  59. let idx = touches.findIndex(t => t.identifier === id);
  60. let touch = touches.splice(idx, 1)[0];
  61. let ev = { type: 'touchend',
  62. touches: touches,
  63. targetTouches: touches,
  64. changedTouches: [ touch ],
  65. stopPropagation: sinon.spy(),
  66. preventDefault: sinon.spy() };
  67. target.dispatchEvent(ev);
  68. }
  69. describe('Single finger tap', function () {
  70. it('should handle single finger tap', function () {
  71. touchStart(1, 20.0, 30.0);
  72. expect(gestures).to.not.have.been.called;
  73. touchEnd(1);
  74. expect(gestures).to.have.been.calledTwice;
  75. expect(gestures.firstCall).to.have.been.calledWith(
  76. sinon.match({ type: 'gesturestart',
  77. detail: { type: 'onetap',
  78. clientX: 20.0,
  79. clientY: 30.0 } }));
  80. expect(gestures.secondCall).to.have.been.calledWith(
  81. sinon.match({ type: 'gestureend',
  82. detail: { type: 'onetap',
  83. clientX: 20.0,
  84. clientY: 30.0 } }));
  85. });
  86. });
  87. describe('Two finger tap', function () {
  88. it('should handle two finger tap', function () {
  89. touchStart(1, 20.0, 30.0);
  90. touchStart(2, 30.0, 50.0);
  91. expect(gestures).to.not.have.been.called;
  92. touchEnd(1);
  93. expect(gestures).to.not.have.been.called;
  94. touchEnd(2);
  95. expect(gestures).to.have.been.calledTwice;
  96. expect(gestures.firstCall).to.have.been.calledWith(
  97. sinon.match({ type: 'gesturestart',
  98. detail: { type: 'twotap',
  99. clientX: 25.0,
  100. clientY: 40.0 } }));
  101. expect(gestures.secondCall).to.have.been.calledWith(
  102. sinon.match({ type: 'gestureend',
  103. detail: { type: 'twotap',
  104. clientX: 25.0,
  105. clientY: 40.0 } }));
  106. });
  107. it('should ignore slow starting two finger tap', function () {
  108. touchStart(1, 20.0, 30.0);
  109. clock.tick(500);
  110. touchStart(2, 30.0, 50.0);
  111. touchEnd(1);
  112. touchEnd(2);
  113. expect(gestures).to.not.have.been.called;
  114. });
  115. it('should ignore slow ending two finger tap', function () {
  116. touchStart(1, 20.0, 30.0);
  117. touchStart(2, 30.0, 50.0);
  118. touchEnd(1);
  119. clock.tick(500);
  120. touchEnd(2);
  121. expect(gestures).to.not.have.been.called;
  122. });
  123. it('should ignore slow two finger tap', function () {
  124. touchStart(1, 20.0, 30.0);
  125. touchStart(2, 30.0, 50.0);
  126. clock.tick(1500);
  127. touchEnd(1);
  128. touchEnd(2);
  129. expect(gestures).to.not.have.been.called;
  130. });
  131. });
  132. describe('Three finger tap', function () {
  133. it('should handle three finger tap', function () {
  134. touchStart(1, 20.0, 30.0);
  135. touchStart(2, 30.0, 50.0);
  136. touchStart(3, 40.0, 40.0);
  137. expect(gestures).to.not.have.been.called;
  138. touchEnd(1);
  139. expect(gestures).to.not.have.been.called;
  140. touchEnd(2);
  141. expect(gestures).to.not.have.been.called;
  142. touchEnd(3);
  143. expect(gestures).to.have.been.calledTwice;
  144. expect(gestures.firstCall).to.have.been.calledWith(
  145. sinon.match({ type: 'gesturestart',
  146. detail: { type: 'threetap',
  147. clientX: 30.0,
  148. clientY: 40.0 } }));
  149. expect(gestures.secondCall).to.have.been.calledWith(
  150. sinon.match({ type: 'gestureend',
  151. detail: { type: 'threetap',
  152. clientX: 30.0,
  153. clientY: 40.0 } }));
  154. });
  155. it('should ignore slow starting three finger tap', function () {
  156. touchStart(1, 20.0, 30.0);
  157. touchStart(2, 30.0, 50.0);
  158. clock.tick(500);
  159. touchStart(3, 40.0, 40.0);
  160. touchEnd(1);
  161. touchEnd(2);
  162. touchEnd(3);
  163. expect(gestures).to.not.have.been.called;
  164. });
  165. it('should ignore slow ending three finger tap', function () {
  166. touchStart(1, 20.0, 30.0);
  167. touchStart(2, 30.0, 50.0);
  168. touchStart(3, 40.0, 40.0);
  169. touchEnd(1);
  170. touchEnd(2);
  171. clock.tick(500);
  172. touchEnd(3);
  173. expect(gestures).to.not.have.been.called;
  174. });
  175. it('should ignore three finger drag', function () {
  176. touchStart(1, 20.0, 30.0);
  177. touchStart(2, 30.0, 50.0);
  178. touchStart(3, 40.0, 40.0);
  179. touchMove(1, 120.0, 130.0);
  180. touchMove(2, 130.0, 150.0);
  181. touchMove(3, 140.0, 140.0);
  182. touchEnd(1);
  183. touchEnd(2);
  184. touchEnd(3);
  185. expect(gestures).to.not.have.been.called;
  186. });
  187. it('should ignore slow three finger tap', function () {
  188. touchStart(1, 20.0, 30.0);
  189. touchStart(2, 30.0, 50.0);
  190. touchStart(3, 40.0, 40.0);
  191. clock.tick(1500);
  192. touchEnd(1);
  193. touchEnd(2);
  194. touchEnd(3);
  195. expect(gestures).to.not.have.been.called;
  196. });
  197. });
  198. describe('Single finger drag', function () {
  199. it('should handle horizontal single finger drag', function () {
  200. touchStart(1, 20.0, 30.0);
  201. expect(gestures).to.not.have.been.called;
  202. touchMove(1, 40.0, 30.0);
  203. expect(gestures).to.not.have.been.called;
  204. touchMove(1, 80.0, 30.0);
  205. expect(gestures).to.have.been.calledTwice;
  206. expect(gestures.firstCall).to.have.been.calledWith(
  207. sinon.match({ type: 'gesturestart',
  208. detail: { type: 'drag',
  209. clientX: 20.0,
  210. clientY: 30.0 } }));
  211. expect(gestures.secondCall).to.have.been.calledWith(
  212. sinon.match({ type: 'gesturemove',
  213. detail: { type: 'drag',
  214. clientX: 80.0,
  215. clientY: 30.0 } }));
  216. gestures.resetHistory();
  217. touchEnd(1);
  218. expect(gestures).to.have.been.calledOnceWith(
  219. sinon.match({ type: 'gestureend',
  220. detail: { type: 'drag',
  221. clientX: 80.0,
  222. clientY: 30.0 } }));
  223. });
  224. it('should handle vertical single finger drag', function () {
  225. touchStart(1, 20.0, 30.0);
  226. expect(gestures).to.not.have.been.called;
  227. touchMove(1, 20.0, 50.0);
  228. expect(gestures).to.not.have.been.called;
  229. touchMove(1, 20.0, 90.0);
  230. expect(gestures).to.have.been.calledTwice;
  231. expect(gestures.firstCall).to.have.been.calledWith(
  232. sinon.match({ type: 'gesturestart',
  233. detail: { type: 'drag',
  234. clientX: 20.0,
  235. clientY: 30.0 } }));
  236. expect(gestures.secondCall).to.have.been.calledWith(
  237. sinon.match({ type: 'gesturemove',
  238. detail: { type: 'drag',
  239. clientX: 20.0,
  240. clientY: 90.0 } }));
  241. gestures.resetHistory();
  242. touchEnd(1);
  243. expect(gestures).to.have.been.calledOnceWith(
  244. sinon.match({ type: 'gestureend',
  245. detail: { type: 'drag',
  246. clientX: 20.0,
  247. clientY: 90.0 } }));
  248. });
  249. it('should handle diagonal single finger drag', function () {
  250. touchStart(1, 120.0, 130.0);
  251. expect(gestures).to.not.have.been.called;
  252. touchMove(1, 90.0, 100.0);
  253. expect(gestures).to.not.have.been.called;
  254. touchMove(1, 60.0, 70.0);
  255. expect(gestures).to.have.been.calledTwice;
  256. expect(gestures.firstCall).to.have.been.calledWith(
  257. sinon.match({ type: 'gesturestart',
  258. detail: { type: 'drag',
  259. clientX: 120.0,
  260. clientY: 130.0 } }));
  261. expect(gestures.secondCall).to.have.been.calledWith(
  262. sinon.match({ type: 'gesturemove',
  263. detail: { type: 'drag',
  264. clientX: 60.0,
  265. clientY: 70.0 } }));
  266. gestures.resetHistory();
  267. touchEnd(1);
  268. expect(gestures).to.have.been.calledOnceWith(
  269. sinon.match({ type: 'gestureend',
  270. detail: { type: 'drag',
  271. clientX: 60.0,
  272. clientY: 70.0 } }));
  273. });
  274. });
  275. describe('Long press', function () {
  276. it('should handle long press', function () {
  277. touchStart(1, 20.0, 30.0);
  278. expect(gestures).to.not.have.been.called;
  279. clock.tick(1500);
  280. expect(gestures).to.have.been.calledOnceWith(
  281. sinon.match({ type: 'gesturestart',
  282. detail: { type: 'longpress',
  283. clientX: 20.0,
  284. clientY: 30.0 } }));
  285. gestures.resetHistory();
  286. touchEnd(1);
  287. expect(gestures).to.have.been.calledOnceWith(
  288. sinon.match({ type: 'gestureend',
  289. detail: { type: 'longpress',
  290. clientX: 20.0,
  291. clientY: 30.0 } }));
  292. });
  293. it('should handle long press drag', function () {
  294. touchStart(1, 20.0, 30.0);
  295. expect(gestures).to.not.have.been.called;
  296. clock.tick(1500);
  297. expect(gestures).to.have.been.calledOnceWith(
  298. sinon.match({ type: 'gesturestart',
  299. detail: { type: 'longpress',
  300. clientX: 20.0,
  301. clientY: 30.0 } }));
  302. gestures.resetHistory();
  303. touchMove(1, 120.0, 50.0);
  304. expect(gestures).to.have.been.calledOnceWith(
  305. sinon.match({ type: 'gesturemove',
  306. detail: { type: 'longpress',
  307. clientX: 120.0,
  308. clientY: 50.0 } }));
  309. gestures.resetHistory();
  310. touchEnd(1);
  311. expect(gestures).to.have.been.calledOnceWith(
  312. sinon.match({ type: 'gestureend',
  313. detail: { type: 'longpress',
  314. clientX: 120.0,
  315. clientY: 50.0 } }));
  316. });
  317. });
  318. describe('Two finger drag', function () {
  319. it('should handle fast and distinct horizontal two finger drag', function () {
  320. touchStart(1, 20.0, 30.0);
  321. touchStart(2, 30.0, 30.0);
  322. expect(gestures).to.not.have.been.called;
  323. touchMove(1, 40.0, 30.0);
  324. touchMove(2, 50.0, 30.0);
  325. expect(gestures).to.not.have.been.called;
  326. touchMove(2, 90.0, 30.0);
  327. touchMove(1, 80.0, 30.0);
  328. expect(gestures).to.have.been.calledTwice;
  329. expect(gestures.firstCall).to.have.been.calledWith(
  330. sinon.match({ type: 'gesturestart',
  331. detail: { type: 'twodrag',
  332. clientX: 25.0,
  333. clientY: 30.0,
  334. magnitudeX: 0.0,
  335. magnitudeY: 0.0 } }));
  336. expect(gestures.secondCall).to.have.been.calledWith(
  337. sinon.match({ type: 'gesturemove',
  338. detail: { type: 'twodrag',
  339. clientX: 25.0,
  340. clientY: 30.0,
  341. magnitudeX: 60.0,
  342. magnitudeY: 0.0 } }));
  343. gestures.resetHistory();
  344. touchEnd(1);
  345. expect(gestures).to.have.been.calledOnceWith(
  346. sinon.match({ type: 'gestureend',
  347. detail: { type: 'twodrag',
  348. clientX: 25.0,
  349. clientY: 30.0,
  350. magnitudeX: 60.0,
  351. magnitudeY: 0.0 } }));
  352. });
  353. it('should handle fast and distinct vertical two finger drag', function () {
  354. touchStart(1, 20.0, 30.0);
  355. touchStart(2, 30.0, 30.0);
  356. expect(gestures).to.not.have.been.called;
  357. touchMove(1, 20.0, 100.0);
  358. touchMove(2, 30.0, 40.0);
  359. expect(gestures).to.not.have.been.called;
  360. touchMove(2, 30.0, 90.0);
  361. expect(gestures).to.have.been.calledTwice;
  362. expect(gestures.firstCall).to.have.been.calledWith(
  363. sinon.match({ type: 'gesturestart',
  364. detail: { type: 'twodrag',
  365. clientX: 25.0,
  366. clientY: 30.0,
  367. magnitudeX: 0.0,
  368. magnitudeY: 0.0 } }));
  369. expect(gestures.secondCall).to.have.been.calledWith(
  370. sinon.match({ type: 'gesturemove',
  371. detail: { type: 'twodrag',
  372. clientX: 25.0,
  373. clientY: 30.0,
  374. magnitudeX: 0.0,
  375. magnitudeY: 65.0 } }));
  376. gestures.resetHistory();
  377. touchEnd(1);
  378. expect(gestures).to.have.been.calledOnceWith(
  379. sinon.match({ type: 'gestureend',
  380. detail: { type: 'twodrag',
  381. clientX: 25.0,
  382. clientY: 30.0,
  383. magnitudeX: 0.0,
  384. magnitudeY: 65.0 } }));
  385. });
  386. it('should handle fast and distinct diagonal two finger drag', function () {
  387. touchStart(1, 120.0, 130.0);
  388. touchStart(2, 130.0, 130.0);
  389. expect(gestures).to.not.have.been.called;
  390. touchMove(1, 80.0, 90.0);
  391. touchMove(2, 100.0, 130.0);
  392. expect(gestures).to.not.have.been.called;
  393. touchMove(2, 60.0, 70.0);
  394. expect(gestures).to.have.been.calledTwice;
  395. expect(gestures.firstCall).to.have.been.calledWith(
  396. sinon.match({ type: 'gesturestart',
  397. detail: { type: 'twodrag',
  398. clientX: 125.0,
  399. clientY: 130.0,
  400. magnitudeX: 0.0,
  401. magnitudeY: 0.0 } }));
  402. expect(gestures.secondCall).to.have.been.calledWith(
  403. sinon.match({ type: 'gesturemove',
  404. detail: { type: 'twodrag',
  405. clientX: 125.0,
  406. clientY: 130.0,
  407. magnitudeX: -55.0,
  408. magnitudeY: -50.0 } }));
  409. gestures.resetHistory();
  410. touchEnd(1);
  411. expect(gestures).to.have.been.calledOnceWith(
  412. sinon.match({ type: 'gestureend',
  413. detail: { type: 'twodrag',
  414. clientX: 125.0,
  415. clientY: 130.0,
  416. magnitudeX: -55.0,
  417. magnitudeY: -50.0 } }));
  418. });
  419. it('should ignore fast almost two finger dragging', function () {
  420. touchStart(1, 20.0, 30.0);
  421. touchStart(2, 30.0, 30.0);
  422. touchMove(1, 80.0, 30.0);
  423. touchMove(2, 70.0, 30.0);
  424. touchEnd(1);
  425. touchEnd(2);
  426. expect(gestures).to.not.have.been.called;
  427. clock.tick(1500);
  428. expect(gestures).to.not.have.been.called;
  429. });
  430. it('should handle slow horizontal two finger drag', function () {
  431. touchStart(1, 50.0, 40.0);
  432. touchStart(2, 60.0, 40.0);
  433. touchMove(1, 80.0, 40.0);
  434. touchMove(2, 110.0, 40.0);
  435. expect(gestures).to.not.have.been.called;
  436. clock.tick(60);
  437. expect(gestures).to.have.been.calledTwice;
  438. expect(gestures.firstCall).to.have.been.calledWith(
  439. sinon.match({ type: 'gesturestart',
  440. detail: { type: 'twodrag',
  441. clientX: 55.0,
  442. clientY: 40.0,
  443. magnitudeX: 0.0,
  444. magnitudeY: 0.0 } }));
  445. expect(gestures.secondCall).to.have.been.calledWith(
  446. sinon.match({ type: 'gesturemove',
  447. detail: { type: 'twodrag',
  448. clientX: 55.0,
  449. clientY: 40.0,
  450. magnitudeX: 40.0,
  451. magnitudeY: 0.0 } }));
  452. });
  453. it('should handle slow vertical two finger drag', function () {
  454. touchStart(1, 40.0, 40.0);
  455. touchStart(2, 40.0, 60.0);
  456. touchMove(2, 40.0, 80.0);
  457. touchMove(1, 40.0, 100.0);
  458. expect(gestures).to.not.have.been.called;
  459. clock.tick(60);
  460. expect(gestures).to.have.been.calledTwice;
  461. expect(gestures.firstCall).to.have.been.calledWith(
  462. sinon.match({ type: 'gesturestart',
  463. detail: { type: 'twodrag',
  464. clientX: 40.0,
  465. clientY: 50.0,
  466. magnitudeX: 0.0,
  467. magnitudeY: 0.0 } }));
  468. expect(gestures.secondCall).to.have.been.calledWith(
  469. sinon.match({ type: 'gesturemove',
  470. detail: { type: 'twodrag',
  471. clientX: 40.0,
  472. clientY: 50.0,
  473. magnitudeX: 0.0,
  474. magnitudeY: 40.0 } }));
  475. });
  476. it('should handle slow diagonal two finger drag', function () {
  477. touchStart(1, 50.0, 40.0);
  478. touchStart(2, 40.0, 60.0);
  479. touchMove(1, 70.0, 60.0);
  480. touchMove(2, 90.0, 110.0);
  481. expect(gestures).to.not.have.been.called;
  482. clock.tick(60);
  483. expect(gestures).to.have.been.calledTwice;
  484. expect(gestures.firstCall).to.have.been.calledWith(
  485. sinon.match({ type: 'gesturestart',
  486. detail: { type: 'twodrag',
  487. clientX: 45.0,
  488. clientY: 50.0,
  489. magnitudeX: 0.0,
  490. magnitudeY: 0.0 } }));
  491. expect(gestures.secondCall).to.have.been.calledWith(
  492. sinon.match({ type: 'gesturemove',
  493. detail: { type: 'twodrag',
  494. clientX: 45.0,
  495. clientY: 50.0,
  496. magnitudeX: 35.0,
  497. magnitudeY: 35.0 } }));
  498. });
  499. it('should ignore too slow two finger drag', function () {
  500. touchStart(1, 20.0, 30.0);
  501. clock.tick(500);
  502. touchStart(2, 30.0, 30.0);
  503. touchMove(1, 40.0, 30.0);
  504. touchMove(2, 50.0, 30.0);
  505. touchMove(1, 80.0, 30.0);
  506. expect(gestures).to.not.have.been.called;
  507. });
  508. });
  509. describe('Pinch', function () {
  510. it('should handle pinching distinctly and fast inwards', function () {
  511. touchStart(1, 0.0, 0.0);
  512. touchStart(2, 130.0, 130.0);
  513. expect(gestures).to.not.have.been.called;
  514. touchMove(1, 50.0, 40.0);
  515. touchMove(2, 100.0, 130.0);
  516. expect(gestures).to.not.have.been.called;
  517. touchMove(2, 60.0, 70.0);
  518. expect(gestures).to.have.been.calledTwice;
  519. expect(gestures.firstCall).to.have.been.calledWith(
  520. sinon.match({ type: 'gesturestart',
  521. detail: { type: 'pinch',
  522. clientX: 65.0,
  523. clientY: 65.0,
  524. magnitudeX: 130.0,
  525. magnitudeY: 130.0 } }));
  526. expect(gestures.secondCall).to.have.been.calledWith(
  527. sinon.match({ type: 'gesturemove',
  528. detail: { type: 'pinch',
  529. clientX: 65.0,
  530. clientY: 65.0,
  531. magnitudeX: 10.0,
  532. magnitudeY: 30.0 } }));
  533. gestures.resetHistory();
  534. touchEnd(1);
  535. expect(gestures).to.have.been.calledOnceWith(
  536. sinon.match({ type: 'gestureend',
  537. detail: { type: 'pinch',
  538. clientX: 65.0,
  539. clientY: 65.0,
  540. magnitudeX: 10.0,
  541. magnitudeY: 30.0 } }));
  542. });
  543. it('should handle pinching fast and distinctly outwards', function () {
  544. touchStart(1, 100.0, 100.0);
  545. touchStart(2, 110.0, 100.0);
  546. expect(gestures).to.not.have.been.called;
  547. touchMove(1, 130.0, 70.0);
  548. touchMove(2, 0.0, 200.0);
  549. expect(gestures).to.not.have.been.called;
  550. touchMove(1, 180.0, 20.0);
  551. expect(gestures).to.have.been.calledTwice;
  552. expect(gestures.firstCall).to.have.been.calledWith(
  553. sinon.match({ type: 'gesturestart',
  554. detail: { type: 'pinch',
  555. clientX: 105.0,
  556. clientY: 100.0,
  557. magnitudeX: 10.0,
  558. magnitudeY: 0.0 } }));
  559. expect(gestures.secondCall).to.have.been.calledWith(
  560. sinon.match({ type: 'gesturemove',
  561. detail: { type: 'pinch',
  562. clientX: 105.0,
  563. clientY: 100.0,
  564. magnitudeX: 180.0,
  565. magnitudeY: 180.0 } }));
  566. gestures.resetHistory();
  567. touchEnd(1);
  568. expect(gestures).to.have.been.calledOnceWith(
  569. sinon.match({ type: 'gestureend',
  570. detail: { type: 'pinch',
  571. clientX: 105.0,
  572. clientY: 100.0,
  573. magnitudeX: 180.0,
  574. magnitudeY: 180.0 } }));
  575. });
  576. it('should ignore fast almost pinching', function () {
  577. touchStart(1, 20.0, 30.0);
  578. touchStart(2, 130.0, 130.0);
  579. touchMove(1, 80.0, 70.0);
  580. touchEnd(1);
  581. touchEnd(2);
  582. expect(gestures).to.not.have.been.called;
  583. clock.tick(1500);
  584. expect(gestures).to.not.have.been.called;
  585. });
  586. it('should handle pinching inwards slowly', function () {
  587. touchStart(1, 0.0, 0.0);
  588. touchStart(2, 130.0, 130.0);
  589. touchMove(1, 50.0, 40.0);
  590. touchMove(2, 100.0, 130.0);
  591. expect(gestures).to.not.have.been.called;
  592. clock.tick(60);
  593. expect(gestures).to.have.been.calledTwice;
  594. expect(gestures.firstCall).to.have.been.calledWith(
  595. sinon.match({ type: 'gesturestart',
  596. detail: { type: 'pinch',
  597. clientX: 65.0,
  598. clientY: 65.0,
  599. magnitudeX: 130.0,
  600. magnitudeY: 130.0 } }));
  601. expect(gestures.secondCall).to.have.been.calledWith(
  602. sinon.match({ type: 'gesturemove',
  603. detail: { type: 'pinch',
  604. clientX: 65.0,
  605. clientY: 65.0,
  606. magnitudeX: 50.0,
  607. magnitudeY: 90.0 } }));
  608. });
  609. it('should handle pinching outwards slowly', function () {
  610. touchStart(1, 100.0, 130.0);
  611. touchStart(2, 110.0, 130.0);
  612. touchMove(2, 200.0, 130.0);
  613. expect(gestures).to.not.have.been.called;
  614. clock.tick(60);
  615. expect(gestures).to.have.been.calledTwice;
  616. expect(gestures.firstCall).to.have.been.calledWith(
  617. sinon.match({ type: 'gesturestart',
  618. detail: { type: 'pinch',
  619. clientX: 105.0,
  620. clientY: 130.0,
  621. magnitudeX: 10.0,
  622. magnitudeY: 0.0 } }));
  623. expect(gestures.secondCall).to.have.been.calledWith(
  624. sinon.match({ type: 'gesturemove',
  625. detail: { type: 'pinch',
  626. clientX: 105.0,
  627. clientY: 130.0,
  628. magnitudeX: 100.0,
  629. magnitudeY: 0.0 } }));
  630. });
  631. it('should ignore pinching too slowly', function () {
  632. touchStart(1, 0.0, 0.0);
  633. clock.tick(500);
  634. touchStart(2, 130.0, 130.0);
  635. touchMove(2, 100.0, 130.0);
  636. touchMove(1, 50.0, 40.0);
  637. expect(gestures).to.not.have.been.called;
  638. });
  639. });
  640. describe('Ignoring', function () {
  641. it('should ignore extra touches during gesture', function () {
  642. touchStart(1, 20.0, 30.0);
  643. touchMove(1, 40.0, 30.0);
  644. touchMove(1, 80.0, 30.0);
  645. expect(gestures).to.have.been.calledTwice;
  646. expect(gestures.firstCall).to.have.been.calledWith(
  647. sinon.match({ type: 'gesturestart',
  648. detail: { type: 'drag' } }));
  649. expect(gestures.secondCall).to.have.been.calledWith(
  650. sinon.match({ type: 'gesturemove',
  651. detail: { type: 'drag' } }));
  652. gestures.resetHistory();
  653. touchStart(2, 10.0, 10.0);
  654. expect(gestures).to.not.have.been.called;
  655. touchMove(1, 100.0, 50.0);
  656. expect(gestures).to.have.been.calledOnceWith(
  657. sinon.match({ type: 'gesturemove',
  658. detail: { type: 'drag',
  659. clientX: 100.0,
  660. clientY: 50.0 } }));
  661. gestures.resetHistory();
  662. touchEnd(1);
  663. expect(gestures).to.have.been.calledOnceWith(
  664. sinon.match({ type: 'gestureend',
  665. detail: { type: 'drag',
  666. clientX: 100.0,
  667. clientY: 50.0 } }));
  668. });
  669. it('should ignore extra touches when waiting for gesture to end', function () {
  670. touchStart(1, 20.0, 30.0);
  671. touchStart(2, 30.0, 30.0);
  672. touchMove(1, 40.0, 30.0);
  673. touchMove(2, 90.0, 30.0);
  674. touchMove(1, 80.0, 30.0);
  675. expect(gestures).to.have.been.calledTwice;
  676. expect(gestures.firstCall).to.have.been.calledWith(
  677. sinon.match({ type: 'gesturestart',
  678. detail: { type: 'twodrag' } }));
  679. expect(gestures.secondCall).to.have.been.calledWith(
  680. sinon.match({ type: 'gesturemove',
  681. detail: { type: 'twodrag' } }));
  682. gestures.resetHistory();
  683. touchEnd(1);
  684. expect(gestures).to.have.been.calledOnceWith(
  685. sinon.match({ type: 'gestureend',
  686. detail: { type: 'twodrag' } }));
  687. gestures.resetHistory();
  688. touchStart(3, 10.0, 10.0);
  689. touchEnd(3);
  690. expect(gestures).to.not.have.been.called;
  691. });
  692. it('should ignore extra touches after gesture', function () {
  693. touchStart(1, 20.0, 30.0);
  694. touchMove(1, 40.0, 30.0);
  695. touchMove(1, 80.0, 30.0);
  696. expect(gestures).to.have.been.calledTwice;
  697. expect(gestures.firstCall).to.have.been.calledWith(
  698. sinon.match({ type: 'gesturestart',
  699. detail: { type: 'drag' } }));
  700. expect(gestures.secondCall).to.have.been.calledWith(
  701. sinon.match({ type: 'gesturemove',
  702. detail: { type: 'drag' } }));
  703. gestures.resetHistory();
  704. touchStart(2, 10.0, 10.0);
  705. expect(gestures).to.not.have.been.called;
  706. touchMove(1, 100.0, 50.0);
  707. expect(gestures).to.have.been.calledOnceWith(
  708. sinon.match({ type: 'gesturemove',
  709. detail: { type: 'drag' } }));
  710. gestures.resetHistory();
  711. touchEnd(1);
  712. expect(gestures).to.have.been.calledOnceWith(
  713. sinon.match({ type: 'gestureend',
  714. detail: { type: 'drag' } }));
  715. gestures.resetHistory();
  716. touchEnd(2);
  717. expect(gestures).to.not.have.been.called;
  718. // Check that everything is reseted after trailing ignores are released
  719. touchStart(3, 20.0, 30.0);
  720. touchEnd(3);
  721. expect(gestures).to.have.been.calledTwice;
  722. expect(gestures.firstCall).to.have.been.calledWith(
  723. sinon.match({ type: 'gesturestart',
  724. detail: { type: 'onetap' } }));
  725. expect(gestures.secondCall).to.have.been.calledWith(
  726. sinon.match({ type: 'gestureend',
  727. detail: { type: 'onetap' } }));
  728. });
  729. it('should properly reset after a gesture', function () {
  730. touchStart(1, 20.0, 30.0);
  731. expect(gestures).to.not.have.been.called;
  732. touchEnd(1);
  733. expect(gestures).to.have.been.calledTwice;
  734. expect(gestures.firstCall).to.have.been.calledWith(
  735. sinon.match({ type: 'gesturestart',
  736. detail: { type: 'onetap',
  737. clientX: 20.0,
  738. clientY: 30.0 } }));
  739. expect(gestures.secondCall).to.have.been.calledWith(
  740. sinon.match({ type: 'gestureend',
  741. detail: { type: 'onetap',
  742. clientX: 20.0,
  743. clientY: 30.0 } }));
  744. gestures.resetHistory();
  745. touchStart(2, 70.0, 80.0);
  746. expect(gestures).to.not.have.been.called;
  747. touchEnd(2);
  748. expect(gestures).to.have.been.calledTwice;
  749. expect(gestures.firstCall).to.have.been.calledWith(
  750. sinon.match({ type: 'gesturestart',
  751. detail: { type: 'onetap',
  752. clientX: 70.0,
  753. clientY: 80.0 } }));
  754. expect(gestures.secondCall).to.have.been.calledWith(
  755. sinon.match({ type: 'gestureend',
  756. detail: { type: 'onetap',
  757. clientX: 70.0,
  758. clientY: 80.0 } }));
  759. });
  760. });
  761. });