]>
Commit | Line | Data |
---|---|---|
8be924c9 PO |
1 | const expect = chai.expect; |
2 | ||
3 | import EventTargetMixin from '../core/util/eventtarget.js'; | |
4 | ||
5 | import GestureHandler from '../core/input/gesturehandler.js'; | |
6 | import * as browser from '../core/util/browser.js'; | |
7 | ||
8 | class DummyTarget extends EventTargetMixin { | |
9 | } | |
10 | ||
11 | describe('Gesture handler', function () { | |
12 | let target, handler; | |
13 | let gestures; | |
14 | let clock; | |
15 | let touches; | |
16 | ||
17 | before(function () { | |
18 | clock = sinon.useFakeTimers(); | |
19 | }); | |
20 | ||
21 | after(function () { | |
22 | clock.restore(); | |
23 | }); | |
24 | ||
25 | beforeEach(function () { | |
26 | // Touch events and gestures are not supported on IE | |
27 | if (browser.isIE()) { | |
28 | this.skip(); | |
29 | return; | |
30 | } | |
31 | ||
32 | target = new DummyTarget(); | |
33 | gestures = sinon.spy(); | |
34 | target.addEventListener('gesturestart', gestures); | |
35 | target.addEventListener('gesturemove', gestures); | |
36 | target.addEventListener('gestureend', gestures); | |
37 | touches = []; | |
38 | handler = new GestureHandler(); | |
39 | handler.attach(target); | |
40 | }); | |
41 | ||
42 | afterEach(function () { | |
43 | handler.detach(); | |
44 | target = null; | |
45 | gestures = null; | |
46 | }); | |
47 | ||
48 | function touchStart(id, x, y) { | |
49 | let touch = { identifier: id, | |
50 | clientX: x, clientY: y }; | |
51 | touches.push(touch); | |
52 | let ev = { type: 'touchstart', | |
53 | touches: touches, | |
54 | targetTouches: touches, | |
55 | changedTouches: [ touch ], | |
56 | stopPropagation: sinon.spy(), | |
57 | preventDefault: sinon.spy() }; | |
58 | target.dispatchEvent(ev); | |
59 | } | |
60 | ||
61 | function touchMove(id, x, y) { | |
62 | let touch = touches.find(t => t.identifier === id); | |
63 | touch.clientX = x; | |
64 | touch.clientY = y; | |
65 | let ev = { type: 'touchmove', | |
66 | touches: touches, | |
67 | targetTouches: touches, | |
68 | changedTouches: [ touch ], | |
69 | stopPropagation: sinon.spy(), | |
70 | preventDefault: sinon.spy() }; | |
71 | target.dispatchEvent(ev); | |
72 | } | |
73 | ||
74 | function touchEnd(id) { | |
75 | let idx = touches.findIndex(t => t.identifier === id); | |
76 | let touch = touches.splice(idx, 1)[0]; | |
77 | let ev = { type: 'touchend', | |
78 | touches: touches, | |
79 | targetTouches: touches, | |
80 | changedTouches: [ touch ], | |
81 | stopPropagation: sinon.spy(), | |
82 | preventDefault: sinon.spy() }; | |
83 | target.dispatchEvent(ev); | |
84 | } | |
85 | ||
86 | describe('Single finger tap', function () { | |
87 | it('should handle single finger tap', function () { | |
88 | touchStart(1, 20.0, 30.0); | |
89 | ||
90 | expect(gestures).to.not.have.been.called; | |
91 | ||
92 | touchEnd(1); | |
93 | ||
94 | expect(gestures).to.have.been.calledTwice; | |
95 | ||
96 | expect(gestures.firstCall).to.have.been.calledWith( | |
97 | sinon.match({ type: 'gesturestart', | |
98 | detail: { type: 'onetap', | |
99 | clientX: 20.0, | |
100 | clientY: 30.0 } })); | |
101 | ||
102 | expect(gestures.secondCall).to.have.been.calledWith( | |
103 | sinon.match({ type: 'gestureend', | |
104 | detail: { type: 'onetap', | |
105 | clientX: 20.0, | |
106 | clientY: 30.0 } })); | |
107 | }); | |
108 | }); | |
109 | ||
110 | describe('Two finger tap', function () { | |
111 | it('should handle two finger tap', function () { | |
112 | touchStart(1, 20.0, 30.0); | |
113 | touchStart(2, 30.0, 50.0); | |
114 | ||
115 | expect(gestures).to.not.have.been.called; | |
116 | ||
117 | touchEnd(1); | |
118 | ||
119 | expect(gestures).to.not.have.been.called; | |
120 | ||
121 | touchEnd(2); | |
122 | ||
123 | expect(gestures).to.have.been.calledTwice; | |
124 | ||
125 | expect(gestures.firstCall).to.have.been.calledWith( | |
126 | sinon.match({ type: 'gesturestart', | |
127 | detail: { type: 'twotap', | |
128 | clientX: 25.0, | |
129 | clientY: 40.0 } })); | |
130 | ||
131 | expect(gestures.secondCall).to.have.been.calledWith( | |
132 | sinon.match({ type: 'gestureend', | |
133 | detail: { type: 'twotap', | |
134 | clientX: 25.0, | |
135 | clientY: 40.0 } })); | |
136 | }); | |
137 | ||
138 | it('should ignore slow starting two finger tap', function () { | |
139 | touchStart(1, 20.0, 30.0); | |
140 | ||
141 | clock.tick(500); | |
142 | ||
143 | touchStart(2, 30.0, 50.0); | |
144 | touchEnd(1); | |
145 | touchEnd(2); | |
146 | ||
147 | expect(gestures).to.not.have.been.called; | |
148 | }); | |
149 | ||
150 | it('should ignore slow ending two finger tap', function () { | |
151 | touchStart(1, 20.0, 30.0); | |
152 | touchStart(2, 30.0, 50.0); | |
153 | touchEnd(1); | |
154 | ||
155 | clock.tick(500); | |
156 | ||
157 | touchEnd(2); | |
158 | ||
159 | expect(gestures).to.not.have.been.called; | |
160 | }); | |
161 | ||
162 | it('should ignore slow two finger tap', function () { | |
163 | touchStart(1, 20.0, 30.0); | |
164 | touchStart(2, 30.0, 50.0); | |
165 | ||
166 | clock.tick(1500); | |
167 | ||
168 | touchEnd(1); | |
169 | touchEnd(2); | |
170 | ||
171 | expect(gestures).to.not.have.been.called; | |
172 | }); | |
173 | }); | |
174 | ||
175 | describe('Three finger tap', function () { | |
176 | it('should handle three finger tap', function () { | |
177 | touchStart(1, 20.0, 30.0); | |
178 | touchStart(2, 30.0, 50.0); | |
179 | touchStart(3, 40.0, 40.0); | |
180 | ||
181 | expect(gestures).to.not.have.been.called; | |
182 | ||
183 | touchEnd(1); | |
184 | ||
185 | expect(gestures).to.not.have.been.called; | |
186 | ||
187 | touchEnd(2); | |
188 | ||
189 | expect(gestures).to.not.have.been.called; | |
190 | ||
191 | touchEnd(3); | |
192 | ||
193 | expect(gestures).to.have.been.calledTwice; | |
194 | ||
195 | expect(gestures.firstCall).to.have.been.calledWith( | |
196 | sinon.match({ type: 'gesturestart', | |
197 | detail: { type: 'threetap', | |
198 | clientX: 30.0, | |
199 | clientY: 40.0 } })); | |
200 | ||
201 | expect(gestures.secondCall).to.have.been.calledWith( | |
202 | sinon.match({ type: 'gestureend', | |
203 | detail: { type: 'threetap', | |
204 | clientX: 30.0, | |
205 | clientY: 40.0 } })); | |
206 | }); | |
207 | ||
208 | it('should ignore slow starting three finger tap', function () { | |
209 | touchStart(1, 20.0, 30.0); | |
210 | touchStart(2, 30.0, 50.0); | |
211 | ||
212 | clock.tick(500); | |
213 | ||
214 | touchStart(3, 40.0, 40.0); | |
215 | touchEnd(1); | |
216 | touchEnd(2); | |
217 | touchEnd(3); | |
218 | ||
219 | expect(gestures).to.not.have.been.called; | |
220 | }); | |
221 | ||
222 | it('should ignore slow ending three finger tap', function () { | |
223 | touchStart(1, 20.0, 30.0); | |
224 | touchStart(2, 30.0, 50.0); | |
225 | touchStart(3, 40.0, 40.0); | |
226 | touchEnd(1); | |
227 | touchEnd(2); | |
228 | ||
229 | clock.tick(500); | |
230 | ||
231 | touchEnd(3); | |
232 | ||
233 | expect(gestures).to.not.have.been.called; | |
234 | }); | |
235 | ||
236 | it('should ignore three finger drag', function () { | |
237 | touchStart(1, 20.0, 30.0); | |
238 | touchStart(2, 30.0, 50.0); | |
239 | touchStart(3, 40.0, 40.0); | |
240 | ||
241 | touchMove(1, 120.0, 130.0); | |
242 | touchMove(2, 130.0, 150.0); | |
243 | touchMove(3, 140.0, 140.0); | |
244 | ||
245 | touchEnd(1); | |
246 | touchEnd(2); | |
247 | touchEnd(3); | |
248 | ||
249 | expect(gestures).to.not.have.been.called; | |
250 | }); | |
251 | ||
252 | it('should ignore slow three finger tap', function () { | |
253 | touchStart(1, 20.0, 30.0); | |
254 | touchStart(2, 30.0, 50.0); | |
255 | touchStart(3, 40.0, 40.0); | |
256 | ||
257 | clock.tick(1500); | |
258 | ||
259 | touchEnd(1); | |
260 | touchEnd(2); | |
261 | touchEnd(3); | |
262 | ||
263 | expect(gestures).to.not.have.been.called; | |
264 | }); | |
265 | }); | |
266 | ||
267 | describe('Single finger drag', function () { | |
268 | it('should handle horizontal single finger drag', function () { | |
269 | touchStart(1, 20.0, 30.0); | |
270 | ||
271 | expect(gestures).to.not.have.been.called; | |
272 | ||
273 | touchMove(1, 40.0, 30.0); | |
274 | ||
275 | expect(gestures).to.not.have.been.called; | |
276 | ||
277 | touchMove(1, 80.0, 30.0); | |
278 | ||
279 | expect(gestures).to.have.been.calledTwice; | |
280 | ||
281 | expect(gestures.firstCall).to.have.been.calledWith( | |
282 | sinon.match({ type: 'gesturestart', | |
283 | detail: { type: 'drag', | |
284 | clientX: 20.0, | |
285 | clientY: 30.0 } })); | |
286 | ||
287 | expect(gestures.secondCall).to.have.been.calledWith( | |
288 | sinon.match({ type: 'gesturemove', | |
289 | detail: { type: 'drag', | |
290 | clientX: 80.0, | |
291 | clientY: 30.0 } })); | |
292 | ||
293 | gestures.resetHistory(); | |
294 | ||
295 | touchEnd(1); | |
296 | ||
297 | expect(gestures).to.have.been.calledOnceWith( | |
298 | sinon.match({ type: 'gestureend', | |
299 | detail: { type: 'drag', | |
300 | clientX: 80.0, | |
301 | clientY: 30.0 } })); | |
302 | }); | |
303 | ||
304 | it('should handle vertical single finger drag', function () { | |
305 | touchStart(1, 20.0, 30.0); | |
306 | ||
307 | expect(gestures).to.not.have.been.called; | |
308 | ||
309 | touchMove(1, 20.0, 50.0); | |
310 | ||
311 | expect(gestures).to.not.have.been.called; | |
312 | ||
313 | touchMove(1, 20.0, 90.0); | |
314 | ||
315 | expect(gestures).to.have.been.calledTwice; | |
316 | ||
317 | expect(gestures.firstCall).to.have.been.calledWith( | |
318 | sinon.match({ type: 'gesturestart', | |
319 | detail: { type: 'drag', | |
320 | clientX: 20.0, | |
321 | clientY: 30.0 } })); | |
322 | ||
323 | expect(gestures.secondCall).to.have.been.calledWith( | |
324 | sinon.match({ type: 'gesturemove', | |
325 | detail: { type: 'drag', | |
326 | clientX: 20.0, | |
327 | clientY: 90.0 } })); | |
328 | ||
329 | gestures.resetHistory(); | |
330 | ||
331 | touchEnd(1); | |
332 | ||
333 | expect(gestures).to.have.been.calledOnceWith( | |
334 | sinon.match({ type: 'gestureend', | |
335 | detail: { type: 'drag', | |
336 | clientX: 20.0, | |
337 | clientY: 90.0 } })); | |
338 | }); | |
339 | ||
340 | it('should handle diagonal single finger drag', function () { | |
341 | touchStart(1, 120.0, 130.0); | |
342 | ||
343 | expect(gestures).to.not.have.been.called; | |
344 | ||
345 | touchMove(1, 90.0, 100.0); | |
346 | ||
347 | expect(gestures).to.not.have.been.called; | |
348 | ||
349 | touchMove(1, 60.0, 70.0); | |
350 | ||
351 | expect(gestures).to.have.been.calledTwice; | |
352 | ||
353 | expect(gestures.firstCall).to.have.been.calledWith( | |
354 | sinon.match({ type: 'gesturestart', | |
355 | detail: { type: 'drag', | |
356 | clientX: 120.0, | |
357 | clientY: 130.0 } })); | |
358 | ||
359 | expect(gestures.secondCall).to.have.been.calledWith( | |
360 | sinon.match({ type: 'gesturemove', | |
361 | detail: { type: 'drag', | |
362 | clientX: 60.0, | |
363 | clientY: 70.0 } })); | |
364 | ||
365 | gestures.resetHistory(); | |
366 | ||
367 | touchEnd(1); | |
368 | ||
369 | expect(gestures).to.have.been.calledOnceWith( | |
370 | sinon.match({ type: 'gestureend', | |
371 | detail: { type: 'drag', | |
372 | clientX: 60.0, | |
373 | clientY: 70.0 } })); | |
374 | }); | |
375 | }); | |
376 | ||
377 | describe('Long press', function () { | |
378 | it('should handle long press', function () { | |
379 | touchStart(1, 20.0, 30.0); | |
380 | ||
381 | expect(gestures).to.not.have.been.called; | |
382 | ||
383 | clock.tick(1500); | |
384 | ||
385 | expect(gestures).to.have.been.calledOnceWith( | |
386 | sinon.match({ type: 'gesturestart', | |
387 | detail: { type: 'longpress', | |
388 | clientX: 20.0, | |
389 | clientY: 30.0 } })); | |
390 | ||
391 | gestures.resetHistory(); | |
392 | ||
393 | touchEnd(1); | |
394 | ||
395 | expect(gestures).to.have.been.calledOnceWith( | |
396 | sinon.match({ type: 'gestureend', | |
397 | detail: { type: 'longpress', | |
398 | clientX: 20.0, | |
399 | clientY: 30.0 } })); | |
400 | }); | |
401 | ||
402 | it('should handle long press drag', function () { | |
403 | touchStart(1, 20.0, 30.0); | |
404 | ||
405 | expect(gestures).to.not.have.been.called; | |
406 | ||
407 | clock.tick(1500); | |
408 | ||
409 | expect(gestures).to.have.been.calledOnceWith( | |
410 | sinon.match({ type: 'gesturestart', | |
411 | detail: { type: 'longpress', | |
412 | clientX: 20.0, | |
413 | clientY: 30.0 } })); | |
414 | ||
415 | gestures.resetHistory(); | |
416 | ||
417 | touchMove(1, 120.0, 50.0); | |
418 | ||
419 | expect(gestures).to.have.been.calledOnceWith( | |
420 | sinon.match({ type: 'gesturemove', | |
421 | detail: { type: 'longpress', | |
422 | clientX: 120.0, | |
423 | clientY: 50.0 } })); | |
424 | ||
425 | gestures.resetHistory(); | |
426 | ||
427 | touchEnd(1); | |
428 | ||
429 | expect(gestures).to.have.been.calledOnceWith( | |
430 | sinon.match({ type: 'gestureend', | |
431 | detail: { type: 'longpress', | |
432 | clientX: 120.0, | |
433 | clientY: 50.0 } })); | |
434 | }); | |
435 | }); | |
436 | ||
437 | describe('Two finger drag', function () { | |
438 | it('should handle fast and distinct horizontal two finger drag', function () { | |
439 | touchStart(1, 20.0, 30.0); | |
440 | touchStart(2, 30.0, 30.0); | |
441 | ||
442 | expect(gestures).to.not.have.been.called; | |
443 | ||
444 | touchMove(1, 40.0, 30.0); | |
445 | touchMove(2, 50.0, 30.0); | |
446 | ||
447 | expect(gestures).to.not.have.been.called; | |
448 | ||
449 | touchMove(2, 90.0, 30.0); | |
450 | touchMove(1, 80.0, 30.0); | |
451 | ||
452 | expect(gestures).to.have.been.calledTwice; | |
453 | ||
454 | expect(gestures.firstCall).to.have.been.calledWith( | |
455 | sinon.match({ type: 'gesturestart', | |
456 | detail: { type: 'twodrag', | |
457 | clientX: 25.0, | |
458 | clientY: 30.0, | |
459 | magnitudeX: 0.0, | |
460 | magnitudeY: 0.0 } })); | |
461 | ||
462 | expect(gestures.secondCall).to.have.been.calledWith( | |
463 | sinon.match({ type: 'gesturemove', | |
464 | detail: { type: 'twodrag', | |
465 | clientX: 25.0, | |
466 | clientY: 30.0, | |
467 | magnitudeX: 60.0, | |
468 | magnitudeY: 0.0 } })); | |
469 | ||
470 | gestures.resetHistory(); | |
471 | ||
472 | touchEnd(1); | |
473 | ||
474 | expect(gestures).to.have.been.calledOnceWith( | |
475 | sinon.match({ type: 'gestureend', | |
476 | detail: { type: 'twodrag', | |
477 | clientX: 25.0, | |
478 | clientY: 30.0, | |
479 | magnitudeX: 60.0, | |
480 | magnitudeY: 0.0 } })); | |
481 | }); | |
482 | ||
483 | it('should handle fast and distinct vertical two finger drag', function () { | |
484 | touchStart(1, 20.0, 30.0); | |
485 | touchStart(2, 30.0, 30.0); | |
486 | ||
487 | expect(gestures).to.not.have.been.called; | |
488 | ||
489 | touchMove(1, 20.0, 100.0); | |
490 | touchMove(2, 30.0, 40.0); | |
491 | ||
492 | expect(gestures).to.not.have.been.called; | |
493 | ||
494 | touchMove(2, 30.0, 90.0); | |
495 | ||
496 | expect(gestures).to.have.been.calledTwice; | |
497 | ||
498 | expect(gestures.firstCall).to.have.been.calledWith( | |
499 | sinon.match({ type: 'gesturestart', | |
500 | detail: { type: 'twodrag', | |
501 | clientX: 25.0, | |
502 | clientY: 30.0, | |
503 | magnitudeX: 0.0, | |
504 | magnitudeY: 0.0 } })); | |
505 | ||
506 | expect(gestures.secondCall).to.have.been.calledWith( | |
507 | sinon.match({ type: 'gesturemove', | |
508 | detail: { type: 'twodrag', | |
509 | clientX: 25.0, | |
510 | clientY: 30.0, | |
511 | magnitudeX: 0.0, | |
512 | magnitudeY: 65.0 } })); | |
513 | ||
514 | gestures.resetHistory(); | |
515 | ||
516 | touchEnd(1); | |
517 | ||
518 | expect(gestures).to.have.been.calledOnceWith( | |
519 | sinon.match({ type: 'gestureend', | |
520 | detail: { type: 'twodrag', | |
521 | clientX: 25.0, | |
522 | clientY: 30.0, | |
523 | magnitudeX: 0.0, | |
524 | magnitudeY: 65.0 } })); | |
525 | }); | |
526 | ||
527 | it('should handle fast and distinct diagonal two finger drag', function () { | |
528 | touchStart(1, 120.0, 130.0); | |
529 | touchStart(2, 130.0, 130.0); | |
530 | ||
531 | expect(gestures).to.not.have.been.called; | |
532 | ||
533 | touchMove(1, 80.0, 90.0); | |
534 | touchMove(2, 100.0, 130.0); | |
535 | ||
536 | expect(gestures).to.not.have.been.called; | |
537 | ||
538 | touchMove(2, 60.0, 70.0); | |
539 | ||
540 | expect(gestures).to.have.been.calledTwice; | |
541 | ||
542 | expect(gestures.firstCall).to.have.been.calledWith( | |
543 | sinon.match({ type: 'gesturestart', | |
544 | detail: { type: 'twodrag', | |
545 | clientX: 125.0, | |
546 | clientY: 130.0, | |
547 | magnitudeX: 0.0, | |
548 | magnitudeY: 0.0 } })); | |
549 | ||
550 | expect(gestures.secondCall).to.have.been.calledWith( | |
551 | sinon.match({ type: 'gesturemove', | |
552 | detail: { type: 'twodrag', | |
553 | clientX: 125.0, | |
554 | clientY: 130.0, | |
555 | magnitudeX: -55.0, | |
556 | magnitudeY: -50.0 } })); | |
557 | ||
558 | gestures.resetHistory(); | |
559 | ||
560 | touchEnd(1); | |
561 | ||
562 | expect(gestures).to.have.been.calledOnceWith( | |
563 | sinon.match({ type: 'gestureend', | |
564 | detail: { type: 'twodrag', | |
565 | clientX: 125.0, | |
566 | clientY: 130.0, | |
567 | magnitudeX: -55.0, | |
568 | magnitudeY: -50.0 } })); | |
569 | }); | |
570 | ||
571 | it('should ignore fast almost two finger dragging', function () { | |
572 | touchStart(1, 20.0, 30.0); | |
573 | touchStart(2, 30.0, 30.0); | |
574 | touchMove(1, 80.0, 30.0); | |
575 | touchMove(2, 70.0, 30.0); | |
576 | touchEnd(1); | |
577 | touchEnd(2); | |
578 | ||
579 | expect(gestures).to.not.have.been.called; | |
580 | ||
581 | clock.tick(1500); | |
582 | ||
583 | expect(gestures).to.not.have.been.called; | |
584 | }); | |
585 | ||
586 | it('should handle slow horizontal two finger drag', function () { | |
587 | touchStart(1, 50.0, 40.0); | |
588 | touchStart(2, 60.0, 40.0); | |
589 | touchMove(1, 80.0, 40.0); | |
590 | touchMove(2, 110.0, 40.0); | |
591 | ||
592 | expect(gestures).to.not.have.been.called; | |
593 | ||
594 | clock.tick(60); | |
595 | ||
596 | expect(gestures).to.have.been.calledTwice; | |
597 | ||
598 | expect(gestures.firstCall).to.have.been.calledWith( | |
599 | sinon.match({ type: 'gesturestart', | |
600 | detail: { type: 'twodrag', | |
601 | clientX: 55.0, | |
602 | clientY: 40.0, | |
603 | magnitudeX: 0.0, | |
604 | magnitudeY: 0.0 } })); | |
605 | ||
606 | expect(gestures.secondCall).to.have.been.calledWith( | |
607 | sinon.match({ type: 'gesturemove', | |
608 | detail: { type: 'twodrag', | |
609 | clientX: 55.0, | |
610 | clientY: 40.0, | |
611 | magnitudeX: 40.0, | |
612 | magnitudeY: 0.0 } })); | |
613 | }); | |
614 | ||
615 | it('should handle slow vertical two finger drag', function () { | |
616 | touchStart(1, 40.0, 40.0); | |
617 | touchStart(2, 40.0, 60.0); | |
618 | touchMove(2, 40.0, 80.0); | |
619 | touchMove(1, 40.0, 100.0); | |
620 | ||
621 | expect(gestures).to.not.have.been.called; | |
622 | ||
623 | clock.tick(60); | |
624 | ||
625 | expect(gestures).to.have.been.calledTwice; | |
626 | ||
627 | expect(gestures.firstCall).to.have.been.calledWith( | |
628 | sinon.match({ type: 'gesturestart', | |
629 | detail: { type: 'twodrag', | |
630 | clientX: 40.0, | |
631 | clientY: 50.0, | |
632 | magnitudeX: 0.0, | |
633 | magnitudeY: 0.0 } })); | |
634 | ||
635 | expect(gestures.secondCall).to.have.been.calledWith( | |
636 | sinon.match({ type: 'gesturemove', | |
637 | detail: { type: 'twodrag', | |
638 | clientX: 40.0, | |
639 | clientY: 50.0, | |
640 | magnitudeX: 0.0, | |
641 | magnitudeY: 40.0 } })); | |
642 | }); | |
643 | ||
644 | it('should handle slow diagonal two finger drag', function () { | |
645 | touchStart(1, 50.0, 40.0); | |
646 | touchStart(2, 40.0, 60.0); | |
647 | touchMove(1, 70.0, 60.0); | |
648 | touchMove(2, 90.0, 110.0); | |
649 | ||
650 | expect(gestures).to.not.have.been.called; | |
651 | ||
652 | clock.tick(60); | |
653 | ||
654 | expect(gestures).to.have.been.calledTwice; | |
655 | ||
656 | expect(gestures.firstCall).to.have.been.calledWith( | |
657 | sinon.match({ type: 'gesturestart', | |
658 | detail: { type: 'twodrag', | |
659 | clientX: 45.0, | |
660 | clientY: 50.0, | |
661 | magnitudeX: 0.0, | |
662 | magnitudeY: 0.0 } })); | |
663 | ||
664 | expect(gestures.secondCall).to.have.been.calledWith( | |
665 | sinon.match({ type: 'gesturemove', | |
666 | detail: { type: 'twodrag', | |
667 | clientX: 45.0, | |
668 | clientY: 50.0, | |
669 | magnitudeX: 35.0, | |
670 | magnitudeY: 35.0 } })); | |
671 | }); | |
672 | ||
673 | it('should ignore too slow two finger drag', function () { | |
674 | touchStart(1, 20.0, 30.0); | |
675 | ||
676 | clock.tick(500); | |
677 | ||
678 | touchStart(2, 30.0, 30.0); | |
679 | touchMove(1, 40.0, 30.0); | |
680 | touchMove(2, 50.0, 30.0); | |
681 | touchMove(1, 80.0, 30.0); | |
682 | ||
683 | expect(gestures).to.not.have.been.called; | |
684 | }); | |
685 | }); | |
686 | ||
687 | describe('Pinch', function () { | |
688 | it('should handle pinching distinctly and fast inwards', function () { | |
689 | touchStart(1, 0.0, 0.0); | |
690 | touchStart(2, 130.0, 130.0); | |
691 | ||
692 | expect(gestures).to.not.have.been.called; | |
693 | ||
694 | touchMove(1, 50.0, 40.0); | |
695 | touchMove(2, 100.0, 130.0); | |
696 | ||
697 | expect(gestures).to.not.have.been.called; | |
698 | ||
699 | touchMove(2, 60.0, 70.0); | |
700 | ||
701 | expect(gestures).to.have.been.calledTwice; | |
702 | ||
703 | expect(gestures.firstCall).to.have.been.calledWith( | |
704 | sinon.match({ type: 'gesturestart', | |
705 | detail: { type: 'pinch', | |
706 | clientX: 65.0, | |
707 | clientY: 65.0, | |
708 | magnitudeX: 130.0, | |
709 | magnitudeY: 130.0 } })); | |
710 | ||
711 | expect(gestures.secondCall).to.have.been.calledWith( | |
712 | sinon.match({ type: 'gesturemove', | |
713 | detail: { type: 'pinch', | |
714 | clientX: 65.0, | |
715 | clientY: 65.0, | |
716 | magnitudeX: 10.0, | |
717 | magnitudeY: 30.0 } })); | |
718 | ||
719 | gestures.resetHistory(); | |
720 | ||
721 | touchEnd(1); | |
722 | ||
723 | expect(gestures).to.have.been.calledOnceWith( | |
724 | sinon.match({ type: 'gestureend', | |
725 | detail: { type: 'pinch', | |
726 | clientX: 65.0, | |
727 | clientY: 65.0, | |
728 | magnitudeX: 10.0, | |
729 | magnitudeY: 30.0 } })); | |
730 | }); | |
731 | ||
732 | it('should handle pinching fast and distinctly outwards', function () { | |
733 | touchStart(1, 100.0, 100.0); | |
734 | touchStart(2, 110.0, 100.0); | |
735 | ||
736 | expect(gestures).to.not.have.been.called; | |
737 | ||
738 | touchMove(1, 130.0, 70.0); | |
739 | touchMove(2, 0.0, 200.0); | |
740 | ||
741 | expect(gestures).to.not.have.been.called; | |
742 | ||
743 | touchMove(1, 180.0, 20.0); | |
744 | ||
745 | expect(gestures).to.have.been.calledTwice; | |
746 | ||
747 | expect(gestures.firstCall).to.have.been.calledWith( | |
748 | sinon.match({ type: 'gesturestart', | |
749 | detail: { type: 'pinch', | |
750 | clientX: 105.0, | |
751 | clientY: 100.0, | |
752 | magnitudeX: 10.0, | |
753 | magnitudeY: 0.0 } })); | |
754 | ||
755 | expect(gestures.secondCall).to.have.been.calledWith( | |
756 | sinon.match({ type: 'gesturemove', | |
757 | detail: { type: 'pinch', | |
758 | clientX: 105.0, | |
759 | clientY: 100.0, | |
760 | magnitudeX: 180.0, | |
761 | magnitudeY: 180.0 } })); | |
762 | ||
763 | gestures.resetHistory(); | |
764 | ||
765 | touchEnd(1); | |
766 | ||
767 | expect(gestures).to.have.been.calledOnceWith( | |
768 | sinon.match({ type: 'gestureend', | |
769 | detail: { type: 'pinch', | |
770 | clientX: 105.0, | |
771 | clientY: 100.0, | |
772 | magnitudeX: 180.0, | |
773 | magnitudeY: 180.0 } })); | |
774 | }); | |
775 | ||
776 | it('should ignore fast almost pinching', function () { | |
777 | touchStart(1, 20.0, 30.0); | |
778 | touchStart(2, 130.0, 130.0); | |
779 | touchMove(1, 80.0, 70.0); | |
780 | touchEnd(1); | |
781 | touchEnd(2); | |
782 | ||
783 | expect(gestures).to.not.have.been.called; | |
784 | ||
785 | clock.tick(1500); | |
786 | ||
787 | expect(gestures).to.not.have.been.called; | |
788 | }); | |
789 | ||
790 | it('should handle pinching inwards slowly', function () { | |
791 | touchStart(1, 0.0, 0.0); | |
792 | touchStart(2, 130.0, 130.0); | |
793 | touchMove(1, 50.0, 40.0); | |
794 | touchMove(2, 100.0, 130.0); | |
795 | ||
796 | expect(gestures).to.not.have.been.called; | |
797 | ||
798 | clock.tick(60); | |
799 | ||
800 | expect(gestures).to.have.been.calledTwice; | |
801 | ||
802 | expect(gestures.firstCall).to.have.been.calledWith( | |
803 | sinon.match({ type: 'gesturestart', | |
804 | detail: { type: 'pinch', | |
805 | clientX: 65.0, | |
806 | clientY: 65.0, | |
807 | magnitudeX: 130.0, | |
808 | magnitudeY: 130.0 } })); | |
809 | ||
810 | expect(gestures.secondCall).to.have.been.calledWith( | |
811 | sinon.match({ type: 'gesturemove', | |
812 | detail: { type: 'pinch', | |
813 | clientX: 65.0, | |
814 | clientY: 65.0, | |
815 | magnitudeX: 50.0, | |
816 | magnitudeY: 90.0 } })); | |
817 | }); | |
818 | ||
819 | it('should handle pinching outwards slowly', function () { | |
820 | touchStart(1, 100.0, 130.0); | |
821 | touchStart(2, 110.0, 130.0); | |
822 | touchMove(2, 200.0, 130.0); | |
823 | ||
824 | expect(gestures).to.not.have.been.called; | |
825 | ||
826 | clock.tick(60); | |
827 | ||
828 | expect(gestures).to.have.been.calledTwice; | |
829 | ||
830 | expect(gestures.firstCall).to.have.been.calledWith( | |
831 | sinon.match({ type: 'gesturestart', | |
832 | detail: { type: 'pinch', | |
833 | clientX: 105.0, | |
834 | clientY: 130.0, | |
835 | magnitudeX: 10.0, | |
836 | magnitudeY: 0.0 } })); | |
837 | ||
838 | expect(gestures.secondCall).to.have.been.calledWith( | |
839 | sinon.match({ type: 'gesturemove', | |
840 | detail: { type: 'pinch', | |
841 | clientX: 105.0, | |
842 | clientY: 130.0, | |
843 | magnitudeX: 100.0, | |
844 | magnitudeY: 0.0 } })); | |
845 | }); | |
846 | ||
847 | it('should ignore pinching too slowly', function () { | |
848 | touchStart(1, 0.0, 0.0); | |
849 | ||
850 | clock.tick(500); | |
851 | ||
852 | touchStart(2, 130.0, 130.0); | |
853 | touchMove(2, 100.0, 130.0); | |
854 | touchMove(1, 50.0, 40.0); | |
855 | ||
856 | expect(gestures).to.not.have.been.called; | |
857 | }); | |
858 | }); | |
859 | ||
860 | describe('Ignoring', function () { | |
861 | it('should ignore extra touches during gesture', function () { | |
862 | touchStart(1, 20.0, 30.0); | |
863 | touchMove(1, 40.0, 30.0); | |
864 | touchMove(1, 80.0, 30.0); | |
865 | ||
866 | expect(gestures).to.have.been.calledTwice; | |
867 | ||
868 | expect(gestures.firstCall).to.have.been.calledWith( | |
869 | sinon.match({ type: 'gesturestart', | |
870 | detail: { type: 'drag' } })); | |
871 | expect(gestures.secondCall).to.have.been.calledWith( | |
872 | sinon.match({ type: 'gesturemove', | |
873 | detail: { type: 'drag' } })); | |
874 | ||
875 | gestures.resetHistory(); | |
876 | ||
877 | touchStart(2, 10.0, 10.0); | |
878 | ||
879 | expect(gestures).to.not.have.been.called; | |
880 | ||
881 | touchMove(1, 100.0, 50.0); | |
882 | ||
883 | expect(gestures).to.have.been.calledOnceWith( | |
884 | sinon.match({ type: 'gesturemove', | |
885 | detail: { type: 'drag', | |
886 | clientX: 100.0, | |
887 | clientY: 50.0 } })); | |
888 | ||
889 | gestures.resetHistory(); | |
890 | ||
891 | touchEnd(1); | |
892 | ||
893 | expect(gestures).to.have.been.calledOnceWith( | |
894 | sinon.match({ type: 'gestureend', | |
895 | detail: { type: 'drag', | |
896 | clientX: 100.0, | |
897 | clientY: 50.0 } })); | |
898 | }); | |
899 | ||
900 | it('should ignore extra touches when waiting for gesture to end', function () { | |
901 | touchStart(1, 20.0, 30.0); | |
902 | touchStart(2, 30.0, 30.0); | |
903 | touchMove(1, 40.0, 30.0); | |
904 | touchMove(2, 90.0, 30.0); | |
905 | touchMove(1, 80.0, 30.0); | |
906 | ||
907 | expect(gestures).to.have.been.calledTwice; | |
908 | ||
909 | expect(gestures.firstCall).to.have.been.calledWith( | |
910 | sinon.match({ type: 'gesturestart', | |
911 | detail: { type: 'twodrag' } })); | |
912 | expect(gestures.secondCall).to.have.been.calledWith( | |
913 | sinon.match({ type: 'gesturemove', | |
914 | detail: { type: 'twodrag' } })); | |
915 | ||
916 | gestures.resetHistory(); | |
917 | ||
918 | touchEnd(1); | |
919 | ||
920 | expect(gestures).to.have.been.calledOnceWith( | |
921 | sinon.match({ type: 'gestureend', | |
922 | detail: { type: 'twodrag' } })); | |
923 | ||
924 | gestures.resetHistory(); | |
925 | ||
926 | touchStart(3, 10.0, 10.0); | |
927 | touchEnd(3); | |
928 | ||
929 | expect(gestures).to.not.have.been.called; | |
930 | }); | |
931 | ||
932 | it('should ignore extra touches after gesture', function () { | |
933 | touchStart(1, 20.0, 30.0); | |
934 | touchMove(1, 40.0, 30.0); | |
935 | touchMove(1, 80.0, 30.0); | |
936 | ||
937 | expect(gestures).to.have.been.calledTwice; | |
938 | ||
939 | expect(gestures.firstCall).to.have.been.calledWith( | |
940 | sinon.match({ type: 'gesturestart', | |
941 | detail: { type: 'drag' } })); | |
942 | expect(gestures.secondCall).to.have.been.calledWith( | |
943 | sinon.match({ type: 'gesturemove', | |
944 | detail: { type: 'drag' } })); | |
945 | ||
946 | gestures.resetHistory(); | |
947 | ||
948 | touchStart(2, 10.0, 10.0); | |
949 | ||
950 | expect(gestures).to.not.have.been.called; | |
951 | ||
952 | touchMove(1, 100.0, 50.0); | |
953 | ||
954 | expect(gestures).to.have.been.calledOnceWith( | |
955 | sinon.match({ type: 'gesturemove', | |
956 | detail: { type: 'drag' } })); | |
957 | ||
958 | gestures.resetHistory(); | |
959 | ||
960 | touchEnd(1); | |
961 | ||
962 | expect(gestures).to.have.been.calledOnceWith( | |
963 | sinon.match({ type: 'gestureend', | |
964 | detail: { type: 'drag' } })); | |
965 | ||
966 | gestures.resetHistory(); | |
967 | ||
968 | touchEnd(2); | |
969 | ||
970 | expect(gestures).to.not.have.been.called; | |
971 | ||
972 | // Check that everything is reseted after trailing ignores are released | |
973 | ||
974 | touchStart(3, 20.0, 30.0); | |
975 | touchEnd(3); | |
976 | ||
977 | expect(gestures).to.have.been.calledTwice; | |
978 | ||
979 | expect(gestures.firstCall).to.have.been.calledWith( | |
980 | sinon.match({ type: 'gesturestart', | |
981 | detail: { type: 'onetap' } })); | |
982 | expect(gestures.secondCall).to.have.been.calledWith( | |
983 | sinon.match({ type: 'gestureend', | |
984 | detail: { type: 'onetap' } })); | |
985 | }); | |
986 | ||
987 | it('should properly reset after a gesture', function () { | |
988 | touchStart(1, 20.0, 30.0); | |
989 | ||
990 | expect(gestures).to.not.have.been.called; | |
991 | ||
992 | touchEnd(1); | |
993 | ||
994 | expect(gestures).to.have.been.calledTwice; | |
995 | ||
996 | expect(gestures.firstCall).to.have.been.calledWith( | |
997 | sinon.match({ type: 'gesturestart', | |
998 | detail: { type: 'onetap', | |
999 | clientX: 20.0, | |
1000 | clientY: 30.0 } })); | |
1001 | ||
1002 | expect(gestures.secondCall).to.have.been.calledWith( | |
1003 | sinon.match({ type: 'gestureend', | |
1004 | detail: { type: 'onetap', | |
1005 | clientX: 20.0, | |
1006 | clientY: 30.0 } })); | |
1007 | ||
1008 | gestures.resetHistory(); | |
1009 | ||
1010 | touchStart(2, 70.0, 80.0); | |
1011 | ||
1012 | expect(gestures).to.not.have.been.called; | |
1013 | ||
1014 | touchEnd(2); | |
1015 | ||
1016 | expect(gestures).to.have.been.calledTwice; | |
1017 | ||
1018 | expect(gestures.firstCall).to.have.been.calledWith( | |
1019 | sinon.match({ type: 'gesturestart', | |
1020 | detail: { type: 'onetap', | |
1021 | clientX: 70.0, | |
1022 | clientY: 80.0 } })); | |
1023 | ||
1024 | expect(gestures.secondCall).to.have.been.calledWith( | |
1025 | sinon.match({ type: 'gestureend', | |
1026 | detail: { type: 'onetap', | |
1027 | clientX: 70.0, | |
1028 | clientY: 80.0 } })); | |
1029 | }); | |
1030 | }); | |
1031 | }); |