@samitouri / QOS-React-2 / commits / a5e951d4cc

[react-interactions] Event testing library improvements (#17614)

Introduces a state machine around pointer events to produce more accurate mock touch events. This allows multi-touch unit tests to be written entirely in terms of mock pointer interactions, while producing the expected 'changedTouches', 'targetTouches', and 'touches' fields for mock touch events.

Nicolas Gallagher committed Dec 18, 2019 at 23:32 UTC a5e951d4cc75583084c91d7eb0332831e15bfbc0
23 files changed +631 -456
packages/react-interactions/accessibility/src/__tests__/FocusContain-test.internal.js
+34 -24
@@ -7,13 +7,23 @@
7 * @flow
8 */
9
10 -import {createEventTarget} from 'react-interactions/events/src/dom/testing-library';
10 +import {createEventTarget} from 'react-interactions/events/src/dom/event-testing-library';
11
12 let React;
13 let ReactFeatureFlags;
14 let FocusContain;
15 let tabbableScopeQuery;
16
17 +function tabNext(target) {
18 + target.keydown({key: 'Tab'});
19 + target.keyup({key: 'Tab'});
20 +}
21 +
22 +function tabPrevious(target) {
23 + target.keydown({key: 'Tab', shiftKey: true});
24 + target.keyup({key: 'Tab', shiftKey: true});
25 +}
26 +
27 describe('FocusContain', () => {
28 beforeEach(() => {
29 jest.resetModules();
@@ -59,13 +69,13 @@ describe('FocusContain', () => {
69
70 ReactDOM.render(<Test />, container);
71 expect(document.activeElement).toBe(inputRef.current);
62 - createEventTarget(document.activeElement).tabNext();
72 + tabNext(createEventTarget(document.activeElement));
73 expect(document.activeElement).toBe(buttonRef.current);
64 - createEventTarget(document.activeElement).tabNext();
74 + tabNext(createEventTarget(document.activeElement));
75 expect(document.activeElement).toBe(divRef.current);
66 - createEventTarget(document.activeElement).tabNext();
76 + tabNext(createEventTarget(document.activeElement));
77 expect(document.activeElement).toBe(button2Ref.current);
68 - createEventTarget(document.activeElement).tabPrevious();
78 + tabPrevious(createEventTarget(document.activeElement));
79 expect(document.activeElement).toBe(divRef.current);
80 });
81
@@ -90,15 +100,15 @@ describe('FocusContain', () => {
100
101 ReactDOM.render(<Test />, container);
102 buttonRef.current.focus();
93 - createEventTarget(document.activeElement).tabNext();
103 + tabNext(createEventTarget(document.activeElement));
104 expect(document.activeElement).toBe(button2Ref.current);
95 - createEventTarget(document.activeElement).tabNext();
105 + tabNext(createEventTarget(document.activeElement));
106 expect(document.activeElement).toBe(buttonRef.current);
97 - createEventTarget(document.activeElement).tabNext();
107 + tabNext(createEventTarget(document.activeElement));
108 expect(document.activeElement).toBe(button2Ref.current);
99 - createEventTarget(document.activeElement).tabPrevious();
109 + tabPrevious(createEventTarget(document.activeElement));
110 expect(document.activeElement).toBe(buttonRef.current);
101 - createEventTarget(document.activeElement).tabPrevious();
111 + tabPrevious(createEventTarget(document.activeElement));
112 expect(document.activeElement).toBe(button2Ref.current);
113 // Focus should be restored to the contained area
114 const rAF = window.requestAnimationFrame;
@@ -132,15 +142,15 @@ describe('FocusContain', () => {
142
143 ReactDOM.render(<Test />, container);
144 expect(document.activeElement).toBe(buttonRef.current);
135 - createEventTarget(document.activeElement).tabNext();
145 + tabNext(createEventTarget(document.activeElement));
146 expect(document.activeElement).toBe(button2Ref.current);
137 - createEventTarget(document.activeElement).tabNext();
147 + tabNext(createEventTarget(document.activeElement));
148 expect(document.activeElement).toBe(button3Ref.current);
139 - createEventTarget(document.activeElement).tabNext();
149 + tabNext(createEventTarget(document.activeElement));
150 expect(document.activeElement).toBe(button4Ref.current);
141 - createEventTarget(document.activeElement).tabPrevious();
151 + tabPrevious(createEventTarget(document.activeElement));
152 expect(document.activeElement).toBe(button3Ref.current);
143 - createEventTarget(document.activeElement).tabPrevious();
153 + tabPrevious(createEventTarget(document.activeElement));
154 expect(document.activeElement).toBe(button2Ref.current);
155 });
156
@@ -167,13 +177,13 @@ describe('FocusContain', () => {
177
178 ReactDOM.render(<Test />, container);
179 expect(document.activeElement).toBe(button2Ref.current);
170 - createEventTarget(document.activeElement).tabNext();
180 + tabNext(createEventTarget(document.activeElement));
181 expect(document.activeElement).toBe(button3Ref.current);
172 - createEventTarget(document.activeElement).tabNext();
182 + tabNext(createEventTarget(document.activeElement));
183 expect(document.activeElement).toBe(button2Ref.current);
174 - createEventTarget(document.activeElement).tabPrevious();
184 + tabPrevious(createEventTarget(document.activeElement));
185 expect(document.activeElement).toBe(button3Ref.current);
176 - createEventTarget(document.activeElement).tabPrevious();
186 + tabPrevious(createEventTarget(document.activeElement));
187 expect(document.activeElement).toBe(button2Ref.current);
188 });
189
@@ -213,15 +223,15 @@ describe('FocusContain', () => {
223 ReactDOM.render(<Test />, container);
224 buttonRef.current.focus();
225 expect(document.activeElement).toBe(buttonRef.current);
216 - createEventTarget(document.activeElement).tabNext();
226 + tabNext(createEventTarget(document.activeElement));
227 expect(document.activeElement).toBe(button2Ref.current);
218 - createEventTarget(document.activeElement).tabNext();
228 + tabNext(createEventTarget(document.activeElement));
229 expect(document.activeElement).toBe(button3Ref.current);
220 - createEventTarget(document.activeElement).tabNext();
230 + tabNext(createEventTarget(document.activeElement));
231 expect(document.activeElement).toBe(button4Ref.current);
222 - createEventTarget(document.activeElement).tabPrevious();
232 + tabPrevious(createEventTarget(document.activeElement));
233 expect(document.activeElement).toBe(button3Ref.current);
224 - createEventTarget(document.activeElement).tabPrevious();
234 + tabPrevious(createEventTarget(document.activeElement));
235 expect(document.activeElement).toBe(button2Ref.current);
236 });
237 });
packages/react-interactions/accessibility/src/__tests__/FocusGroup-test.internal.js
+1 -1
@@ -7,7 +7,7 @@
7 * @flow
8 */
9
10 -import {createEventTarget} from 'react-interactions/events/src/dom/testing-library';
10 +import {createEventTarget} from 'react-interactions/events/src/dom/event-testing-library';
11 import {emulateBrowserTab} from '../shared/emulateBrowserTab';
12
13 let React;
packages/react-interactions/accessibility/src/__tests__/FocusTable-test.internal.js
+1 -1
@@ -7,7 +7,7 @@
7 * @flow
8 */
9
10 -import {createEventTarget} from 'react-interactions/events/src/dom/testing-library';
10 +import {createEventTarget} from 'react-interactions/events/src/dom/event-testing-library';
11 import {emulateBrowserTab} from '../shared/emulateBrowserTab';
12
13 let React;
packages/react-interactions/accessibility/src/shared/emulateBrowserTab.js
+1 -1
@@ -9,7 +9,7 @@
9
10 'use strict';
11
12 -import {createEventTarget} from 'react-interactions/events/src/dom/testing-library';
12 +import {createEventTarget} from 'react-interactions/events/src/dom/event-testing-library';
13
14 // This function is used by the a11y modules for testing
15 export function emulateBrowserTab(backwards: boolean): void {
packages/react-interactions/events/src/dom/__tests__/ContextMenu-test.internal.js
+1 -1
@@ -14,7 +14,7 @@ import {
14 createEventTarget,
15 platform,
16 setPointerEvent,
17 -} from '../testing-library';
17 +} from '../event-testing-library';
18
19 let React;
20 let ReactFeatureFlags;
packages/react-interactions/events/src/dom/__tests__/Focus-test.internal.js
+5 -1
@@ -9,7 +9,11 @@
9
10 'use strict';
11
12 -import {createEventTarget, setPointerEvent, platform} from '../testing-library';
12 +import {
13 + createEventTarget,
14 + setPointerEvent,
15 + platform,
16 +} from '../event-testing-library';
17
18 let React;
19 let ReactFeatureFlags;
packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js
+1 -1
@@ -9,7 +9,7 @@
9
10 'use strict';
11
12 -import {createEventTarget, setPointerEvent} from '../testing-library';
12 +import {createEventTarget, setPointerEvent} from '../event-testing-library';
13
14 let React;
15 let ReactFeatureFlags;
packages/react-interactions/events/src/dom/__tests__/Hover-test.internal.js
+1 -1
@@ -9,7 +9,7 @@
9
10 'use strict';
11
12 -import {createEventTarget, setPointerEvent} from '../testing-library';
12 +import {createEventTarget, setPointerEvent} from '../event-testing-library';
13
14 let React;
15 let ReactFeatureFlags;
packages/react-interactions/events/src/dom/__tests__/Keyboard-test.internal.js
+1 -1
@@ -14,7 +14,7 @@ let ReactFeatureFlags;
14 let ReactDOM;
15 let useKeyboard;
16
17 -import {createEventTarget} from '../testing-library';
17 +import {createEventTarget} from '../event-testing-library';
18
19 function initializeModules(hasPointerEvents) {
20 jest.resetModules();
packages/react-interactions/events/src/dom/__tests__/MixedResponders-test-internal.js
+1 -1
@@ -9,7 +9,7 @@
9
10 'use strict';
11
12 -import {createEventTarget} from '../testing-library';
12 +import {createEventTarget} from '../event-testing-library';
13
14 let React;
15 let ReactFeatureFlags;
packages/react-interactions/events/src/dom/__tests__/Press-test.internal.js
+3 -1
@@ -14,8 +14,9 @@ import {
14 buttonsType,
15 createEventTarget,
16 describeWithPointerEvent,
17 + resetActivePointers,
18 setPointerEvent,
18 -} from '../testing-library';
19 +} from '../event-testing-library';
20
21 let React;
22 let ReactFeatureFlags;
@@ -47,6 +48,7 @@ describeWithPointerEvent('Press responder', hasPointerEvents => {
48 ReactDOM.render(null, container);
49 document.body.removeChild(container);
50 container = null;
51 + resetActivePointers();
52 });
53
54 describe('disabled', () => {
packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js
+3 -1
@@ -13,8 +13,9 @@ import {
13 buttonType,
14 buttonsType,
15 createEventTarget,
16 + resetActivePointers,
17 setPointerEvent,
17 -} from '../testing-library';
18 +} from '../event-testing-library';
19
20 let React;
21 let ReactFeatureFlags;
@@ -59,6 +60,7 @@ describe.each(environmentTable)('Press responder', hasPointerEvents => {
60 ReactDOM.render(null, container);
61 document.body.removeChild(container);
62 container = null;
63 + resetActivePointers();
64 });
65
66 describe('disabled', () => {
packages/react-interactions/events/src/dom/__tests__/Scroll-test.internal.js
+1 -1
@@ -9,7 +9,7 @@
9
10 'use strict';
11
12 -import {createEventTarget, setPointerEvent} from '../testing-library';
12 +import {createEventTarget, setPointerEvent} from '../event-testing-library';
13
14 let React;
15 let ReactFeatureFlags;
packages/react-interactions/events/src/dom/__tests__/Tap-test.internal.js
+17 -23
@@ -16,7 +16,8 @@ import {
16 describeWithPointerEvent,
17 setPointerEvent,
18 testWithPointerType,
19 -} from '../testing-library';
19 + resetActivePointers,
20 +} from '../event-testing-library';
21
22 let React;
23 let ReactFeatureFlags;
@@ -82,6 +83,7 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
83 ReactDOM.render(null, container);
84 document.body.removeChild(container);
85 container = null;
86 + resetActivePointers();
87 });
88
89 test('supports repeated use', () => {
@@ -295,12 +297,7 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
297 const buttons = buttonsType.primary;
298 target.pointerdown({button, buttons, pointerId: 1, pointerType});
299 expect(onTapStart).toHaveBeenCalledTimes(1);
298 - if (hasPointerEvents) {
299 - target.pointerdown({button, buttons, pointerId: 2, pointerType});
300 - } else {
301 - // TouchEvents
302 - target.pointerdown([{pointerId: 1}, {pointerId: 2}]);
303 - }
300 + target.pointerdown({button, buttons, pointerId: 2, pointerType});
301 expect(onTapStart).toHaveBeenCalledTimes(1);
302 });
303
@@ -313,28 +310,28 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
310 buttons: buttonsType.secondary,
311 pointerType,
312 });
316 - target.pointerup();
313 + target.pointerup({pointerType});
314 // middle-click
315 target.pointerdown({
316 button: buttonType.auxiliary,
317 buttons: buttonsType.auxiliary,
318 pointerType,
319 });
323 - target.pointerup();
320 + target.pointerup({pointerType});
321 // virtual middle-click with misleading 'buttons' value
322 target.pointerdown({
323 button: buttonType.auxiliary,
324 buttons: 0,
325 pointerType,
326 });
330 - target.pointerup();
327 + target.pointerup({pointerType});
328 // pen eraser
329 target.pointerdown({
330 button: buttonType.eraser,
331 buttons: buttonsType.eraser,
332 pointerType,
333 });
337 - target.pointerup();
334 + target.pointerup({pointerType});
335 }
336 // alt-click
337 target.pointerdown({
@@ -343,7 +340,7 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
340 altKey: true,
341 pointerType,
342 });
346 - target.pointerup();
343 + target.pointerup({pointerType});
344 // ctrl-click
345 target.pointerdown({
346 button: buttonType.primary,
@@ -351,7 +348,7 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
348 ctrlKey: true,
349 pointerType,
350 });
354 - target.pointerup();
351 + target.pointerup({pointerType});
352 // meta-click
353 target.pointerdown({
354 button: buttonType.primary,
@@ -359,7 +356,7 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
356 metaKey: true,
357 pointerType,
358 });
362 - target.pointerup();
359 + target.pointerup({pointerType});
360 // shift-click
361 target.pointerdown({
362 button: buttonType.primary,
@@ -367,7 +364,7 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
364 shiftKey: true,
365 pointerType,
366 });
370 - target.pointerup();
367 + target.pointerup({pointerType});
368
369 expect(onTapStart).toHaveBeenCalledTimes(0);
370 });
@@ -565,8 +562,10 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
562 testWithPointerType('requires activation', pointerType => {
563 const target = createEventTarget(ref.current);
564 target.setBoundingClientRect(rect);
568 - target.pointerhover({pointerType, ...coordinates});
569 - target.pointermove({pointerType, ...coordinates});
565 + if (pointerType !== 'touch') {
566 + target.pointerhover({pointerType, ...coordinates});
567 + target.pointermove({pointerType, ...coordinates});
568 + }
569 expect(onTapUpdate).not.toBeCalled();
570 });
571
@@ -771,12 +770,7 @@ describeWithPointerEvent('Tap responder', hasPointerEvents => {
770 const button = buttonType.primary;
771 const buttons = buttonsType.primary;
772 target.pointerdown({button, buttons, pointerId: 1, pointerType});
774 - if (hasPointerEvents) {
775 - target.pointerdown({button, buttons, pointerId: 2, pointerType});
776 - } else {
777 - // TouchEvents
778 - target.pointerdown([{pointerId: 1}, {pointerId: 2}]);
779 - }
773 + target.pointerdown({button, buttons, pointerId: 2, pointerType});
774 expect(onTapCancel).toHaveBeenCalledTimes(1);
775 });
776
packages/react-interactions/events/src/dom/event-testing-library/constants.js new
+65
@@ -0,0 +1,65 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @emails react-core
8 + */
9 +
10 +'use strict';
11 +
12 +export const defaultPointerId = 1;
13 +export const defaultPointerSize = 23;
14 +export const defaultBrowserChromeSize = 50;
15 +
16 +/**
17 + * Button property
18 + * This property only guarantees to indicate which buttons are pressed during events caused by pressing or
19 + * releasing one or multiple buttons. As such, it is not reliable for events such as 'mouseenter', 'mouseleave',
20 + * 'mouseover', 'mouseout' or 'mousemove'. Furthermore, the semantics differ for PointerEvent, where the value
21 + * for 'pointermove' will always be -1.
22 + */
23 +
24 +export const buttonType = {
25 + // no change since last event
26 + none: -1,
27 + // left-mouse
28 + // touch contact
29 + // pen contact
30 + primary: 0,
31 + // right-mouse
32 + // pen barrel button
33 + secondary: 2,
34 + // middle mouse
35 + auxiliary: 1,
36 + // back mouse
37 + back: 3,
38 + // forward mouse
39 + forward: 4,
40 + // pen eraser
41 + eraser: 5,
42 +};
43 +
44 +/**
45 + * Buttons bitmask
46 + */
47 +
48 +export const buttonsType = {
49 + none: 0,
50 + // left-mouse
51 + // touch contact
52 + // pen contact
53 + primary: 1,
54 + // right-mouse
55 + // pen barrel button
56 + secondary: 2,
57 + // middle mouse
58 + auxiliary: 4,
59 + // back mouse
60 + back: 8,
61 + // forward mouse
62 + forward: 16,
63 + // pen eraser
64 + eraser: 32,
65 +};
packages/react-interactions/events/src/dom/event-testing-library/domEnvironment.js renamed
-51
@@ -65,54 +65,3 @@ export const platform = {
65 }
66 },
67 };
68 -
69 -/**
70 - * Button property
71 - * This property only guarantees to indicate which buttons are pressed during events caused by pressing or
72 - * releasing one or multiple buttons. As such, it is not reliable for events such as 'mouseenter', 'mouseleave',
73 - * 'mouseover', 'mouseout' or 'mousemove'. Furthermore, the semantics differ for PointerEvent, where the value
74 - * for 'pointermove' will always be -1.
75 - */
76 -
77 -export const buttonType = {
78 - // no change since last event
79 - none: -1,
80 - // left-mouse
81 - // touch contact
82 - // pen contact
83 - primary: 0,
84 - // right-mouse
85 - // pen barrel button
86 - secondary: 2,
87 - // middle mouse
88 - auxiliary: 1,
89 - // back mouse
90 - back: 3,
91 - // forward mouse
92 - forward: 4,
93 - // pen eraser
94 - eraser: 5,
95 -};
96 -
97 -/**
98 - * Buttons bitmask
99 - */
100 -
101 -export const buttonsType = {
102 - none: 0,
103 - // left-mouse
104 - // touch contact
105 - // pen contact
106 - primary: 1,
107 - // right-mouse
108 - // pen barrel button
109 - secondary: 2,
110 - // middle mouse
111 - auxiliary: 4,
112 - // back mouse
113 - back: 8,
114 - // forward mouse
115 - forward: 16,
116 - // pen eraser
117 - eraser: 32,
118 -};
packages/react-interactions/events/src/dom/event-testing-library/domEventSequences.js new
+361
@@ -0,0 +1,361 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @emails react-core
8 + */
9 +
10 +'use strict';
11 +
12 +import {
13 + buttonType,
14 + buttonsType,
15 + defaultPointerId,
16 + defaultPointerSize,
17 + defaultBrowserChromeSize,
18 +} from './constants';
19 +import * as domEvents from './domEvents';
20 +import {hasPointerEvent, platform} from './domEnvironment';
21 +import * as touchStore from './touchStore';
22 +
23 +/**
24 + * Converts a PointerEvent payload to a Touch
25 + */
26 +function createTouch(target, payload) {
27 + const {
28 + height = defaultPointerSize,
29 + pageX,
30 + pageY,
31 + pointerId,
32 + pressure = 1,
33 + twist = 0,
34 + width = defaultPointerSize,
35 + x = 0,
36 + y = 0,
37 + } = payload;
38 +
39 + return {
40 + clientX: x,
41 + clientY: y,
42 + force: pressure,
43 + identifier: pointerId,
44 + pageX: pageX || x,
45 + pageY: pageY || y,
46 + radiusX: width / 2,
47 + radiusY: height / 2,
48 + rotationAngle: twist,
49 + target,
50 + screenX: x,
51 + screenY: y + defaultBrowserChromeSize,
52 + };
53 +}
54 +
55 +/**
56 + * Converts a PointerEvent to a TouchEvent
57 + */
58 +function createTouchEventPayload(target, touch, payload) {
59 + const {
60 + altKey = false,
61 + ctrlKey = false,
62 + metaKey = false,
63 + preventDefault,
64 + shiftKey = false,
65 + timeStamp,
66 + } = payload;
67 +
68 + return {
69 + altKey,
70 + changedTouches: [touch],
71 + ctrlKey,
72 + metaKey,
73 + preventDefault,
74 + shiftKey,
75 + targetTouches: touchStore.getTargetTouches(target),
76 + timeStamp,
77 + touches: touchStore.getTouches(),
78 + };
79 +}
80 +
81 +function getPointerType(payload) {
82 + let pointerType = 'mouse';
83 + if (payload != null && payload.pointerType != null) {
84 + pointerType = payload.pointerType;
85 + }
86 + return pointerType;
87 +}
88 +
89 +/**
90 + * Pointer events sequences.
91 + *
92 + * Creates representative browser event sequences for high-level gestures based on pointers.
93 + * This allows unit tests to be written in terms of simple pointer interactions while testing
94 + * that the responses to those interactions account for the complex sequence of events that
95 + * browsers produce as a result.
96 + *
97 + * Every time a new pointer touches the surface a 'touchstart' event should be dispatched.
98 + * - 'changedTouches' contains the new touch.
99 + * - 'targetTouches' contains all the active pointers for the target.
100 + * - 'touches' contains all the active pointers on the surface.
101 + *
102 + * Every time an existing pointer moves a 'touchmove' event should be dispatched.
103 + * - 'changedTouches' contains the updated touch.
104 + *
105 + * Every time an existing pointer leaves the surface a 'touchend' event should be dispatched.
106 + * - 'changedTouches' contains the released touch.
107 + * - 'targetTouches' contains any of the remaining active pointers for the target.
108 + */
109 +
110 +export function contextmenu(
111 + target,
112 + defaultPayload,
113 + {pointerType = 'mouse', modified} = {},
114 +) {
115 + const dispatch = arg => target.dispatchEvent(arg);
116 +
117 + const payload = {
118 + pointerId: defaultPointerId,
119 + pointerType,
120 + ...defaultPayload,
121 + };
122 +
123 + const preventDefault = payload.preventDefault;
124 +
125 + if (pointerType === 'touch') {
126 + if (hasPointerEvent()) {
127 + dispatch(
128 + domEvents.pointerdown({
129 + ...payload,
130 + button: buttonType.primary,
131 + buttons: buttonsType.primary,
132 + }),
133 + );
134 + }
135 + const touch = createTouch(target, payload);
136 + touchStore.addTouch(touch);
137 + const touchEventPayload = createTouchEventPayload(target, touch, payload);
138 + dispatch(domEvents.touchstart(touchEventPayload));
139 + dispatch(
140 + domEvents.contextmenu({
141 + button: buttonType.primary,
142 + buttons: buttonsType.none,
143 + preventDefault,
144 + }),
145 + );
146 + touchStore.removeTouch(touch);
147 + } else if (pointerType === 'mouse') {
148 + if (modified === true) {
149 + const button = buttonType.primary;
150 + const buttons = buttonsType.primary;
151 + const ctrlKey = true;
152 + if (hasPointerEvent()) {
153 + dispatch(
154 + domEvents.pointerdown({button, buttons, ctrlKey, pointerType}),
155 + );
156 + }
157 + dispatch(domEvents.mousedown({button, buttons, ctrlKey}));
158 + if (platform.get() === 'mac') {
159 + dispatch(
160 + domEvents.contextmenu({button, buttons, ctrlKey, preventDefault}),
161 + );
162 + }
163 + } else {
164 + const button = buttonType.secondary;
165 + const buttons = buttonsType.secondary;
166 + if (hasPointerEvent()) {
167 + dispatch(domEvents.pointerdown({button, buttons, pointerType}));
168 + }
169 + dispatch(domEvents.mousedown({button, buttons}));
170 + dispatch(domEvents.contextmenu({button, buttons, preventDefault}));
171 + }
172 + }
173 +}
174 +
175 +export function pointercancel(target, defaultPayload) {
176 + const dispatchEvent = arg => target.dispatchEvent(arg);
177 + const pointerType = getPointerType(defaultPayload);
178 +
179 + const payload = {
180 + pointerId: defaultPointerId,
181 + pointerType,
182 + ...defaultPayload,
183 + };
184 +
185 + if (hasPointerEvent()) {
186 + dispatchEvent(domEvents.pointercancel(payload));
187 + } else {
188 + if (pointerType === 'mouse') {
189 + dispatchEvent(domEvents.dragstart(payload));
190 + } else {
191 + const touch = createTouch(target, payload);
192 + touchStore.removeTouch(touch);
193 + const touchEventPayload = createTouchEventPayload(target, touch, payload);
194 + dispatchEvent(domEvents.touchcancel(touchEventPayload));
195 + }
196 + }
197 +}
198 +
199 +export function pointerdown(target, defaultPayload) {
200 + const dispatch = arg => target.dispatchEvent(arg);
201 + const pointerType = getPointerType(defaultPayload);
202 +
203 + const payload = {
204 + button: buttonType.primary,
205 + buttons: buttonsType.primary,
206 + pointerId: defaultPointerId,
207 + pointerType,
208 + ...defaultPayload,
209 + };
210 +
211 + if (pointerType === 'mouse') {
212 + if (hasPointerEvent()) {
213 + dispatch(domEvents.pointerover(payload));
214 + dispatch(domEvents.pointerenter(payload));
215 + }
216 + dispatch(domEvents.mouseover(payload));
217 + dispatch(domEvents.mouseenter(payload));
218 + if (hasPointerEvent()) {
219 + dispatch(domEvents.pointerdown(payload));
220 + }
221 + dispatch(domEvents.mousedown(payload));
222 + if (document.activeElement !== target) {
223 + dispatch(domEvents.focus());
224 + }
225 + } else {
226 + if (hasPointerEvent()) {
227 + dispatch(domEvents.pointerover(payload));
228 + dispatch(domEvents.pointerenter(payload));
229 + dispatch(domEvents.pointerdown(payload));
230 + }
231 + const touch = createTouch(target, payload);
232 + touchStore.addTouch(touch);
233 + const touchEventPayload = createTouchEventPayload(target, touch, payload);
234 + dispatch(domEvents.touchstart(touchEventPayload));
235 + if (hasPointerEvent()) {
236 + dispatch(domEvents.gotpointercapture(payload));
237 + }
238 + }
239 +}
240 +
241 +export function pointerenter(target, defaultPayload) {
242 + const dispatch = arg => target.dispatchEvent(arg);
243 +
244 + const payload = {
245 + pointerId: defaultPointerId,
246 + ...defaultPayload,
247 + };
248 +
249 + if (hasPointerEvent()) {
250 + dispatch(domEvents.pointerover(payload));
251 + dispatch(domEvents.pointerenter(payload));
252 + }
253 + dispatch(domEvents.mouseover(payload));
254 + dispatch(domEvents.mouseenter(payload));
255 +}
256 +
257 +export function pointerexit(target, defaultPayload) {
258 + const dispatch = arg => target.dispatchEvent(arg);
259 +
260 + const payload = {
261 + pointerId: defaultPointerId,
262 + ...defaultPayload,
263 + };
264 +
265 + if (hasPointerEvent()) {
266 + dispatch(domEvents.pointerout(payload));
267 + dispatch(domEvents.pointerleave(payload));
268 + }
269 + dispatch(domEvents.mouseout(payload));
270 + dispatch(domEvents.mouseleave(payload));
271 +}
272 +
273 +export function pointerhover(target, defaultPayload) {
274 + const dispatch = arg => target.dispatchEvent(arg);
275 +
276 + const payload = {
277 + pointerId: defaultPointerId,
278 + ...defaultPayload,
279 + };
280 +
281 + if (hasPointerEvent()) {
282 + dispatch(domEvents.pointermove(payload));
283 + }
284 + dispatch(domEvents.mousemove(payload));
285 +}
286 +
287 +export function pointermove(target, defaultPayload) {
288 + const dispatch = arg => target.dispatchEvent(arg);
289 + const pointerType = getPointerType(defaultPayload);
290 +
291 + const payload = {
292 + pointerId: defaultPointerId,
293 + pointerType,
294 + ...defaultPayload,
295 + };
296 +
297 + if (hasPointerEvent()) {
298 + dispatch(
299 + domEvents.pointermove({
300 + pressure: pointerType === 'touch' ? 1 : 0.5,
301 + ...payload,
302 + }),
303 + );
304 + } else {
305 + if (pointerType === 'mouse') {
306 + dispatch(domEvents.mousemove(payload));
307 + } else {
308 + const touch = createTouch(target, payload);
309 + touchStore.updateTouch(touch);
310 + const touchEventPayload = createTouchEventPayload(target, touch, payload);
311 + dispatch(domEvents.touchmove(touchEventPayload));
312 + }
313 + }
314 +}
315 +
316 +export function pointerup(target, defaultPayload) {
317 + const dispatch = arg => target.dispatchEvent(arg);
318 + const pointerType = getPointerType(defaultPayload);
319 +
320 + const payload = {
321 + pointerId: defaultPointerId,
322 + pointerType,
323 + ...defaultPayload,
324 + };
325 +
326 + if (pointerType === 'mouse') {
327 + if (hasPointerEvent()) {
328 + dispatch(domEvents.pointerup(payload));
329 + }
330 + dispatch(domEvents.mouseup(payload));
331 + dispatch(domEvents.click(payload));
332 + } else {
333 + if (hasPointerEvent()) {
334 + dispatch(domEvents.pointerup(payload));
335 + dispatch(domEvents.lostpointercapture(payload));
336 + dispatch(domEvents.pointerout(payload));
337 + dispatch(domEvents.pointerleave(payload));
338 + }
339 + const touch = createTouch(target, payload);
340 + touchStore.removeTouch(touch);
341 + const touchEventPayload = createTouchEventPayload(target, touch, payload);
342 + dispatch(domEvents.touchend(touchEventPayload));
343 + dispatch(domEvents.mouseover(payload));
344 + dispatch(domEvents.mousemove(payload));
345 + dispatch(domEvents.mousedown(payload));
346 + if (document.activeElement !== target) {
347 + dispatch(domEvents.focus());
348 + }
349 + dispatch(domEvents.mouseup(payload));
350 + dispatch(domEvents.click(payload));
351 + }
352 +}
353 +
354 +/**
355 + * This function should be called after each test to ensure the touchStore is cleared
356 + * in cases where the mock pointers weren't released before the test completed
357 + * (e.g., a test failed or ran a partial gesture).
358 + */
359 +export function resetActivePointers() {
360 + touchStore.clear();
361 +}
packages/react-interactions/events/src/dom/event-testing-library/domEvents.js renamed
+8 -74
@@ -9,7 +9,12 @@
9
10 'use strict';
11
12 -import {buttonType, buttonsType} from './domEnvironment';
12 +import {
13 + buttonType,
14 + buttonsType,
15 + defaultPointerSize,
16 + defaultBrowserChromeSize,
17 +} from './constants';
18
19 /**
20 * Native event object mocks for higher-level events.
@@ -26,9 +31,6 @@ import {buttonType, buttonsType} from './domEnvironment';
31 * 3. PointerEvent and TouchEvent fields are normalized (e.g., 'rotationAngle' -> 'twist')
32 */
33
29 -const defaultPointerSize = 23;
30 -const defaultBrowserChromeSize = 50;
31 -
34 function emptyFunction() {}
35
36 function createEvent(type, data = {}) {
@@ -77,7 +79,7 @@ function createPointerEvent(
79 offsetY = 0,
80 pageX,
81 pageY,
80 - pointerId = 1,
82 + pointerId,
83 pressure = 0,
84 preventDefault = emptyFunction,
85 pointerType = 'mouse',
@@ -215,80 +217,12 @@ function createMouseEvent(
217 }
218
219 function createTouchEvent(type, payload) {
218 - const touchesPayload = Array.isArray(payload) ? payload : [payload];
219 - const firstTouch = touchesPayload[0];
220 - let altKey = false;
221 - let ctrlKey = false;
222 - let metaKey = false;
223 - let preventDefault = emptyFunction;
224 - let shiftKey = false;
225 - let timeStamp;
226 -
227 - if (firstTouch != null) {
228 - if (firstTouch.altKey != null) {
229 - altKey = firstTouch.altKey;
230 - }
231 - if (firstTouch.ctrlKey != null) {
232 - ctrlKey = firstTouch.ctrlKey;
233 - }
234 - if (firstTouch.metaKey != null) {
235 - metaKey = firstTouch.metaKey;
236 - }
237 - if (firstTouch.preventDefault != null) {
238 - preventDefault = firstTouch.preventDefault;
239 - }
240 - if (firstTouch.shiftKey != null) {
241 - shiftKey = firstTouch.shiftKey;
242 - }
243 - if (firstTouch.timeStamp != null) {
244 - timeStamp = firstTouch.timeStamp;
245 - }
246 - }
247 -
248 - const touches = touchesPayload.map(
249 - ({
250 - height = defaultPointerSize,
251 - pageX,
252 - pageY,
253 - pointerId = 1,
254 - pressure = 1,
255 - twist = 0,
256 - width = defaultPointerSize,
257 - x = 0,
258 - y = 0,
259 - } = {}) => {
260 - return {
261 - clientX: x,
262 - clientY: y,
263 - force: pressure,
264 - identifier: pointerId,
265 - pageX: pageX || x,
266 - pageY: pageY || y,
267 - radiusX: width / 2,
268 - radiusY: height / 2,
269 - rotationAngle: twist,
270 - screenX: x,
271 - screenY: y + defaultBrowserChromeSize,
272 - };
273 - },
274 - );
275 -
276 - const activeTouches = type !== 'touchend' ? touches : [];
277 -
220 return createEvent(type, {
279 - altKey,
280 - changedTouches: touches,
281 - ctrlKey,
221 + ...payload,
222 detail: 0,
283 - metaKey,
284 - preventDefault,
285 - shiftKey,
223 sourceCapabilities: {
224 firesTouchEvents: true,
225 },
289 - targetTouches: activeTouches,
290 - timeStamp,
291 - touches: activeTouches,
226 });
227 }
228
packages/react-interactions/events/src/dom/event-testing-library/index.js renamed
+5 -55
@@ -9,15 +9,11 @@
9
10 'use strict';
11
12 +import {buttonType, buttonsType} from './constants';
13 import * as domEvents from './domEvents';
14 import * as domEventSequences from './domEventSequences';
14 -import {
15 - buttonType,
16 - buttonsType,
17 - hasPointerEvent,
18 - setPointerEvent,
19 - platform,
20 -} from './domEnvironment';
15 +import {hasPointerEvent, setPointerEvent, platform} from './domEnvironment';
16 +import {describeWithPointerEvent, testWithPointerType} from './testHelpers';
17
18 const createEventTarget = node => ({
19 node,
@@ -52,32 +48,6 @@ const createEventTarget = node => ({
48 virtualclick(payload) {
49 node.dispatchEvent(domEvents.virtualclick(payload));
50 },
55 - tabNext() {
56 - node.dispatchEvent(
57 - domEvents.keydown({
58 - key: 'Tab',
59 - }),
60 - );
61 - node.dispatchEvent(
62 - domEvents.keyup({
63 - key: 'Tab',
64 - }),
65 - );
66 - },
67 - tabPrevious() {
68 - node.dispatchEvent(
69 - domEvents.keydown({
70 - key: 'Tab',
71 - shiftKey: true,
72 - }),
73 - );
74 - node.dispatchEvent(
75 - domEvents.keyup({
76 - key: 'Tab',
77 - shiftKey: true,
78 - }),
79 - );
80 - },
51 /**
52 * PointerEvent abstraction.
53 * Dispatches the expected sequence of PointerEvents, MouseEvents, and
@@ -137,28 +107,7 @@ const createEventTarget = node => ({
107 },
108 });
109
140 -function describeWithPointerEvent(message, describeFn) {
141 - const pointerEvent = 'PointerEvent';
142 - const fallback = 'MouseEvent/TouchEvent';
143 - describe.each`
144 - value | name
145 - ${true} | ${pointerEvent}
146 - ${false} | ${fallback}
147 - `(`${message}: $name`, entry => {
148 - const hasPointerEvents = entry.value;
149 - setPointerEvent(hasPointerEvents);
150 - describeFn(hasPointerEvents);
151 - });
152 -}
153 -
154 -function testWithPointerType(message, testFn) {
155 - const table = hasPointerEvent()
156 - ? ['mouse', 'touch', 'pen']
157 - : ['mouse', 'touch'];
158 - test.each(table)(`${message}: %s`, pointerType => {
159 - testFn(pointerType);
160 - });
161 -}
110 +const resetActivePointers = domEventSequences.resetActivePointers;
111
112 export {
113 buttonType,
@@ -167,6 +116,7 @@ export {
116 describeWithPointerEvent,
117 platform,
118 hasPointerEvent,
119 + resetActivePointers,
120 setPointerEvent,
121 testWithPointerType,
122 };
packages/react-interactions/events/src/dom/event-testing-library/testHelpers.js new
+35
@@ -0,0 +1,35 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @emails react-core
8 + */
9 +
10 +'use strict';
11 +
12 +import {hasPointerEvent, setPointerEvent} from './domEnvironment';
13 +
14 +export function describeWithPointerEvent(message, describeFn) {
15 + const pointerEvent = 'PointerEvent';
16 + const fallback = 'MouseEvent/TouchEvent';
17 + describe.each`
18 + value | name
19 + ${true} | ${pointerEvent}
20 + ${false} | ${fallback}
21 + `(`${message}: $name`, entry => {
22 + const hasPointerEvents = entry.value;
23 + setPointerEvent(hasPointerEvents);
24 + describeFn(hasPointerEvents);
25 + });
26 +}
27 +
28 +export function testWithPointerType(message, testFn) {
29 + const table = hasPointerEvent()
30 + ? ['mouse', 'touch', 'pen']
31 + : ['mouse', 'touch'];
32 + test.each(table)(`${message}: %s`, pointerType => {
33 + testFn(pointerType);
34 + });
35 +}
packages/react-interactions/events/src/dom/event-testing-library/touchStore.js new
+85
@@ -0,0 +1,85 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @emails react-core
8 + */
9 +
10 +'use strict';
11 +
12 +/**
13 + * Touch events state machine.
14 + *
15 + * Keeps track of the active pointers and allows them to be reflected in touch events.
16 + */
17 +
18 +const activeTouches = new Map();
19 +
20 +export function addTouch(touch) {
21 + const identifier = touch.identifier;
22 + const target = touch.target;
23 + if (!activeTouches.has(target)) {
24 + activeTouches.set(target, new Map());
25 + }
26 + if (activeTouches.get(target).get(identifier)) {
27 + // Do not allow existing touches to be overwritten
28 + // eslint-disable-next-line react-internal/no-production-logging
29 + console.error(
30 + 'Touch with identifier %s already exists. Did not record touch start.',
31 + identifier,
32 + );
33 + } else {
34 + activeTouches.get(target).set(identifier, touch);
35 + }
36 +}
37 +
38 +export function updateTouch(touch) {
39 + const identifier = touch.identifier;
40 + const target = touch.target;
41 + if (activeTouches.get(target) != null) {
42 + activeTouches.get(target).set(identifier, touch);
43 + } else {
44 + // eslint-disable-next-line react-internal/no-production-logging
45 + console.error(
46 + 'Touch with identifier %s does not exist. Cannot record touch move without a touch start.',
47 + identifier,
48 + );
49 + }
50 +}
51 +
52 +export function removeTouch(touch) {
53 + const identifier = touch.identifier;
54 + const target = touch.target;
55 + if (activeTouches.get(target) != null) {
56 + if (activeTouches.get(target).has(identifier)) {
57 + activeTouches.get(target).delete(identifier);
58 + } else {
59 + // eslint-disable-next-line react-internal/no-production-logging
60 + console.error(
61 + 'Touch with identifier %s does not exist. Cannot record touch end without a touch start.',
62 + identifier,
63 + );
64 + }
65 + }
66 +}
67 +
68 +export function getTouches() {
69 + const touches = [];
70 + activeTouches.forEach((_, target) => {
71 + touches.push(...getTargetTouches(target));
72 + });
73 + return touches;
74 +}
75 +
76 +export function getTargetTouches(target) {
77 + if (activeTouches.get(target) != null) {
78 + return Array.from(activeTouches.get(target).values());
79 + }
80 + return [];
81 +}
82 +
83 +export function clear() {
84 + activeTouches.clear();
85 +}
packages/react-interactions/events/src/dom/testing-library/domEventSequences.js deleted
-216
@@ -1,216 +0,0 @@
1 -/**
2 - * Copyright (c) Facebook, Inc. and its affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @emails react-core
8 - */
9 -
10 -'use strict';
11 -
12 -import * as domEvents from './domEvents';
13 -import {
14 - buttonType,
15 - buttonsType,
16 - hasPointerEvent,
17 - platform,
18 -} from './domEnvironment';
19 -
20 -function emptyFunction() {}
21 -
22 -function getPointerType(payload) {
23 - let pointerType = 'mouse';
24 - if (payload != null && payload.pointerType != null) {
25 - pointerType = payload.pointerType;
26 - } else if (Array.isArray(payload)) {
27 - pointerType = 'touch';
28 - }
29 - return pointerType;
30 -}
31 -
32 -export function contextmenu(
33 - target,
34 - {preventDefault = emptyFunction} = {},
35 - {pointerType = 'mouse', modified} = {},
36 -) {
37 - const dispatch = arg => target.dispatchEvent(arg);
38 - if (pointerType === 'touch') {
39 - if (hasPointerEvent()) {
40 - dispatch(
41 - domEvents.pointerdown({
42 - button: buttonType.primary,
43 - buttons: buttonsType.primary,
44 - pointerType,
45 - }),
46 - );
47 - }
48 - dispatch(domEvents.touchstart());
49 - dispatch(
50 - domEvents.contextmenu({
51 - button: buttonType.primary,
52 - buttons: buttonsType.none,
53 - preventDefault,
54 - }),
55 - );
56 - } else if (pointerType === 'mouse') {
57 - if (modified === true) {
58 - const button = buttonType.primary;
59 - const buttons = buttonsType.primary;
60 - const ctrlKey = true;
61 - if (hasPointerEvent()) {
62 - dispatch(
63 - domEvents.pointerdown({button, buttons, ctrlKey, pointerType}),
64 - );
65 - }
66 - dispatch(domEvents.mousedown({button, buttons, ctrlKey}));
67 - if (platform.get() === 'mac') {
68 - dispatch(
69 - domEvents.contextmenu({button, buttons, ctrlKey, preventDefault}),
70 - );
71 - }
72 - } else {
73 - const button = buttonType.secondary;
74 - const buttons = buttonsType.secondary;
75 - if (hasPointerEvent()) {
76 - dispatch(domEvents.pointerdown({button, buttons, pointerType}));
77 - }
78 - dispatch(domEvents.mousedown({button, buttons}));
79 - dispatch(domEvents.contextmenu({button, buttons, preventDefault}));
80 - }
81 - }
82 -}
83 -
84 -export function pointercancel(target, payload) {
85 - const dispatchEvent = arg => target.dispatchEvent(arg);
86 - const pointerType = getPointerType(payload);
87 - if (hasPointerEvent()) {
88 - dispatchEvent(domEvents.pointercancel(payload));
89 - } else {
90 - if (pointerType === 'mouse') {
91 - dispatchEvent(domEvents.dragstart(payload));
92 - } else {
93 - dispatchEvent(domEvents.touchcancel(payload));
94 - }
95 - }
96 -}
97 -
98 -export function pointerdown(target, defaultPayload) {
99 - const dispatch = arg => target.dispatchEvent(arg);
100 - const pointerType = getPointerType(defaultPayload);
101 -
102 - if (Array.isArray(defaultPayload)) {
103 - // Arrays are for multi-touch only
104 - dispatch(domEvents.touchstart(defaultPayload));
105 - } else {
106 - const payload = {
107 - button: buttonType.primary,
108 - buttons: buttonsType.primary,
109 - ...defaultPayload,
110 - };
111 - if (pointerType === 'mouse') {
112 - if (hasPointerEvent()) {
113 - dispatch(domEvents.pointerover(payload));
114 - dispatch(domEvents.pointerenter(payload));
115 - }
116 - dispatch(domEvents.mouseover(payload));
117 - dispatch(domEvents.mouseenter(payload));
118 - if (hasPointerEvent()) {
119 - dispatch(domEvents.pointerdown(payload));
120 - }
121 - dispatch(domEvents.mousedown(payload));
122 - if (document.activeElement !== target) {
123 - dispatch(domEvents.focus());
124 - }
125 - } else {
126 - if (hasPointerEvent()) {
127 - dispatch(domEvents.pointerover(payload));
128 - dispatch(domEvents.pointerenter(payload));
129 - dispatch(domEvents.pointerdown(payload));
130 - }
131 - dispatch(domEvents.touchstart(payload));
132 - if (hasPointerEvent()) {
133 - dispatch(domEvents.gotpointercapture(payload));
134 - }
135 - }
136 - }
137 -}
138 -
139 -export function pointerenter(target, payload) {
140 - const dispatch = arg => target.dispatchEvent(arg);
141 - if (hasPointerEvent()) {
142 - dispatch(domEvents.pointerover(payload));
143 - dispatch(domEvents.pointerenter(payload));
144 - }
145 - dispatch(domEvents.mouseover(payload));
146 - dispatch(domEvents.mouseenter(payload));
147 -}
148 -
149 -export function pointerexit(target, payload) {
150 - const dispatch = arg => target.dispatchEvent(arg);
151 - if (hasPointerEvent()) {
152 - dispatch(domEvents.pointerout(payload));
153 - dispatch(domEvents.pointerleave(payload));
154 - }
155 - dispatch(domEvents.mouseout(payload));
156 - dispatch(domEvents.mouseleave(payload));
157 -}
158 -
159 -export function pointerhover(target, payload) {
160 - const dispatch = arg => target.dispatchEvent(arg);
161 - if (hasPointerEvent()) {
162 - dispatch(domEvents.pointermove(payload));
163 - }
164 - dispatch(domEvents.mousemove(payload));
165 -}
166 -
167 -export function pointermove(target, payload) {
168 - const dispatch = arg => target.dispatchEvent(arg);
169 - const pointerType = getPointerType(payload);
170 - if (hasPointerEvent()) {
171 - dispatch(
172 - domEvents.pointermove({
173 - pressure: pointerType === 'touch' ? 1 : 0.5,
174 - ...payload,
175 - }),
176 - );
177 - } else {
178 - if (pointerType === 'mouse') {
179 - dispatch(domEvents.mousemove(payload));
180 - } else {
181 - dispatch(domEvents.touchmove(payload));
182 - }
183 - }
184 -}
185 -
186 -export function pointerup(target, payload) {
187 - const dispatch = arg => target.dispatchEvent(arg);
188 - const pointerType = getPointerType(payload);
189 -
190 - if (Array.isArray(payload)) {
191 - // Arrays are for multi-touch only
192 - dispatch(domEvents.touchend(payload));
193 - } else if (pointerType === 'mouse') {
194 - if (hasPointerEvent()) {
195 - dispatch(domEvents.pointerup(payload));
196 - }
197 - dispatch(domEvents.mouseup(payload));
198 - dispatch(domEvents.click(payload));
199 - } else {
200 - if (hasPointerEvent()) {
201 - dispatch(domEvents.pointerup(payload));
202 - dispatch(domEvents.lostpointercapture(payload));
203 - dispatch(domEvents.pointerout(payload));
204 - dispatch(domEvents.pointerleave(payload));
205 - }
206 - dispatch(domEvents.touchend(payload));
207 - dispatch(domEvents.mouseover(payload));
208 - dispatch(domEvents.mousemove(payload));
209 - dispatch(domEvents.mousedown(payload));
210 - if (document.activeElement !== target) {
211 - dispatch(domEvents.focus());
212 - }
213 - dispatch(domEvents.mouseup(payload));
214 - dispatch(domEvents.click(payload));
215 - }
216 -}
packages/react-reconciler/src/__tests__/ReactScope-test.internal.js
+1 -1
@@ -9,7 +9,7 @@
9
10 'use strict';
11
12 -import {createEventTarget} from 'react-interactions/events/src/dom/testing-library';
12 +import {createEventTarget} from 'react-interactions/events/src/dom/event-testing-library';
13
14 let React;
15 let ReactFeatureFlags;