@samitouri / QOS-React-2 / commits / 8abf243b86

Ensure touch events are properly handled for pageX and pageY (#15587)

Dominic Gannaway committed May 8, 2019 at 19:08 UTC 8abf243b86e062cf54110d4b3bf629cd5d071dd8
2 files changed +563 -181
packages/react-events/src/Press.js
+36 -10
@@ -190,14 +190,13 @@ function dispatchLongPressChangeEvent(
190
191 function activate(event, context, props, state) {
192 const nativeEvent: any = event.nativeEvent;
193 - const pageX = nativeEvent.pageX;
194 - const pageY = nativeEvent.pageY;
193 + const {x, y} = getEventPageCoords(nativeEvent);
194 const wasActivePressed = state.isActivePressed;
195 state.isActivePressed = true;
197 - if (pageX != null && pageY != null) {
196 + if (x !== null && y !== null) {
197 state.activationPosition = {
199 - pageX: nativeEvent.pageX,
200 - pageY: nativeEvent.pageY,
198 + pageX: x,
199 + pageY: y,
200 };
201 }
202
@@ -402,12 +401,39 @@ function calculateResponderRegion(target: Element, props: PressProps) {
401 };
402 }
403
404 +function isTouchEvent(nativeEvent: Event): boolean {
405 + return Array.isArray((nativeEvent: any).changedTouches);
406 +}
407 +
408 +function getTouchFromPressEvent(nativeEvent: TouchEvent): Touch {
409 + const {changedTouches, touches} = nativeEvent;
410 + return changedTouches.length > 0
411 + ? changedTouches[0]
412 + : touches.length > 0
413 + ? touches[0]
414 + : (nativeEvent: any);
415 +}
416 +
417 +function getEventPageCoords(
418 + nativeEvent: Event,
419 +): {x: null | number, y: null | number} {
420 + let eventObject = (nativeEvent: any);
421 + if (isTouchEvent(eventObject)) {
422 + eventObject = getTouchFromPressEvent(eventObject);
423 + }
424 + const pageX = eventObject.pageX;
425 + const pageY = eventObject.pageY;
426 + return {
427 + x: pageX != null ? pageX : null,
428 + y: pageY != null ? pageY : null,
429 + };
430 +}
431 +
432 function isPressWithinResponderRegion(
433 nativeEvent: $PropertyType<ReactResponderEvent, 'nativeEvent'>,
434 state: PressState,
435 ): boolean {
436 const {responderRegionOnActivation, responderRegionOnDeactivation} = state;
410 - const event = (nativeEvent: any);
437 let left, top, right, bottom;
438
439 if (responderRegionOnActivation != null) {
@@ -423,16 +449,16 @@ function isPressWithinResponderRegion(
449 bottom = Math.max(bottom, responderRegionOnDeactivation.bottom);
450 }
451 }
452 + const {x, y} = getEventPageCoords(((nativeEvent: any): Event));
453
454 return (
455 left != null &&
456 right != null &&
457 top != null &&
458 bottom != null &&
432 - (event.pageX >= left &&
433 - event.pageX <= right &&
434 - event.pageY >= top &&
435 - event.pageY <= bottom)
459 + x !== null &&
460 + y !== null &&
461 + (x >= left && x <= right && y >= top && y <= bottom)
462 );
463 }
464
packages/react-events/src/__tests__/Press-test.internal.js
+527 -171
@@ -16,7 +16,7 @@ let Press;
16
17 const DEFAULT_LONG_PRESS_DELAY = 500;
18
19 -const createPointerEvent = (type, data) => {
19 +const createEvent = (type, data) => {
20 const event = document.createEvent('CustomEvent');
21 event.initCustomEvent(type, true, true);
22 if (data != null) {
@@ -77,8 +77,8 @@ describe('Event responder: Press', () => {
77 });
78
79 it('prevents custom events being dispatched', () => {
80 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
81 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
80 + ref.current.dispatchEvent(createEvent('pointerdown'));
81 + ref.current.dispatchEvent(createEvent('pointerup'));
82 expect(onPressStart).not.toBeCalled();
83 expect(onPress).not.toBeCalled();
84 expect(onPressEnd).not.toBeCalled();
@@ -101,7 +101,7 @@ describe('Event responder: Press', () => {
101
102 it('is called after "pointerdown" event', () => {
103 ref.current.dispatchEvent(
104 - createPointerEvent('pointerdown', {pointerType: 'pen'}),
104 + createEvent('pointerdown', {pointerType: 'pen'}),
105 );
106 expect(onPressStart).toHaveBeenCalledTimes(1);
107 expect(onPressStart).toHaveBeenCalledWith(
@@ -110,16 +110,16 @@ describe('Event responder: Press', () => {
110 });
111
112 it('ignores browser emulated events', () => {
113 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
114 - ref.current.dispatchEvent(createPointerEvent('touchstart'));
115 - ref.current.dispatchEvent(createPointerEvent('mousedown'));
113 + ref.current.dispatchEvent(createEvent('pointerdown'));
114 + ref.current.dispatchEvent(createEvent('touchstart'));
115 + ref.current.dispatchEvent(createEvent('mousedown'));
116 expect(onPressStart).toHaveBeenCalledTimes(1);
117 });
118
119 it('ignores any events not caused by left-click or touch/pen contact', () => {
120 - ref.current.dispatchEvent(createPointerEvent('pointerdown', {button: 1}));
121 - ref.current.dispatchEvent(createPointerEvent('pointerdown', {button: 5}));
122 - ref.current.dispatchEvent(createPointerEvent('mousedown', {button: 2}));
120 + ref.current.dispatchEvent(createEvent('pointerdown', {button: 1}));
121 + ref.current.dispatchEvent(createEvent('pointerdown', {button: 5}));
122 + ref.current.dispatchEvent(createEvent('mousedown', {button: 2}));
123 expect(onPressStart).toHaveBeenCalledTimes(0);
124 });
125
@@ -151,14 +151,14 @@ describe('Event responder: Press', () => {
151
152 // No PointerEvent fallbacks
153 it('is called after "mousedown" event', () => {
154 - ref.current.dispatchEvent(createPointerEvent('mousedown'));
154 + ref.current.dispatchEvent(createEvent('mousedown'));
155 expect(onPressStart).toHaveBeenCalledTimes(1);
156 expect(onPressStart).toHaveBeenCalledWith(
157 expect.objectContaining({pointerType: 'mouse', type: 'pressstart'}),
158 );
159 });
160 it('is called after "touchstart" event', () => {
161 - ref.current.dispatchEvent(createPointerEvent('touchstart'));
161 + ref.current.dispatchEvent(createEvent('touchstart'));
162 expect(onPressStart).toHaveBeenCalledTimes(1);
163 expect(onPressStart).toHaveBeenCalledWith(
164 expect.objectContaining({pointerType: 'touch', type: 'pressstart'}),
@@ -174,7 +174,7 @@ describe('Event responder: Press', () => {
174 );
175 ReactDOM.render(element, container);
176
177 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
177 + ref.current.dispatchEvent(createEvent('pointerdown'));
178 jest.advanceTimersByTime(1999);
179 expect(onPressStart).not.toBeCalled();
180 jest.advanceTimersByTime(1);
@@ -196,11 +196,11 @@ describe('Event responder: Press', () => {
196 right: 500,
197 });
198
199 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
199 + ref.current.dispatchEvent(createEvent('pointerdown'));
200 jest.advanceTimersByTime(499);
201 expect(onPressStart).toHaveBeenCalledTimes(0);
202 ref.current.dispatchEvent(
203 - createPointerEvent('pointerup', {
203 + createEvent('pointerup', {
204 pageX: 55,
205 pageY: 55,
206 }),
@@ -218,7 +218,7 @@ describe('Event responder: Press', () => {
218 );
219 ReactDOM.render(element, container);
220
221 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
221 + ref.current.dispatchEvent(createEvent('pointerdown'));
222 expect(onPressStart).toHaveBeenCalledTimes(1);
223 });
224 });
@@ -235,9 +235,9 @@ describe('Event responder: Press', () => {
235 );
236 ReactDOM.render(element, container);
237
238 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
239 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
240 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
238 + ref.current.dispatchEvent(createEvent('pointerdown'));
239 + ref.current.dispatchEvent(createEvent('pointerup'));
240 + ref.current.dispatchEvent(createEvent('pointerdown'));
241 expect(onPressStart).toHaveBeenCalledTimes(2);
242 });
243 });
@@ -259,9 +259,9 @@ describe('Event responder: Press', () => {
259
260 it('is called after "pointerup" event', () => {
261 ref.current.dispatchEvent(
262 - createPointerEvent('pointerdown', {pointerType: 'pen'}),
262 + createEvent('pointerdown', {pointerType: 'pen'}),
263 );
264 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
264 + ref.current.dispatchEvent(createEvent('pointerup'));
265 expect(onPressEnd).toHaveBeenCalledTimes(1);
266 expect(onPressEnd).toHaveBeenCalledWith(
267 expect.objectContaining({pointerType: 'pen', type: 'pressend'}),
@@ -270,13 +270,13 @@ describe('Event responder: Press', () => {
270
271 it('ignores browser emulated events', () => {
272 ref.current.dispatchEvent(
273 - createPointerEvent('pointerdown', {pointerType: 'touch'}),
273 + createEvent('pointerdown', {pointerType: 'touch'}),
274 );
275 - ref.current.dispatchEvent(createPointerEvent('touchstart'));
276 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
277 - ref.current.dispatchEvent(createPointerEvent('touchend'));
278 - ref.current.dispatchEvent(createPointerEvent('mousedown'));
279 - ref.current.dispatchEvent(createPointerEvent('mouseup'));
275 + ref.current.dispatchEvent(createEvent('touchstart'));
276 + ref.current.dispatchEvent(createEvent('pointerup'));
277 + ref.current.dispatchEvent(createEvent('touchend'));
278 + ref.current.dispatchEvent(createEvent('mousedown'));
279 + ref.current.dispatchEvent(createEvent('mouseup'));
280 expect(onPressEnd).toHaveBeenCalledTimes(1);
281 expect(onPressEnd).toHaveBeenCalledWith(
282 expect.objectContaining({pointerType: 'touch', type: 'pressend'}),
@@ -309,16 +309,16 @@ describe('Event responder: Press', () => {
309
310 // No PointerEvent fallbacks
311 it('is called after "mouseup" event', () => {
312 - ref.current.dispatchEvent(createPointerEvent('mousedown'));
313 - ref.current.dispatchEvent(createPointerEvent('mouseup'));
312 + ref.current.dispatchEvent(createEvent('mousedown'));
313 + ref.current.dispatchEvent(createEvent('mouseup'));
314 expect(onPressEnd).toHaveBeenCalledTimes(1);
315 expect(onPressEnd).toHaveBeenCalledWith(
316 expect.objectContaining({pointerType: 'mouse', type: 'pressend'}),
317 );
318 });
319 it('is called after "touchend" event', () => {
320 - ref.current.dispatchEvent(createPointerEvent('touchstart'));
321 - ref.current.dispatchEvent(createPointerEvent('touchend'));
320 + ref.current.dispatchEvent(createEvent('touchstart'));
321 + ref.current.dispatchEvent(createEvent('touchend'));
322 expect(onPressEnd).toHaveBeenCalledTimes(1);
323 expect(onPressEnd).toHaveBeenCalledWith(
324 expect.objectContaining({pointerType: 'touch', type: 'pressend'}),
@@ -334,8 +334,8 @@ describe('Event responder: Press', () => {
334 );
335 ReactDOM.render(element, container);
336
337 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
338 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
337 + ref.current.dispatchEvent(createEvent('pointerdown'));
338 + ref.current.dispatchEvent(createEvent('pointerup'));
339 jest.advanceTimersByTime(1999);
340 expect(onPressEnd).not.toBeCalled();
341 jest.advanceTimersByTime(1);
@@ -350,13 +350,13 @@ describe('Event responder: Press', () => {
350 );
351 ReactDOM.render(element, container);
352
353 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
354 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
353 + ref.current.dispatchEvent(createEvent('pointerdown'));
354 + ref.current.dispatchEvent(createEvent('pointerup'));
355 jest.advanceTimersByTime(499);
356 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
356 + ref.current.dispatchEvent(createEvent('pointerdown'));
357 jest.advanceTimersByTime(1);
358 expect(onPressEnd).not.toBeCalled();
359 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
359 + ref.current.dispatchEvent(createEvent('pointerup'));
360 jest.runAllTimers();
361 expect(onPressEnd).toHaveBeenCalledTimes(1);
362 });
@@ -370,8 +370,8 @@ describe('Event responder: Press', () => {
370 );
371 ReactDOM.render(element, container);
372
373 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
374 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
373 + ref.current.dispatchEvent(createEvent('pointerdown'));
374 + ref.current.dispatchEvent(createEvent('pointerup'));
375 expect(onPressEnd).toHaveBeenCalledTimes(1);
376 });
377 });
@@ -391,10 +391,10 @@ describe('Event responder: Press', () => {
391 });
392
393 it('is called after "pointerdown" and "pointerup" events', () => {
394 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
394 + ref.current.dispatchEvent(createEvent('pointerdown'));
395 expect(onPressChange).toHaveBeenCalledTimes(1);
396 expect(onPressChange).toHaveBeenCalledWith(true);
397 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
397 + ref.current.dispatchEvent(createEvent('pointerup'));
398 expect(onPressChange).toHaveBeenCalledTimes(2);
399 expect(onPressChange).toHaveBeenCalledWith(false);
400 });
@@ -416,7 +416,7 @@ describe('Event responder: Press', () => {
416 );
417 ReactDOM.render(element, container);
418
419 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
419 + ref.current.dispatchEvent(createEvent('pointerdown'));
420 jest.advanceTimersByTime(499);
421 expect(onPressChange).not.toBeCalled();
422 jest.advanceTimersByTime(1);
@@ -439,10 +439,10 @@ describe('Event responder: Press', () => {
439 right: 500,
440 });
441
442 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
442 + ref.current.dispatchEvent(createEvent('pointerdown'));
443 jest.advanceTimersByTime(100);
444 ref.current.dispatchEvent(
445 - createPointerEvent('pointerup', {
445 + createEvent('pointerup', {
446 pageX: 55,
447 pageY: 55,
448 }),
@@ -461,10 +461,10 @@ describe('Event responder: Press', () => {
461 );
462 ReactDOM.render(element, container);
463
464 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
464 + ref.current.dispatchEvent(createEvent('pointerdown'));
465 expect(onPressChange).toHaveBeenCalledTimes(1);
466 expect(onPressChange).toHaveBeenCalledWith(true);
467 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
467 + ref.current.dispatchEvent(createEvent('pointerup'));
468 jest.advanceTimersByTime(499);
469 expect(onPressChange).toHaveBeenCalledTimes(1);
470 jest.advanceTimersByTime(1);
@@ -474,18 +474,18 @@ describe('Event responder: Press', () => {
474
475 // No PointerEvent fallbacks
476 it('is called after "mousedown" and "mouseup" events', () => {
477 - ref.current.dispatchEvent(createPointerEvent('mousedown'));
477 + ref.current.dispatchEvent(createEvent('mousedown'));
478 expect(onPressChange).toHaveBeenCalledTimes(1);
479 expect(onPressChange).toHaveBeenCalledWith(true);
480 - ref.current.dispatchEvent(createPointerEvent('mouseup'));
480 + ref.current.dispatchEvent(createEvent('mouseup'));
481 expect(onPressChange).toHaveBeenCalledTimes(2);
482 expect(onPressChange).toHaveBeenCalledWith(false);
483 });
484 it('is called after "touchstart" and "touchend" events', () => {
485 - ref.current.dispatchEvent(createPointerEvent('touchstart'));
485 + ref.current.dispatchEvent(createEvent('touchstart'));
486 expect(onPressChange).toHaveBeenCalledTimes(1);
487 expect(onPressChange).toHaveBeenCalledWith(true);
488 - ref.current.dispatchEvent(createPointerEvent('touchend'));
488 + ref.current.dispatchEvent(createEvent('touchend'));
489 expect(onPressChange).toHaveBeenCalledTimes(2);
490 expect(onPressChange).toHaveBeenCalledWith(false);
491 });
@@ -513,10 +513,10 @@ describe('Event responder: Press', () => {
513
514 it('is called after "pointerup" event', () => {
515 ref.current.dispatchEvent(
516 - createPointerEvent('pointerdown', {pointerType: 'pen'}),
516 + createEvent('pointerdown', {pointerType: 'pen'}),
517 );
518 ref.current.dispatchEvent(
519 - createPointerEvent('pointerup', {pageX: 10, pageY: 10}),
519 + createEvent('pointerup', {pageX: 10, pageY: 10}),
520 );
521 expect(onPress).toHaveBeenCalledTimes(1);
522 expect(onPress).toHaveBeenCalledWith(
@@ -541,9 +541,9 @@ describe('Event responder: Press', () => {
541 );
542 ReactDOM.render(element, container);
543
544 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
544 + ref.current.dispatchEvent(createEvent('pointerdown'));
545 ref.current.dispatchEvent(
546 - createPointerEvent('pointerup', {pageX: 10, pageY: 10}),
546 + createEvent('pointerup', {pageX: 10, pageY: 10}),
547 );
548 expect(onPress).toHaveBeenCalledTimes(1);
549 });
@@ -551,8 +551,8 @@ describe('Event responder: Press', () => {
551 // No PointerEvent fallbacks
552 // TODO: jsdom missing APIs
553 // it('is called after "touchend" event', () => {
554 - // ref.current.dispatchEvent(createPointerEvent('touchstart'));
555 - // ref.current.dispatchEvent(createPointerEvent('touchend'));
554 + // ref.current.dispatchEvent(createEvent('touchstart'));
555 + // ref.current.dispatchEvent(createEvent('touchend'));
556 // expect(onPress).toHaveBeenCalledTimes(1);
557 // });
558 });
@@ -573,7 +573,7 @@ describe('Event responder: Press', () => {
573
574 it('is called if "pointerdown" lasts default delay', () => {
575 ref.current.dispatchEvent(
576 - createPointerEvent('pointerdown', {pointerType: 'pen'}),
576 + createEvent('pointerdown', {pointerType: 'pen'}),
577 );
578 jest.advanceTimersByTime(DEFAULT_LONG_PRESS_DELAY - 1);
579 expect(onLongPress).not.toBeCalled();
@@ -585,9 +585,9 @@ describe('Event responder: Press', () => {
585 });
586
587 it('is not called if "pointerup" is dispatched before delay', () => {
588 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
588 + ref.current.dispatchEvent(createEvent('pointerdown'));
589 jest.advanceTimersByTime(DEFAULT_LONG_PRESS_DELAY - 1);
590 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
590 + ref.current.dispatchEvent(createEvent('pointerup'));
591 jest.advanceTimersByTime(1);
592 expect(onLongPress).not.toBeCalled();
593 });
@@ -619,10 +619,10 @@ describe('Event responder: Press', () => {
619 right: 100,
620 });
621 ref.current.dispatchEvent(
622 - createPointerEvent('pointerdown', {pageX: 10, pageY: 10}),
622 + createEvent('pointerdown', {pageX: 10, pageY: 10}),
623 );
624 ref.current.dispatchEvent(
625 - createPointerEvent('pointermove', {pageX: 50, pageY: 50}),
625 + createEvent('pointermove', {pageX: 50, pageY: 50}),
626 );
627 jest.runAllTimers();
628 expect(onLongPress).not.toBeCalled();
@@ -637,7 +637,7 @@ describe('Event responder: Press', () => {
637 );
638 ReactDOM.render(element, container);
639
640 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
640 + ref.current.dispatchEvent(createEvent('pointerdown'));
641 jest.advanceTimersByTime(1999);
642 expect(onLongPress).not.toBeCalled();
643 jest.advanceTimersByTime(1);
@@ -652,7 +652,7 @@ describe('Event responder: Press', () => {
652 );
653 ReactDOM.render(element, container);
654
655 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
655 + ref.current.dispatchEvent(createEvent('pointerdown'));
656 jest.advanceTimersByTime(9);
657 expect(onLongPress).not.toBeCalled();
658 jest.advanceTimersByTime(1);
@@ -668,7 +668,7 @@ describe('Event responder: Press', () => {
668 );
669 ReactDOM.render(element, container);
670
671 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
671 + ref.current.dispatchEvent(createEvent('pointerdown'));
672 jest.advanceTimersByTime(
673 delayPressStart + DEFAULT_LONG_PRESS_DELAY - 1,
674 );
@@ -690,11 +690,11 @@ describe('Event responder: Press', () => {
690 );
691 ReactDOM.render(element, container);
692
693 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
693 + ref.current.dispatchEvent(createEvent('pointerdown'));
694 jest.advanceTimersByTime(DEFAULT_LONG_PRESS_DELAY);
695 expect(onLongPressChange).toHaveBeenCalledTimes(1);
696 expect(onLongPressChange).toHaveBeenCalledWith(true);
697 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
697 + ref.current.dispatchEvent(createEvent('pointerup'));
698 expect(onLongPressChange).toHaveBeenCalledTimes(2);
699 expect(onLongPressChange).toHaveBeenCalledWith(false);
700 });
@@ -709,11 +709,11 @@ describe('Event responder: Press', () => {
709 );
710 ReactDOM.render(element, container);
711
712 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
712 + ref.current.dispatchEvent(createEvent('pointerdown'));
713 jest.advanceTimersByTime(DEFAULT_LONG_PRESS_DELAY);
714 expect(onLongPressChange).toHaveBeenCalledTimes(1);
715 expect(onLongPressChange).toHaveBeenCalledWith(true);
716 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
716 + ref.current.dispatchEvent(createEvent('pointerup'));
717 jest.advanceTimersByTime(499);
718 expect(onLongPressChange).toHaveBeenCalledTimes(1);
719 jest.advanceTimersByTime(1);
@@ -739,10 +739,10 @@ describe('Event responder: Press', () => {
739 ReactDOM.render(element, container);
740
741 // NOTE: onPressChange behavior should not be affected
742 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
742 + ref.current.dispatchEvent(createEvent('pointerdown'));
743 expect(onPressChange).toHaveBeenCalledTimes(1);
744 jest.advanceTimersByTime(DEFAULT_LONG_PRESS_DELAY);
745 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
745 + ref.current.dispatchEvent(createEvent('pointerup'));
746 expect(onPress).not.toBeCalled();
747 expect(onPressChange).toHaveBeenCalledTimes(2);
748 });
@@ -766,10 +766,10 @@ describe('Event responder: Press', () => {
766 right: 100,
767 });
768 ref.current.dispatchEvent(
769 - createPointerEvent('pointerdown', {pointerType: 'touch'}),
769 + createEvent('pointerdown', {pointerType: 'touch'}),
770 );
771 ref.current.dispatchEvent(
772 - createPointerEvent('pointermove', {
772 + createEvent('pointermove', {
773 pointerType: 'touch',
774 pageX: 10,
775 pageY: 10,
@@ -799,7 +799,7 @@ describe('Event responder: Press', () => {
799 });
800 ref.current.dispatchEvent(createKeyboardEvent('keydown', {key: 'Enter'}));
801 ref.current.dispatchEvent(
802 - createPointerEvent('pointermove', {
802 + createEvent('pointermove', {
803 pointerType: 'mouse',
804 pageX: 10,
805 pageY: 10,
@@ -825,23 +825,23 @@ describe('Event responder: Press', () => {
825 right: 100,
826 });
827 ref.current.dispatchEvent(
828 - createPointerEvent('pointerdown', {pointerType: 'touch'}),
828 + createEvent('pointerdown', {pointerType: 'touch'}),
829 );
830 - ref.current.dispatchEvent(createPointerEvent('touchstart'));
830 + ref.current.dispatchEvent(createEvent('touchstart'));
831 ref.current.dispatchEvent(
832 - createPointerEvent('pointermove', {
832 + createEvent('pointermove', {
833 pointerType: 'touch',
834 pageX: 10,
835 pageY: 10,
836 }),
837 );
838 - ref.current.dispatchEvent(createPointerEvent('touchmove'));
839 - ref.current.dispatchEvent(createPointerEvent('mousemove'));
838 + ref.current.dispatchEvent(createEvent('touchmove'));
839 + ref.current.dispatchEvent(createEvent('mousemove'));
840 expect(onPressMove).toHaveBeenCalledTimes(1);
841 });
842 });
843
844 - describe('press with movement', () => {
844 + describe('press with movement (pointer events)', () => {
845 const rectMock = {
846 width: 100,
847 height: 100,
@@ -890,13 +890,11 @@ describe('Event responder: Press', () => {
890 ReactDOM.render(element, container);
891
892 ref.current.getBoundingClientRect = getBoundingClientRectMock;
893 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
893 + ref.current.dispatchEvent(createEvent('pointerdown'));
894 ref.current.dispatchEvent(
895 - createPointerEvent('pointermove', coordinatesInside),
896 - );
897 - ref.current.dispatchEvent(
898 - createPointerEvent('pointerup', coordinatesInside),
895 + createEvent('pointermove', coordinatesInside),
896 );
897 + ref.current.dispatchEvent(createEvent('pointerup', coordinatesInside));
898 jest.runAllTimers();
899
900 expect(events).toEqual([
@@ -931,9 +929,9 @@ describe('Event responder: Press', () => {
929 ReactDOM.render(element, container);
930
931 ref.current.getBoundingClientRect = getBoundingClientRectMock;
934 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
932 + ref.current.dispatchEvent(createEvent('pointerdown'));
933 ref.current.dispatchEvent(
936 - createPointerEvent('pointermove', coordinatesInside),
934 + createEvent('pointermove', coordinatesInside),
935 );
936 jest.advanceTimersByTime(499);
937 expect(events).toEqual(['onPressMove']);
@@ -943,9 +941,7 @@ describe('Event responder: Press', () => {
941 expect(events).toEqual(['onPressStart', 'onPressChange']);
942 events = [];
943
946 - ref.current.dispatchEvent(
947 - createPointerEvent('pointerup', coordinatesInside),
948 - );
944 + ref.current.dispatchEvent(createEvent('pointerup', coordinatesInside));
945 expect(events).toEqual(['onPressEnd', 'onPressChange', 'onPress']);
946 });
947
@@ -971,16 +967,14 @@ describe('Event responder: Press', () => {
967
968 ReactDOM.render(element, container);
969 ref.current.getBoundingClientRect = getBoundingClientRectMock;
974 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
970 + ref.current.dispatchEvent(createEvent('pointerdown'));
971 ref.current.dispatchEvent(
976 - createPointerEvent('pointermove', {
972 + createEvent('pointermove', {
973 pageX: rectMock.left - pressRetentionOffset.left,
974 pageY: rectMock.top - pressRetentionOffset.top,
975 }),
976 );
981 - ref.current.dispatchEvent(
982 - createPointerEvent('pointerup', coordinatesInside),
983 - );
977 + ref.current.dispatchEvent(createEvent('pointerup', coordinatesInside));
978 expect(events).toEqual([
979 'onPressStart',
980 'onPressChange',
@@ -1009,7 +1003,7 @@ describe('Event responder: Press', () => {
1003
1004 ReactDOM.render(element, container);
1005 ref.current.getBoundingClientRect = getBoundingClientRectMock;
1012 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1006 + ref.current.dispatchEvent(createEvent('pointerdown'));
1007 // emulate smaller dimensions change on activation
1008 ref.current.getBoundingClientRect = () => ({
1009 width: 80,
@@ -1024,10 +1018,8 @@ describe('Event responder: Press', () => {
1018 pageY: rectMock.top,
1019 };
1020 // move to an area within the pre-activation region
1027 - ref.current.dispatchEvent(
1028 - createPointerEvent('pointermove', coordinates),
1029 - );
1030 - ref.current.dispatchEvent(createPointerEvent('pointerup', coordinates));
1021 + ref.current.dispatchEvent(createEvent('pointermove', coordinates));
1022 + ref.current.dispatchEvent(createEvent('pointerup', coordinates));
1023 expect(events).toEqual(['onPressStart', 'onPressEnd', 'onPress']);
1024 });
1025
@@ -1049,7 +1041,7 @@ describe('Event responder: Press', () => {
1041
1042 ReactDOM.render(element, container);
1043 ref.current.getBoundingClientRect = getBoundingClientRectMock;
1052 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1044 + ref.current.dispatchEvent(createEvent('pointerdown'));
1045 // emulate larger dimensions change on activation
1046 ref.current.getBoundingClientRect = () => ({
1047 width: 200,
@@ -1064,10 +1056,8 @@ describe('Event responder: Press', () => {
1056 pageY: rectMock.top - 50,
1057 };
1058 // move to an area within the post-activation region
1067 - ref.current.dispatchEvent(
1068 - createPointerEvent('pointermove', coordinates),
1069 - );
1070 - ref.current.dispatchEvent(createPointerEvent('pointerup', coordinates));
1059 + ref.current.dispatchEvent(createEvent('pointermove', coordinates));
1060 + ref.current.dispatchEvent(createEvent('pointerup', coordinates));
1061 expect(events).toEqual(['onPressStart', 'onPressEnd', 'onPress']);
1062 });
1063 });
@@ -1103,16 +1093,12 @@ describe('Event responder: Press', () => {
1093 ReactDOM.render(element, container);
1094
1095 ref.current.getBoundingClientRect = getBoundingClientRectMock;
1106 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1096 + ref.current.dispatchEvent(createEvent('pointerdown'));
1097 ref.current.dispatchEvent(
1108 - createPointerEvent('pointermove', coordinatesInside),
1109 - );
1110 - container.dispatchEvent(
1111 - createPointerEvent('pointermove', coordinatesOutside),
1112 - );
1113 - container.dispatchEvent(
1114 - createPointerEvent('pointerup', coordinatesOutside),
1098 + createEvent('pointermove', coordinatesInside),
1099 );
1100 + container.dispatchEvent(createEvent('pointermove', coordinatesOutside));
1101 + container.dispatchEvent(createEvent('pointerup', coordinatesOutside));
1102 jest.runAllTimers();
1103
1104 expect(events).toEqual([
@@ -1148,19 +1134,15 @@ describe('Event responder: Press', () => {
1134 ReactDOM.render(element, container);
1135
1136 ref.current.getBoundingClientRect = getBoundingClientRectMock;
1151 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1137 + ref.current.dispatchEvent(createEvent('pointerdown'));
1138 ref.current.dispatchEvent(
1153 - createPointerEvent('pointermove', coordinatesInside),
1154 - );
1155 - container.dispatchEvent(
1156 - createPointerEvent('pointermove', coordinatesOutside),
1139 + createEvent('pointermove', coordinatesInside),
1140 );
1141 + container.dispatchEvent(createEvent('pointermove', coordinatesOutside));
1142 jest.runAllTimers();
1143 expect(events).toEqual(['onPressMove']);
1144 events = [];
1161 - container.dispatchEvent(
1162 - createPointerEvent('pointerup', coordinatesOutside),
1163 - );
1145 + container.dispatchEvent(createEvent('pointerup', coordinatesOutside));
1146 jest.runAllTimers();
1147 expect(events).toEqual([]);
1148 });
@@ -1188,24 +1170,24 @@ describe('Event responder: Press', () => {
1170
1171 ref.current.getBoundingClientRect = getBoundingClientRectMock;
1172 ref.current.dispatchEvent(
1191 - createPointerEvent('pointerdown', {
1173 + createEvent('pointerdown', {
1174 pointerType: 'mouse',
1175 }),
1176 );
1177 ref.current.dispatchEvent(
1196 - createPointerEvent('pointermove', {
1178 + createEvent('pointermove', {
1179 ...coordinatesInside,
1180 pointerType: 'mouse',
1181 }),
1182 );
1183 container.dispatchEvent(
1202 - createPointerEvent('pointermove', {
1184 + createEvent('pointermove', {
1185 ...coordinatesOutside,
1186 pointerType: 'mouse',
1187 }),
1188 );
1189 container.dispatchEvent(
1208 - createPointerEvent('pointerup', {
1190 + createEvent('pointerup', {
1191 ...coordinatesOutside,
1192 pointerType: 'mouse',
1193 }),
@@ -1243,30 +1225,30 @@ describe('Event responder: Press', () => {
1225
1226 ref.current.getBoundingClientRect = getBoundingClientRectMock;
1227 ref.current.dispatchEvent(
1246 - createPointerEvent('pointerdown', {
1228 + createEvent('pointerdown', {
1229 pointerType: 'mouse',
1230 }),
1231 );
1232 ref.current.dispatchEvent(
1251 - createPointerEvent('pointermove', {
1233 + createEvent('pointermove', {
1234 ...coordinatesInside,
1235 pointerType: 'mouse',
1236 }),
1237 );
1238 container.dispatchEvent(
1257 - createPointerEvent('pointermove', {
1239 + createEvent('pointermove', {
1240 ...coordinatesOutside,
1241 pointerType: 'mouse',
1242 }),
1243 );
1244 container.dispatchEvent(
1263 - createPointerEvent('pointermove', {
1245 + createEvent('pointermove', {
1246 ...coordinatesInside,
1247 pointerType: 'mouse',
1248 }),
1249 );
1250 container.dispatchEvent(
1269 - createPointerEvent('pointerup', {
1251 + createEvent('pointerup', {
1252 ...coordinatesInside,
1253 pointerType: 'mouse',
1254 }),
@@ -1309,30 +1291,404 @@ describe('Event responder: Press', () => {
1291
1292 ref.current.getBoundingClientRect = getBoundingClientRectMock;
1293 ref.current.dispatchEvent(
1312 - createPointerEvent('pointerdown', {
1294 + createEvent('pointerdown', {
1295 + pointerType: 'touch',
1296 + }),
1297 + );
1298 + ref.current.dispatchEvent(
1299 + createEvent('pointermove', {
1300 + ...coordinatesInside,
1301 + pointerType: 'touch',
1302 + }),
1303 + );
1304 + container.dispatchEvent(
1305 + createEvent('pointermove', {
1306 + ...coordinatesOutside,
1307 + pointerType: 'touch',
1308 + }),
1309 + );
1310 + container.dispatchEvent(
1311 + createEvent('pointermove', {
1312 + ...coordinatesInside,
1313 + pointerType: 'touch',
1314 + }),
1315 + );
1316 + container.dispatchEvent(
1317 + createEvent('pointerup', {
1318 + ...coordinatesInside,
1319 + pointerType: 'touch',
1320 + }),
1321 + );
1322 + jest.runAllTimers();
1323 +
1324 + expect(events).toEqual([
1325 + 'onPressStart',
1326 + 'onPressChange',
1327 + 'onPressMove',
1328 + 'onPressEnd',
1329 + 'onPressChange',
1330 + 'onPressStart',
1331 + 'onPressChange',
1332 + 'onPressEnd',
1333 + 'onPressChange',
1334 + 'onPress',
1335 + ]);
1336 + });
1337 + });
1338 +
1339 + describe('press with movement (touch events fallback)', () => {
1340 + const rectMock = {
1341 + width: 100,
1342 + height: 100,
1343 + top: 50,
1344 + left: 50,
1345 + right: 500,
1346 + bottom: 500,
1347 + };
1348 + const pressRectOffset = 20;
1349 + const getBoundingClientRectMock = () => rectMock;
1350 + const coordinatesInside = {
1351 + changedTouches: [
1352 + {
1353 + pageX: rectMock.left - pressRectOffset,
1354 + pageY: rectMock.top - pressRectOffset,
1355 + },
1356 + ],
1357 + };
1358 + const coordinatesOutside = {
1359 + changedTouches: [
1360 + {
1361 + pageX: rectMock.left - pressRectOffset - 1,
1362 + pageY: rectMock.top - pressRectOffset - 1,
1363 + },
1364 + ],
1365 + };
1366 +
1367 + describe('within bounds of hit rect', () => {
1368 + /** ┌──────────────────┐
1369 + * │ ┌────────────┐ │
1370 + * │ │ VisualRect │ │
1371 + * │ └────────────┘ │
1372 + * │ HitRect X │ <= Move to X and release
1373 + * └──────────────────┘
1374 + */
1375 + it('no delay and "onPress*" events are called immediately', () => {
1376 + let events = [];
1377 + const ref = React.createRef();
1378 + const createEventHandler = msg => () => {
1379 + events.push(msg);
1380 + };
1381 +
1382 + const element = (
1383 + <Press
1384 + onPress={createEventHandler('onPress')}
1385 + onPressChange={createEventHandler('onPressChange')}
1386 + onPressMove={createEventHandler('onPressMove')}
1387 + onPressStart={createEventHandler('onPressStart')}
1388 + onPressEnd={createEventHandler('onPressEnd')}>
1389 + <div ref={ref} />
1390 + </Press>
1391 + );
1392 +
1393 + ReactDOM.render(element, container);
1394 +
1395 + ref.current.getBoundingClientRect = getBoundingClientRectMock;
1396 + ref.current.dispatchEvent(createEvent('touchstart'));
1397 + ref.current.dispatchEvent(createEvent('touchmove', coordinatesInside));
1398 + ref.current.dispatchEvent(createEvent('touchend', coordinatesInside));
1399 + jest.runAllTimers();
1400 +
1401 + expect(events).toEqual([
1402 + 'onPressStart',
1403 + 'onPressChange',
1404 + 'onPressMove',
1405 + 'onPressEnd',
1406 + 'onPressChange',
1407 + 'onPress',
1408 + ]);
1409 + });
1410 +
1411 + it('delay and "onPressMove" is called before "onPress*" events', () => {
1412 + let events = [];
1413 + const ref = React.createRef();
1414 + const createEventHandler = msg => () => {
1415 + events.push(msg);
1416 + };
1417 +
1418 + const element = (
1419 + <Press
1420 + delayPressStart={500}
1421 + onPress={createEventHandler('onPress')}
1422 + onPressChange={createEventHandler('onPressChange')}
1423 + onPressMove={createEventHandler('onPressMove')}
1424 + onPressStart={createEventHandler('onPressStart')}
1425 + onPressEnd={createEventHandler('onPressEnd')}>
1426 + <div ref={ref} />
1427 + </Press>
1428 + );
1429 +
1430 + ReactDOM.render(element, container);
1431 +
1432 + ref.current.getBoundingClientRect = getBoundingClientRectMock;
1433 + ref.current.dispatchEvent(createEvent('touchstart'));
1434 + ref.current.dispatchEvent(createEvent('touchmove', coordinatesInside));
1435 + jest.advanceTimersByTime(499);
1436 + expect(events).toEqual(['onPressMove']);
1437 + events = [];
1438 +
1439 + jest.advanceTimersByTime(1);
1440 + expect(events).toEqual(['onPressStart', 'onPressChange']);
1441 + events = [];
1442 +
1443 + ref.current.dispatchEvent(createEvent('touchend', coordinatesInside));
1444 + expect(events).toEqual(['onPressEnd', 'onPressChange', 'onPress']);
1445 + });
1446 +
1447 + it('press retention offset can be configured', () => {
1448 + let events = [];
1449 + const ref = React.createRef();
1450 + const createEventHandler = msg => () => {
1451 + events.push(msg);
1452 + };
1453 + const pressRetentionOffset = {top: 40, bottom: 40, left: 40, right: 40};
1454 +
1455 + const element = (
1456 + <Press
1457 + pressRetentionOffset={pressRetentionOffset}
1458 + onPress={createEventHandler('onPress')}
1459 + onPressChange={createEventHandler('onPressChange')}
1460 + onPressMove={createEventHandler('onPressMove')}
1461 + onPressStart={createEventHandler('onPressStart')}
1462 + onPressEnd={createEventHandler('onPressEnd')}>
1463 + <div ref={ref} />
1464 + </Press>
1465 + );
1466 +
1467 + ReactDOM.render(element, container);
1468 + ref.current.getBoundingClientRect = getBoundingClientRectMock;
1469 + ref.current.dispatchEvent(createEvent('touchstart'));
1470 + ref.current.dispatchEvent(
1471 + createEvent('touchmove', {
1472 + pageX: rectMock.left - pressRetentionOffset.left,
1473 + pageY: rectMock.top - pressRetentionOffset.top,
1474 + }),
1475 + );
1476 + ref.current.dispatchEvent(createEvent('touchend', coordinatesInside));
1477 + expect(events).toEqual([
1478 + 'onPressStart',
1479 + 'onPressChange',
1480 + 'onPressMove',
1481 + 'onPressEnd',
1482 + 'onPressChange',
1483 + 'onPress',
1484 + ]);
1485 + });
1486 +
1487 + it('responder region accounts for decrease in element dimensions', () => {
1488 + let events = [];
1489 + const ref = React.createRef();
1490 + const createEventHandler = msg => () => {
1491 + events.push(msg);
1492 + };
1493 +
1494 + const element = (
1495 + <Press
1496 + onPress={createEventHandler('onPress')}
1497 + onPressStart={createEventHandler('onPressStart')}
1498 + onPressEnd={createEventHandler('onPressEnd')}>
1499 + <div ref={ref} />
1500 + </Press>
1501 + );
1502 +
1503 + ReactDOM.render(element, container);
1504 + ref.current.getBoundingClientRect = getBoundingClientRectMock;
1505 + ref.current.dispatchEvent(createEvent('touchstart'));
1506 + // emulate smaller dimensions change on activation
1507 + ref.current.getBoundingClientRect = () => ({
1508 + width: 80,
1509 + height: 80,
1510 + top: 60,
1511 + left: 60,
1512 + right: 490,
1513 + bottom: 490,
1514 + });
1515 + const coordinates = {
1516 + pageX: rectMock.left,
1517 + pageY: rectMock.top,
1518 + };
1519 + // move to an area within the pre-activation region
1520 + ref.current.dispatchEvent(createEvent('touchmove', coordinates));
1521 + ref.current.dispatchEvent(createEvent('touchend', coordinates));
1522 + expect(events).toEqual(['onPressStart', 'onPressEnd', 'onPress']);
1523 + });
1524 +
1525 + it('responder region accounts for increase in element dimensions', () => {
1526 + let events = [];
1527 + const ref = React.createRef();
1528 + const createEventHandler = msg => () => {
1529 + events.push(msg);
1530 + };
1531 +
1532 + const element = (
1533 + <Press
1534 + onPress={createEventHandler('onPress')}
1535 + onPressStart={createEventHandler('onPressStart')}
1536 + onPressEnd={createEventHandler('onPressEnd')}>
1537 + <div ref={ref} />
1538 + </Press>
1539 + );
1540 +
1541 + ReactDOM.render(element, container);
1542 + ref.current.getBoundingClientRect = getBoundingClientRectMock;
1543 + ref.current.dispatchEvent(createEvent('touchstart'));
1544 + // emulate larger dimensions change on activation
1545 + ref.current.getBoundingClientRect = () => ({
1546 + width: 200,
1547 + height: 200,
1548 + top: 0,
1549 + left: 0,
1550 + right: 550,
1551 + bottom: 550,
1552 + });
1553 + const coordinates = {
1554 + pageX: rectMock.left - 50,
1555 + pageY: rectMock.top - 50,
1556 + };
1557 + // move to an area within the post-activation region
1558 + ref.current.dispatchEvent(createEvent('touchmove', coordinates));
1559 + ref.current.dispatchEvent(createEvent('touchend', coordinates));
1560 + expect(events).toEqual(['onPressStart', 'onPressEnd', 'onPress']);
1561 + });
1562 + });
1563 +
1564 + describe('beyond bounds of hit rect', () => {
1565 + /** ┌──────────────────┐
1566 + * │ ┌────────────┐ │
1567 + * │ │ VisualRect │ │
1568 + * │ └────────────┘ │
1569 + * │ HitRect │
1570 + * └──────────────────┘
1571 + * X <= Move to X and release
1572 + */
1573 +
1574 + it('"onPress" is not called on release', () => {
1575 + let events = [];
1576 + const ref = React.createRef();
1577 + const createEventHandler = msg => () => {
1578 + events.push(msg);
1579 + };
1580 +
1581 + const element = (
1582 + <Press
1583 + onPress={createEventHandler('onPress')}
1584 + onPressChange={createEventHandler('onPressChange')}
1585 + onPressMove={createEventHandler('onPressMove')}
1586 + onPressStart={createEventHandler('onPressStart')}
1587 + onPressEnd={createEventHandler('onPressEnd')}>
1588 + <div ref={ref} />
1589 + </Press>
1590 + );
1591 +
1592 + ReactDOM.render(element, container);
1593 +
1594 + ref.current.getBoundingClientRect = getBoundingClientRectMock;
1595 + ref.current.dispatchEvent(createEvent('touchstart'));
1596 + ref.current.dispatchEvent(createEvent('touchmove', coordinatesInside));
1597 + container.dispatchEvent(createEvent('touchmove', coordinatesOutside));
1598 + container.dispatchEvent(createEvent('touchend', coordinatesOutside));
1599 + jest.runAllTimers();
1600 +
1601 + expect(events).toEqual([
1602 + 'onPressStart',
1603 + 'onPressChange',
1604 + 'onPressMove',
1605 + 'onPressEnd',
1606 + 'onPressChange',
1607 + ]);
1608 + });
1609 +
1610 + it('"onPress*" events are not called after delay expires', () => {
1611 + let events = [];
1612 + const ref = React.createRef();
1613 + const createEventHandler = msg => () => {
1614 + events.push(msg);
1615 + };
1616 +
1617 + const element = (
1618 + <Press
1619 + delayPressStart={500}
1620 + delayPressEnd={500}
1621 + onLongPress={createEventHandler('onLongPress')}
1622 + onPress={createEventHandler('onPress')}
1623 + onPressChange={createEventHandler('onPressChange')}
1624 + onPressMove={createEventHandler('onPressMove')}
1625 + onPressStart={createEventHandler('onPressStart')}
1626 + onPressEnd={createEventHandler('onPressEnd')}>
1627 + <div ref={ref} />
1628 + </Press>
1629 + );
1630 +
1631 + ReactDOM.render(element, container);
1632 +
1633 + ref.current.getBoundingClientRect = getBoundingClientRectMock;
1634 + ref.current.dispatchEvent(createEvent('touchstart'));
1635 + ref.current.dispatchEvent(createEvent('touchmove', coordinatesInside));
1636 + container.dispatchEvent(createEvent('touchmove', coordinatesOutside));
1637 + jest.runAllTimers();
1638 + expect(events).toEqual(['onPressMove']);
1639 + events = [];
1640 + container.dispatchEvent(createEvent('touchend', coordinatesOutside));
1641 + jest.runAllTimers();
1642 + expect(events).toEqual([]);
1643 + });
1644 + });
1645 +
1646 + it('"onPress" is called on re-entry to hit rect for touch', () => {
1647 + let events = [];
1648 + const ref = React.createRef();
1649 + const createEventHandler = msg => () => {
1650 + events.push(msg);
1651 + };
1652 +
1653 + const element = (
1654 + <Press
1655 + onPress={createEventHandler('onPress')}
1656 + onPressChange={createEventHandler('onPressChange')}
1657 + onPressMove={createEventHandler('onPressMove')}
1658 + onPressStart={createEventHandler('onPressStart')}
1659 + onPressEnd={createEventHandler('onPressEnd')}>
1660 + <div ref={ref} />
1661 + </Press>
1662 + );
1663 +
1664 + ReactDOM.render(element, container);
1665 +
1666 + ref.current.getBoundingClientRect = getBoundingClientRectMock;
1667 + ref.current.dispatchEvent(
1668 + createEvent('touchstart', {
1669 pointerType: 'touch',
1670 }),
1671 );
1672 ref.current.dispatchEvent(
1317 - createPointerEvent('pointermove', {
1673 + createEvent('touchmove', {
1674 ...coordinatesInside,
1675 pointerType: 'touch',
1676 }),
1677 );
1678 container.dispatchEvent(
1323 - createPointerEvent('pointermove', {
1679 + createEvent('touchmove', {
1680 ...coordinatesOutside,
1681 pointerType: 'touch',
1682 }),
1683 );
1684 container.dispatchEvent(
1329 - createPointerEvent('pointermove', {
1685 + createEvent('touchmove', {
1686 ...coordinatesInside,
1687 pointerType: 'touch',
1688 }),
1689 );
1690 container.dispatchEvent(
1335 - createPointerEvent('pointerup', {
1691 + createEvent('touchend', {
1692 ...coordinatesInside,
1693 pointerType: 'touch',
1694 }),
@@ -1386,13 +1742,13 @@ describe('Event responder: Press', () => {
1742
1743 // 1
1744 events = [];
1389 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1745 + ref.current.dispatchEvent(createEvent('pointerdown'));
1746 ref.current.dispatchEvent(
1391 - createPointerEvent('pointerup', {pageX: 10, pageY: 10}),
1747 + createEvent('pointerup', {pageX: 10, pageY: 10}),
1748 );
1393 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1749 + ref.current.dispatchEvent(createEvent('pointerdown'));
1750 ref.current.dispatchEvent(
1395 - createPointerEvent('pointerup', {pageX: 10, pageY: 10}),
1751 + createEvent('pointerup', {pageX: 10, pageY: 10}),
1752 );
1753 jest.runAllTimers();
1754
@@ -1408,11 +1764,11 @@ describe('Event responder: Press', () => {
1764
1765 // 2
1766 events = [];
1411 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1767 + ref.current.dispatchEvent(createEvent('pointerdown'));
1768 jest.advanceTimersByTime(250);
1769 jest.advanceTimersByTime(500);
1770 ref.current.dispatchEvent(
1415 - createPointerEvent('pointerup', {pageX: 10, pageY: 10}),
1771 + createEvent('pointerup', {pageX: 10, pageY: 10}),
1772 );
1773 jest.runAllTimers();
1774
@@ -1468,9 +1824,9 @@ describe('Event responder: Press', () => {
1824 right: 0,
1825 });
1826
1471 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1827 + ref.current.dispatchEvent(createEvent('pointerdown'));
1828 ref.current.dispatchEvent(
1473 - createPointerEvent('pointerup', {pageX: 10, pageY: 10}),
1829 + createEvent('pointerup', {pageX: 10, pageY: 10}),
1830 );
1831 expect(events).toEqual([
1832 'inner: onPressStart',
@@ -1502,9 +1858,9 @@ describe('Event responder: Press', () => {
1858 right: 0,
1859 });
1860
1505 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1861 + ref.current.dispatchEvent(createEvent('pointerdown'));
1862 ref.current.dispatchEvent(
1507 - createPointerEvent('pointerup', {pageX: 10, pageY: 10}),
1863 + createEvent('pointerup', {pageX: 10, pageY: 10}),
1864 );
1865 expect(fn).toHaveBeenCalledTimes(1);
1866 });
@@ -1521,9 +1877,9 @@ describe('Event responder: Press', () => {
1877 );
1878 ReactDOM.render(element, container);
1879
1524 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1880 + ref.current.dispatchEvent(createEvent('pointerdown'));
1881 jest.advanceTimersByTime(DEFAULT_LONG_PRESS_DELAY);
1526 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
1882 + ref.current.dispatchEvent(createEvent('pointerup'));
1883 expect(fn).toHaveBeenCalledTimes(1);
1884 });
1885
@@ -1540,10 +1896,10 @@ describe('Event responder: Press', () => {
1896 );
1897 ReactDOM.render(element, container);
1898
1543 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1899 + ref.current.dispatchEvent(createEvent('pointerdown'));
1900 expect(fn).toHaveBeenCalledTimes(1);
1901 expect(fn2).toHaveBeenCalledTimes(0);
1546 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
1902 + ref.current.dispatchEvent(createEvent('pointerup'));
1903 expect(fn).toHaveBeenCalledTimes(1);
1904 expect(fn2).toHaveBeenCalledTimes(1);
1905 });
@@ -1560,9 +1916,9 @@ describe('Event responder: Press', () => {
1916 );
1917 ReactDOM.render(element, container);
1918
1563 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1919 + ref.current.dispatchEvent(createEvent('pointerdown'));
1920 expect(fn).toHaveBeenCalledTimes(1);
1565 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
1921 + ref.current.dispatchEvent(createEvent('pointerup'));
1922 expect(fn).toHaveBeenCalledTimes(2);
1923 });
1924 });
@@ -1580,9 +1936,9 @@ describe('Event responder: Press', () => {
1936 );
1937 ReactDOM.render(element, container);
1938
1583 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1584 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
1585 - ref.current.dispatchEvent(createPointerEvent('click', {preventDefault}));
1939 + ref.current.dispatchEvent(createEvent('pointerdown'));
1940 + ref.current.dispatchEvent(createEvent('pointerup'));
1941 + ref.current.dispatchEvent(createEvent('click', {preventDefault}));
1942 expect(preventDefault).toBeCalled();
1943 });
1944
@@ -1599,13 +1955,13 @@ describe('Event responder: Press', () => {
1955
1956 ['metaKey', 'ctrlKey', 'shiftKey'].forEach(modifierKey => {
1957 ref.current.dispatchEvent(
1602 - createPointerEvent('pointerdown', {[modifierKey]: true}),
1958 + createEvent('pointerdown', {[modifierKey]: true}),
1959 );
1960 ref.current.dispatchEvent(
1605 - createPointerEvent('pointerup', {[modifierKey]: true}),
1961 + createEvent('pointerup', {[modifierKey]: true}),
1962 );
1963 ref.current.dispatchEvent(
1608 - createPointerEvent('click', {[modifierKey]: true, preventDefault}),
1964 + createEvent('click', {[modifierKey]: true, preventDefault}),
1965 );
1966 expect(preventDefault).not.toBeCalled();
1967 });
@@ -1622,9 +1978,9 @@ describe('Event responder: Press', () => {
1978 );
1979 ReactDOM.render(element, container);
1980
1625 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1626 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
1627 - ref.current.dispatchEvent(createPointerEvent('click', {preventDefault}));
1981 + ref.current.dispatchEvent(createEvent('pointerdown'));
1982 + ref.current.dispatchEvent(createEvent('pointerup'));
1983 + ref.current.dispatchEvent(createEvent('click', {preventDefault}));
1984 expect(preventDefault).not.toBeCalled();
1985 });
1986 });
@@ -1641,8 +1997,8 @@ describe('Event responder: Press', () => {
1997 );
1998 ReactDOM.render(element, container);
1999
1644 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1645 - ref.current.dispatchEvent(createPointerEvent('scroll'));
2000 + ref.current.dispatchEvent(createEvent('pointerdown'));
2001 + ref.current.dispatchEvent(createEvent('scroll'));
2002 expect(onPressEnd).toHaveBeenCalledTimes(1);
2003 jest.runAllTimers();
2004 expect(onLongPress).not.toBeCalled();
@@ -1651,8 +2007,8 @@ describe('Event responder: Press', () => {
2007 onPressEnd.mockReset();
2008
2009 // When pointer events are supported
1654 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
1655 - ref.current.dispatchEvent(createPointerEvent('pointercancel'));
2010 + ref.current.dispatchEvent(createEvent('pointerdown'));
2011 + ref.current.dispatchEvent(createEvent('pointercancel'));
2012 expect(onPressEnd).toHaveBeenCalledTimes(1);
2013 jest.runAllTimers();
2014 expect(onLongPress).not.toBeCalled();
@@ -1661,8 +2017,8 @@ describe('Event responder: Press', () => {
2017 onPressEnd.mockReset();
2018
2019 // Touch fallback
1664 - ref.current.dispatchEvent(createPointerEvent('touchstart'));
1665 - ref.current.dispatchEvent(createPointerEvent('touchcancel'));
2020 + ref.current.dispatchEvent(createEvent('touchstart'));
2021 + ref.current.dispatchEvent(createEvent('touchcancel'));
2022 expect(onPressEnd).toHaveBeenCalledTimes(1);
2023 jest.runAllTimers();
2024 expect(onLongPress).not.toBeCalled();
@@ -1671,8 +2027,8 @@ describe('Event responder: Press', () => {
2027 onPressEnd.mockReset();
2028
2029 // Mouse fallback
1674 - ref.current.dispatchEvent(createPointerEvent('mousedown'));
1675 - ref.current.dispatchEvent(createPointerEvent('dragstart'));
2030 + ref.current.dispatchEvent(createEvent('mousedown'));
2031 + ref.current.dispatchEvent(createEvent('dragstart'));
2032 expect(onPressEnd).toHaveBeenCalledTimes(1);
2033 jest.runAllTimers();
2034 expect(onLongPress).not.toBeCalled();
@@ -1692,11 +2048,11 @@ describe('Event responder: Press', () => {
2048 );
2049 ReactDOM.render(element, container);
2050
1695 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
2051 + ref.current.dispatchEvent(createEvent('pointerdown'));
2052 jest.advanceTimersByTime(DEFAULT_LONG_PRESS_DELAY);
1697 - ref.current.dispatchEvent(createPointerEvent('pointermove'));
1698 - ref.current.dispatchEvent(createPointerEvent('pointerup'));
1699 - ref.current.dispatchEvent(createPointerEvent('pointerdown'));
2053 + ref.current.dispatchEvent(createEvent('pointermove'));
2054 + ref.current.dispatchEvent(createEvent('pointerup'));
2055 + ref.current.dispatchEvent(createEvent('pointerdown'));
2056 ReactDOM.render(element, container);
2057 });
2058 });