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