[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;