@samitouri / QOS-React-2 / commits / 4e544cffee

[react-events] Split out mixed event responder tests (#16608)

Dominic Gannaway committed Aug 29, 2019 at 16:13 UTC 4e544cffee19e9403753bdafa35e70db06d4190a
5 files changed +403 -419
packages/react-dom/src/events/__tests__/DOMEventResponderSystem-test.internal.js
+64
@@ -994,4 +994,68 @@ describe('DOMEventResponderSystem', () => {
994 dispatchClickEvent(ref.current);
995 expect(log).toEqual([{counter: 1}]);
996 });
997 +
998 + it('should correctly pass through event properties', () => {
999 + const timeStamps = [];
1000 + const ref = React.createRef();
1001 + const eventLog = [];
1002 + const logEvent = event => {
1003 + const propertiesWeCareAbout = {
1004 + counter: event.counter,
1005 + target: event.target,
1006 + timeStamp: event.timeStamp,
1007 + type: event.type,
1008 + };
1009 + timeStamps.push(event.timeStamp);
1010 + eventLog.push(propertiesWeCareAbout);
1011 + };
1012 + let counter = 0;
1013 +
1014 + const TestResponder = createEventResponder({
1015 + targetEventTypes: ['click'],
1016 + onEvent(event, context, props) {
1017 + const obj = {
1018 + counter,
1019 + timeStamp: context.getTimeStamp(),
1020 + target: event.responderTarget,
1021 + type: 'click-test',
1022 + };
1023 + context.dispatchEvent(obj, props.onClick, DiscreteEvent);
1024 + },
1025 + });
1026 +
1027 + const Component = () => {
1028 + const listener = React.unstable_useResponder(TestResponder, {
1029 + onClick: logEvent,
1030 + });
1031 + return <button ref={ref} listeners={listener} />;
1032 + };
1033 + ReactDOM.render(<Component />, container);
1034 + dispatchClickEvent(ref.current);
1035 + counter++;
1036 + dispatchClickEvent(ref.current);
1037 + counter++;
1038 + dispatchClickEvent(ref.current);
1039 + expect(typeof timeStamps[0] === 'number').toBe(true);
1040 + expect(eventLog).toEqual([
1041 + {
1042 + counter: 0,
1043 + target: ref.current,
1044 + timeStamp: timeStamps[0],
1045 + type: 'click-test',
1046 + },
1047 + {
1048 + counter: 1,
1049 + target: ref.current,
1050 + timeStamp: timeStamps[1],
1051 + type: 'click-test',
1052 + },
1053 + {
1054 + counter: 2,
1055 + target: ref.current,
1056 + timeStamp: timeStamps[2],
1057 + type: 'click-test',
1058 + },
1059 + ]);
1060 + });
1061 });
packages/react-events/src/dom/__tests__/Input-test.internal.js
-92
@@ -14,7 +14,6 @@ let ReactFeatureFlags;
14 let ReactDOM;
15 let InputResponder;
16 let useInput;
17 -let usePress;
17 let Scheduler;
18
19 const setUntrackedChecked = Object.getOwnPropertyDescriptor(
@@ -42,7 +41,6 @@ const modulesInit = () => {
41 Scheduler = require('scheduler');
42 InputResponder = require('react-events/input').InputResponder;
43 useInput = require('react-events/input').useInput;
45 - usePress = require('react-events/press').usePress;
44 };
45
46 describe('Input event responder', () => {
@@ -948,96 +946,6 @@ describe('Input event responder', () => {
946 // Value should be the controlled value, not the original one
947 expect(textarea.value).toBe('changed [!]');
948 });
951 -
952 - it('is async for non-input events', () => {
953 - const root = ReactDOM.unstable_createRoot(container);
954 - let input;
955 -
956 - let ops = [];
957 -
958 - function Component({
959 - innerRef,
960 - onChange,
961 - controlledValue,
962 - pressListener,
963 - }) {
964 - const inputListener = useInput({
965 - onChange,
966 - });
967 - return (
968 - <input
969 - type="text"
970 - ref={innerRef}
971 - value={controlledValue}
972 - listeners={[inputListener, pressListener]}
973 - />
974 - );
975 - }
976 -
977 - function PressWrapper({innerRef, onPress, onChange, controlledValue}) {
978 - const pressListener = usePress({
979 - onPress,
980 - });
981 - return (
982 - <Component
983 - onChange={onChange}
984 - innerRef={el => (input = el)}
985 - controlledValue={controlledValue}
986 - pressListener={pressListener}
987 - />
988 - );
989 - }
990 -
991 - class ControlledInput extends React.Component {
992 - state = {value: 'initial'};
993 - onChange = event => this.setState({value: event.target.value});
994 - reset = () => {
995 - this.setState({value: ''});
996 - };
997 - render() {
998 - ops.push(`render: ${this.state.value}`);
999 - const controlledValue =
1000 - this.state.value === 'changed' ? 'changed [!]' : this.state.value;
1001 - return (
1002 - <PressWrapper
1003 - onPress={this.reset}
1004 - onChange={this.onChange}
1005 - innerRef={el => (input = el)}
1006 - controlledValue={controlledValue}
1007 - />
1008 - );
1009 - }
1010 - }
1011 -
1012 - // Initial mount. Test that this is async.
1013 - root.render(<ControlledInput />);
1014 - // Should not have flushed yet.
1015 - expect(ops).toEqual([]);
1016 - expect(input).toBe(undefined);
1017 - // Flush callbacks.
1018 - Scheduler.unstable_flushAll();
1019 - expect(ops).toEqual(['render: initial']);
1020 - expect(input.value).toBe('initial');
1021 -
1022 - ops = [];
1023 -
1024 - // Trigger a click event
1025 - input.dispatchEvent(
1026 - new MouseEvent('mousedown', {bubbles: true, cancelable: true}),
1027 - );
1028 - input.dispatchEvent(
1029 - new MouseEvent('mouseup', {bubbles: true, cancelable: true}),
1030 - );
1031 - // Nothing should have changed
1032 - expect(ops).toEqual([]);
1033 - expect(input.value).toBe('initial');
1034 -
1035 - // Flush callbacks.
1036 - Scheduler.unstable_flushAll();
1037 - // Now the click update has flushed.
1038 - expect(ops).toEqual(['render: ']);
1039 - expect(input.value).toBe('');
1040 - });
949 });
950 });
951
packages/react-events/src/dom/__tests__/MixedResponders-test-internal.js new
+326
@@ -0,0 +1,326 @@
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 {createEventTarget} from '../testing-library';
13 +
14 +let React;
15 +let ReactFeatureFlags;
16 +let ReactDOM;
17 +let Scheduler;
18 +
19 +describe('mixing responders with the heritage event system', () => {
20 + let container;
21 +
22 + beforeEach(() => {
23 + ReactFeatureFlags = require('shared/ReactFeatureFlags');
24 + ReactFeatureFlags.enableFlareAPI = true;
25 + React = require('react');
26 + ReactDOM = require('react-dom');
27 + Scheduler = require('scheduler');
28 + container = document.createElement('div');
29 + document.body.appendChild(container);
30 + });
31 +
32 + afterEach(() => {
33 + document.body.removeChild(container);
34 + container = null;
35 + });
36 +
37 + it('should properly only flush sync once when the event systems are mixed', () => {
38 + const usePress = require('react-events/press').usePress;
39 + const ref = React.createRef();
40 + let renderCounts = 0;
41 +
42 + function MyComponent() {
43 + const [, updateCounter] = React.useState(0);
44 + renderCounts++;
45 +
46 + function handlePress() {
47 + updateCounter(count => count + 1);
48 + }
49 +
50 + const listener = usePress({
51 + onPress: handlePress,
52 + });
53 +
54 + return (
55 + <div>
56 + <button
57 + ref={ref}
58 + listeners={listener}
59 + onClick={() => {
60 + updateCounter(count => count + 1);
61 + }}>
62 + Press me
63 + </button>
64 + </div>
65 + );
66 + }
67 +
68 + const newContainer = document.createElement('div');
69 + const root = ReactDOM.unstable_createRoot(newContainer);
70 + document.body.appendChild(newContainer);
71 + root.render(<MyComponent />);
72 + Scheduler.unstable_flushAll();
73 +
74 + const target = createEventTarget(ref.current);
75 + target.pointerdown({timeStamp: 100});
76 + target.pointerup({timeStamp: 100});
77 + target.click({timeStamp: 100});
78 +
79 + if (__DEV__) {
80 + expect(renderCounts).toBe(2);
81 + } else {
82 + expect(renderCounts).toBe(1);
83 + }
84 + Scheduler.unstable_flushAll();
85 + if (__DEV__) {
86 + expect(renderCounts).toBe(4);
87 + } else {
88 + expect(renderCounts).toBe(2);
89 + }
90 +
91 + target.pointerdown({timeStamp: 100});
92 + target.pointerup({timeStamp: 100});
93 + // Ensure the timeStamp logic works
94 + target.click({timeStamp: 101});
95 +
96 + if (__DEV__) {
97 + expect(renderCounts).toBe(6);
98 + } else {
99 + expect(renderCounts).toBe(3);
100 + }
101 +
102 + Scheduler.unstable_flushAll();
103 + document.body.removeChild(newContainer);
104 + });
105 +
106 + it('should properly flush sync when the event systems are mixed with unstable_flushDiscreteUpdates', () => {
107 + const usePress = require('react-events/press').usePress;
108 + const ref = React.createRef();
109 + let renderCounts = 0;
110 +
111 + function MyComponent() {
112 + const [, updateCounter] = React.useState(0);
113 + renderCounts++;
114 +
115 + function handlePress() {
116 + updateCounter(count => count + 1);
117 + }
118 +
119 + const listener = usePress({
120 + onPress: handlePress,
121 + });
122 +
123 + return (
124 + <div>
125 + <button
126 + ref={ref}
127 + listeners={listener}
128 + onClick={() => {
129 + // This should flush synchronously
130 + ReactDOM.unstable_flushDiscreteUpdates();
131 + updateCounter(count => count + 1);
132 + }}>
133 + Press me
134 + </button>
135 + </div>
136 + );
137 + }
138 +
139 + const newContainer = document.createElement('div');
140 + const root = ReactDOM.unstable_createRoot(newContainer);
141 + document.body.appendChild(newContainer);
142 + root.render(<MyComponent />);
143 + Scheduler.unstable_flushAll();
144 +
145 + const target = createEventTarget(ref.current);
146 + target.pointerdown({timeStamp: 100});
147 + target.pointerup({timeStamp: 100});
148 +
149 + if (__DEV__) {
150 + expect(renderCounts).toBe(4);
151 + } else {
152 + expect(renderCounts).toBe(2);
153 + }
154 + Scheduler.unstable_flushAll();
155 + if (__DEV__) {
156 + expect(renderCounts).toBe(6);
157 + } else {
158 + expect(renderCounts).toBe(3);
159 + }
160 +
161 + target.pointerdown({timeStamp: 100});
162 + // Ensure the timeStamp logic works
163 + target.pointerup({timeStamp: 101});
164 +
165 + if (__DEV__) {
166 + expect(renderCounts).toBe(8);
167 + } else {
168 + expect(renderCounts).toBe(4);
169 + }
170 +
171 + Scheduler.unstable_flushAll();
172 + document.body.removeChild(newContainer);
173 + });
174 +
175 + it(
176 + 'should only flush before outermost discrete event handler when mixing ' +
177 + 'event systems',
178 + async () => {
179 + const {useState} = React;
180 + const usePress = require('react-events/press').usePress;
181 +
182 + const button = React.createRef();
183 +
184 + const ops = [];
185 +
186 + function MyComponent() {
187 + const [pressesCount, updatePressesCount] = useState(0);
188 + const [clicksCount, updateClicksCount] = useState(0);
189 +
190 + function handlePress() {
191 + // This dispatches a synchronous, discrete event in the legacy event
192 + // system. However, because it's nested inside the new event system,
193 + // its updates should not flush until the end of the outer handler.
194 + const target = createEventTarget(button.current);
195 + target.click();
196 + // Text context should not have changed
197 + ops.push(newContainer.textContent);
198 + updatePressesCount(pressesCount + 1);
199 + }
200 +
201 + const listener = usePress({
202 + onPress: handlePress,
203 + });
204 +
205 + return (
206 + <div>
207 + <button
208 + listeners={listener}
209 + ref={button}
210 + onClick={() => updateClicksCount(clicksCount + 1)}>
211 + Presses: {pressesCount}, Clicks: {clicksCount}
212 + </button>
213 + </div>
214 + );
215 + }
216 +
217 + const newContainer = document.createElement('div');
218 + document.body.appendChild(newContainer);
219 + const root = ReactDOM.unstable_createRoot(newContainer);
220 +
221 + root.render(<MyComponent />);
222 + Scheduler.unstable_flushAll();
223 + expect(newContainer.textContent).toEqual('Presses: 0, Clicks: 0');
224 +
225 + const target = createEventTarget(button.current);
226 + target.pointerdown({timeStamp: 100});
227 + target.pointerup({timeStamp: 100});
228 +
229 + Scheduler.unstable_flushAll();
230 + expect(newContainer.textContent).toEqual('Presses: 1, Clicks: 1');
231 +
232 + expect(ops).toEqual(['Presses: 0, Clicks: 0']);
233 + },
234 + );
235 +
236 + describe('mixing the Input and Press repsonders', () => {
237 + it('is async for non-input events', () => {
238 + ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
239 + ReactFeatureFlags.enableUserBlockingEvents = true;
240 + const usePress = require('react-events/press').usePress;
241 + const useInput = require('react-events/input').useInput;
242 + const root = ReactDOM.unstable_createRoot(container);
243 + let input;
244 +
245 + let ops = [];
246 +
247 + function Component({innerRef, onChange, controlledValue, pressListener}) {
248 + const inputListener = useInput({
249 + onChange,
250 + });
251 + return (
252 + <input
253 + type="text"
254 + ref={innerRef}
255 + value={controlledValue}
256 + listeners={[inputListener, pressListener]}
257 + />
258 + );
259 + }
260 +
261 + function PressWrapper({innerRef, onPress, onChange, controlledValue}) {
262 + const pressListener = usePress({
263 + onPress,
264 + });
265 + return (
266 + <Component
267 + onChange={onChange}
268 + innerRef={el => (input = el)}
269 + controlledValue={controlledValue}
270 + pressListener={pressListener}
271 + />
272 + );
273 + }
274 +
275 + class ControlledInput extends React.Component {
276 + state = {value: 'initial'};
277 + onChange = event => this.setState({value: event.target.value});
278 + reset = () => {
279 + this.setState({value: ''});
280 + };
281 + render() {
282 + ops.push(`render: ${this.state.value}`);
283 + const controlledValue =
284 + this.state.value === 'changed' ? 'changed [!]' : this.state.value;
285 + return (
286 + <PressWrapper
287 + onPress={this.reset}
288 + onChange={this.onChange}
289 + innerRef={el => (input = el)}
290 + controlledValue={controlledValue}
291 + />
292 + );
293 + }
294 + }
295 +
296 + // Initial mount. Test that this is async.
297 + root.render(<ControlledInput />);
298 + // Should not have flushed yet.
299 + expect(ops).toEqual([]);
300 + expect(input).toBe(undefined);
301 + // Flush callbacks.
302 + Scheduler.unstable_flushAll();
303 + expect(ops).toEqual(['render: initial']);
304 + expect(input.value).toBe('initial');
305 +
306 + ops = [];
307 +
308 + // Trigger a click event
309 + input.dispatchEvent(
310 + new MouseEvent('mousedown', {bubbles: true, cancelable: true}),
311 + );
312 + input.dispatchEvent(
313 + new MouseEvent('mouseup', {bubbles: true, cancelable: true}),
314 + );
315 + // Nothing should have changed
316 + expect(ops).toEqual([]);
317 + expect(input.value).toBe('initial');
318 +
319 + // Flush callbacks.
320 + Scheduler.unstable_flushAll();
321 + // Now the click update has flushed.
322 + expect(ops).toEqual(['render: ']);
323 + expect(input.value).toBe('');
324 + });
325 + });
326 +});
packages/react-events/src/dom/__tests__/Press-test.internal.js
-327
@@ -1120,334 +1120,7 @@ describe.each(environmentTable)('Press responder', hasPointerEvents => {
1120 target.pointerdown();
1121 });
1122
1123 - it('should correctly pass through event properties', () => {
1124 - const timeStamps = [];
1125 - const ref = React.createRef();
1126 - const eventLog = [];
1127 - const logEvent = event => {
1128 - const propertiesWeCareAbout = {
1129 - pageX: event.pageX,
1130 - pageY: event.pageY,
1131 - screenX: event.screenX,
1132 - screenY: event.screenY,
1133 - clientX: event.clientX,
1134 - clientY: event.clientY,
1135 - pointerType: event.pointerType,
1136 - target: event.target,
1137 - timeStamp: event.timeStamp,
1138 - type: event.type,
1139 - };
1140 - timeStamps.push(event.timeStamp);
1141 - eventLog.push(propertiesWeCareAbout);
1142 - };
1143 -
1144 - const Component = () => {
1145 - const listener = usePress({
1146 - onPressStart: logEvent,
1147 - onPressEnd: logEvent,
1148 - onPressMove: logEvent,
1149 - onPress: logEvent,
1150 - });
1151 - return <button ref={ref} listeners={listener} />;
1152 - };
1153 - ReactDOM.render(<Component />, container);
1154 -
1155 - const target = createEventTarget(ref.current);
1156 - target.setBoundingClientRect({x: 10, y: 10, width: 100, height: 100});
1157 - target.pointerdown({
1158 - pointerType: 'mouse',
1159 - pageX: 15,
1160 - pageY: 16,
1161 - x: 30,
1162 - y: 31,
1163 - });
1164 - target.pointermove({
1165 - pointerType: 'mouse',
1166 - pageX: 16,
1167 - pageY: 17,
1168 - x: 31,
1169 - y: 32,
1170 - });
1171 - target.pointerup({
1172 - pointerType: 'mouse',
1173 - pageX: 17,
1174 - pageY: 18,
1175 - x: 32,
1176 - y: 33,
1177 - });
1178 - target.pointerdown({
1179 - pointerType: 'mouse',
1180 - pageX: 18,
1181 - pageY: 19,
1182 - x: 33,
1183 - y: 34,
1184 - });
1185 - expect(typeof timeStamps[0] === 'number').toBe(true);
1186 - expect(eventLog).toEqual([
1187 - {
1188 - pointerType: 'mouse',
1189 - pageX: 15,
1190 - pageY: 16,
1191 - screenX: 30,
1192 - screenY: 81,
1193 - clientX: 30,
1194 - clientY: 31,
1195 - target: ref.current,
1196 - timeStamp: timeStamps[0],
1197 - type: 'pressstart',
1198 - },
1199 - {
1200 - pointerType: 'mouse',
1201 - pageX: 16,
1202 - pageY: 17,
1203 - screenX: 31,
1204 - screenY: 82,
1205 - clientX: 31,
1206 - clientY: 32,
1207 - target: ref.current,
1208 - timeStamp: timeStamps[1],
1209 - type: 'pressmove',
1210 - },
1211 - {
1212 - pointerType: 'mouse',
1213 - pageX: 17,
1214 - pageY: 18,
1215 - screenX: 32,
1216 - screenY: 83,
1217 - clientX: 32,
1218 - clientY: 33,
1219 - target: ref.current,
1220 - timeStamp: timeStamps[2],
1221 - type: 'pressend',
1222 - },
1223 - {
1224 - pointerType: 'mouse',
1225 - pageX: 17,
1226 - pageY: 18,
1227 - screenX: 32,
1228 - screenY: 83,
1229 - clientX: 32,
1230 - clientY: 33,
1231 - target: ref.current,
1232 - timeStamp: timeStamps[3],
1233 - type: 'press',
1234 - },
1235 - {
1236 - pointerType: 'mouse',
1237 - pageX: 18,
1238 - pageY: 19,
1239 - screenX: 33,
1240 - screenY: 84,
1241 - clientX: 33,
1242 - clientY: 34,
1243 - target: ref.current,
1244 - timeStamp: timeStamps[4],
1245 - type: 'pressstart',
1246 - },
1247 - ]);
1248 - });
1249 -
1123 if (hasPointerEvents) {
1251 - // TODO(T46067442): move these tests to core
1252 - /*
1253 - it('should properly only flush sync once when the event systems are mixed', () => {
1254 - const ref = React.createRef();
1255 - let renderCounts = 0;
1256 -
1257 - function MyComponent() {
1258 - const [, updateCounter] = React.useState(0);
1259 - renderCounts++;
1260 -
1261 - function handlePress() {
1262 - updateCounter(count => count + 1);
1263 - }
1264 -
1265 - const listener = usePress({
1266 - onPress: handlePress,
1267 - });
1268 -
1269 - return (
1270 - <div>
1271 - <button
1272 - ref={ref}
1273 - listeners={listener}
1274 - onClick={() => {
1275 - updateCounter(count => count + 1);
1276 - }}>
1277 - Press me
1278 - </button>
1279 - </div>
1280 - );
1281 - }
1282 -
1283 - const newContainer = document.createElement('div');
1284 - const root = ReactDOM.unstable_createRoot(newContainer);
1285 - document.body.appendChild(newContainer);
1286 - root.render(<MyComponent />);
1287 - Scheduler.unstable_flushAll();
1288 -
1289 - const target = ref.current;
1290 - target.dispatchEvent(pointerdown({timeStamp: 100}));
1291 - target.dispatchEvent(pointerup({timeStamp: 100}));
1292 - target.dispatchEvent(click({timeStamp: 100}));
1293 -
1294 - if (__DEV__) {
1295 - expect(renderCounts).toBe(2);
1296 - } else {
1297 - expect(renderCounts).toBe(1);
1298 - }
1299 - Scheduler.unstable_flushAll();
1300 - if (__DEV__) {
1301 - expect(renderCounts).toBe(4);
1302 - } else {
1303 - expect(renderCounts).toBe(2);
1304 - }
1305 -
1306 - target.dispatchEvent(pointerdown({timeStamp: 100}));
1307 - target.dispatchEvent(pointerup({timeStamp: 100}));
1308 - // Ensure the timeStamp logic works
1309 - target.dispatchEvent(click({timeStamp: 101}));
1310 -
1311 - if (__DEV__) {
1312 - expect(renderCounts).toBe(6);
1313 - } else {
1314 - expect(renderCounts).toBe(3);
1315 - }
1316 -
1317 - Scheduler.unstable_flushAll();
1318 - document.body.removeChild(newContainer);
1319 - });
1320 -
1321 - it('should properly flush sync when the event systems are mixed with unstable_flushDiscreteUpdates', () => {
1322 - const ref = React.createRef();
1323 - let renderCounts = 0;
1324 -
1325 - function MyComponent() {
1326 - const [, updateCounter] = React.useState(0);
1327 - renderCounts++;
1328 -
1329 - function handlePress() {
1330 - updateCounter(count => count + 1);
1331 - }
1332 -
1333 - const listener = usePress({
1334 - onPress: handlePress,
1335 - });
1336 -
1337 - return (
1338 - <div>
1339 - <button
1340 - ref={ref}
1341 - listeners={listener}
1342 - onClick={() => {
1343 - // This should flush synchronously
1344 - ReactDOM.unstable_flushDiscreteUpdates();
1345 - updateCounter(count => count + 1);
1346 - }}>
1347 - Press me
1348 - </button>
1349 - </div>
1350 - );
1351 - }
1352 -
1353 - const newContainer = document.createElement('div');
1354 - const root = ReactDOM.unstable_createRoot(newContainer);
1355 - document.body.appendChild(newContainer);
1356 - root.render(<MyComponent />);
1357 - Scheduler.unstable_flushAll();
1358 -
1359 - const target = ref.current;
1360 - target.dispatchEvent(pointerdown({timeStamp: 100}));
1361 - target.dispatchEvent(pointerup({timeStamp: 100}));
1362 - target.dispatchEvent(click({timeStamp: 100}));
1363 -
1364 - if (__DEV__) {
1365 - expect(renderCounts).toBe(4);
1366 - } else {
1367 - expect(renderCounts).toBe(2);
1368 - }
1369 - Scheduler.unstable_flushAll();
1370 - if (__DEV__) {
1371 - expect(renderCounts).toBe(6);
1372 - } else {
1373 - expect(renderCounts).toBe(3);
1374 - }
1375 -
1376 - target.dispatchEvent(pointerdown({timeStamp: 100}));
1377 - target.dispatchEvent(pointerup({timeStamp: 100}));
1378 - // Ensure the timeStamp logic works
1379 - target.dispatchEvent(click({timeStamp: 101}));
1380 -
1381 - if (__DEV__) {
1382 - expect(renderCounts).toBe(8);
1383 - } else {
1384 - expect(renderCounts).toBe(4);
1385 - }
1386 -
1387 - Scheduler.unstable_flushAll();
1388 - document.body.removeChild(newContainer);
1389 - });
1390 -
1391 - it(
1392 - 'should only flush before outermost discrete event handler when mixing ' +
1393 - 'event systems',
1394 - async () => {
1395 - const {useState} = React;
1396 -
1397 - const button = React.createRef();
1398 -
1399 - const ops = [];
1400 -
1401 - function MyComponent() {
1402 - const [pressesCount, updatePressesCount] = useState(0);
1403 - const [clicksCount, updateClicksCount] = useState(0);
1404 -
1405 - function handlePress() {
1406 - // This dispatches a synchronous, discrete event in the legacy event
1407 - // system. However, because it's nested inside the new event system,
1408 - // its updates should not flush until the end of the outer handler.
1409 - button.current.click();
1410 - // Text context should not have changed
1411 - ops.push(newContainer.textContent);
1412 - updatePressesCount(pressesCount + 1);
1413 - }
1414 -
1415 - const listener = usePress({
1416 - onPress: handlePress,
1417 - });
1418 -
1419 - return (
1420 - <div>
1421 - <button
1422 - listeners={listener}
1423 - ref={button}
1424 - onClick={() => updateClicksCount(clicksCount + 1)}>
1425 - Presses: {pressesCount}, Clicks: {clicksCount}
1426 - </button>
1427 - </div>
1428 - );
1429 - }
1430 -
1431 - const newContainer = document.createElement('div');
1432 - document.body.appendChild(newContainer);
1433 - const root = ReactDOM.unstable_createRoot(newContainer);
1434 -
1435 - root.render(<MyComponent />);
1436 - Scheduler.unstable_flushAll();
1437 - expect(newContainer.textContent).toEqual('Presses: 0, Clicks: 0');
1438 -
1439 - const target = button.current;
1440 - target.dispatchEvent(pointerdown({timeStamp: 100}));
1441 - target.dispatchEvent(pointerup({timeStamp: 100}));
1442 - target.dispatchEvent(click({timeStamp: 100}));
1443 -
1444 - Scheduler.unstable_flushAll();
1445 - expect(newContainer.textContent).toEqual('Presses: 1, Clicks: 1');
1446 -
1447 - expect(ops).toEqual(['Presses: 0, Clicks: 0']);
1448 - },
1449 - );
1450 - */
1124 it('should work correctly with stopPropagation set to true', () => {
1125 const ref = React.createRef();
1126 const pointerDownEvent = jest.fn();
packages/react-events/src/dom/testing-library/domEvents.js
+13
@@ -37,6 +37,9 @@ function createEvent(type, data = {}) {
37 if (data != null) {
38 Object.keys(data).forEach(key => {
39 const value = data[key];
40 + if (key === 'timeStamp' && !value) {
41 + return;
42 + }
43 Object.defineProperty(event, key, {value});
44 });
45 }
@@ -83,6 +86,7 @@ function createPointerEvent(
86 tangentialPressure = 0,
87 tiltX = 0,
88 tiltY = 0,
89 + timeStamp,
90 twist = 0,
91 width,
92 x = 0,
@@ -122,6 +126,7 @@ function createPointerEvent(
126 tangentialPressure,
127 tiltX,
128 tiltY,
129 + timeStamp,
130 twist,
131 width: isMouse ? 1 : width != null ? width : defaultPointerSize,
132 });
@@ -171,6 +176,7 @@ function createMouseEvent(
176 screenX,
177 screenY,
178 shiftKey = false,
179 + timeStamp,
180 x = 0,
181 y = 0,
182 } = {},
@@ -198,6 +204,7 @@ function createMouseEvent(
204 screenX: screenX === 0 ? screenX : x,
205 screenY: screenY === 0 ? screenY : y + defaultBrowserChromeSize,
206 shiftKey,
207 + timeStamp,
208 });
209 }
210
@@ -209,6 +216,8 @@ function createTouchEvent(type, payload) {
216 let metaKey = false;
217 let preventDefault = emptyFunction;
218 let shiftKey = false;
219 + let timeStamp;
220 +
221 if (firstTouch != null) {
222 if (firstTouch.altKey != null) {
223 altKey = firstTouch.altKey;
@@ -225,6 +234,9 @@ function createTouchEvent(type, payload) {
234 if (firstTouch.shiftKey != null) {
235 shiftKey = firstTouch.shiftKey;
236 }
237 + if (firstTouch.timeStamp != null) {
238 + timeStamp = firstTouch.timeStamp;
239 + }
240 }
241
242 const touches = touchesPayload.map(
@@ -268,6 +280,7 @@ function createTouchEvent(type, payload) {
280 firesTouchEvents: true,
281 },
282 targetTouches: activeTouches,
283 + timeStamp,
284 touches: activeTouches,
285 });
286 }