@samitouri / QOS-React-2 / commits / 161f6ae42c

Codemod act -> await act (3/?) (#26336)

Similar to the rationale for `waitFor` (see #26285), we should always await the result of an `act` call so that microtasks have a chance to fire. This only affects the internal `act` that we use in our repo, for now. In the public `act` API, we don't yet require this; however, we effectively will for any update that triggers suspense once `use` lands. So we likely will start warning in an upcoming minor.

Andrew Clark committed Mar 7, 2023 at 14:39 UTC 161f6ae42cf570d3daec355abcf3b006c58315da
11 files changed +179 -163
packages/react-reconciler/src/__tests__/StrictEffectsMode-test.js
+35 -35
@@ -36,7 +36,7 @@ describe('StrictEffectsMode', () => {
36 );
37 }
38
39 - it('should not double invoke effects in legacy mode', () => {
39 + it('should not double invoke effects in legacy mode', async () => {
40 function App({text}) {
41 React.useEffect(() => {
42 Scheduler.log('useEffect mount');
@@ -51,14 +51,14 @@ describe('StrictEffectsMode', () => {
51 return text;
52 }
53
54 - act(() => {
54 + await act(async () => {
55 ReactTestRenderer.create(<App text={'mount'} />);
56 });
57
58 assertLog(['useLayoutEffect mount', 'useEffect mount']);
59 });
60
61 - it('double invoking for effects works properly', () => {
61 + it('double invoking for effects works properly', async () => {
62 function App({text}) {
63 React.useEffect(() => {
64 Scheduler.log('useEffect mount');
@@ -74,7 +74,7 @@ describe('StrictEffectsMode', () => {
74 }
75
76 let renderer;
77 - act(() => {
77 + await act(async () => {
78 renderer = ReactTestRenderer.create(<App text={'mount'} />, {
79 unstable_isConcurrent: true,
80 });
@@ -93,7 +93,7 @@ describe('StrictEffectsMode', () => {
93 assertLog(['useLayoutEffect mount', 'useEffect mount']);
94 }
95
96 - act(() => {
96 + await act(async () => {
97 renderer.update(<App text={'update'} />);
98 });
99
@@ -104,14 +104,14 @@ describe('StrictEffectsMode', () => {
104 'useEffect mount',
105 ]);
106
107 - act(() => {
107 + await act(async () => {
108 renderer.unmount();
109 });
110
111 assertLog(['useLayoutEffect unmount', 'useEffect unmount']);
112 });
113
114 - it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
114 + it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {
115 function App({text}) {
116 React.useEffect(() => {
117 Scheduler.log('useEffect One mount');
@@ -127,7 +127,7 @@ describe('StrictEffectsMode', () => {
127 }
128
129 let renderer;
130 - act(() => {
130 + await act(async () => {
131 renderer = ReactTestRenderer.create(<App text={'mount'} />, {
132 unstable_isConcurrent: true,
133 });
@@ -146,7 +146,7 @@ describe('StrictEffectsMode', () => {
146 assertLog(['useEffect One mount', 'useEffect Two mount']);
147 }
148
149 - act(() => {
149 + await act(async () => {
150 renderer.update(<App text={'update'} />);
151 });
152
@@ -157,14 +157,14 @@ describe('StrictEffectsMode', () => {
157 'useEffect Two mount',
158 ]);
159
160 - act(() => {
160 + await act(async () => {
161 renderer.unmount(null);
162 });
163
164 assertLog(['useEffect One unmount', 'useEffect Two unmount']);
165 });
166
167 - it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
167 + it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {
168 function App({text}) {
169 React.useLayoutEffect(() => {
170 Scheduler.log('useLayoutEffect One mount');
@@ -180,7 +180,7 @@ describe('StrictEffectsMode', () => {
180 }
181
182 let renderer;
183 - act(() => {
183 + await act(async () => {
184 renderer = ReactTestRenderer.create(<App text={'mount'} />, {
185 unstable_isConcurrent: true,
186 });
@@ -199,7 +199,7 @@ describe('StrictEffectsMode', () => {
199 assertLog(['useLayoutEffect One mount', 'useLayoutEffect Two mount']);
200 }
201
202 - act(() => {
202 + await act(async () => {
203 renderer.update(<App text={'update'} />);
204 });
205
@@ -210,14 +210,14 @@ describe('StrictEffectsMode', () => {
210 'useLayoutEffect Two mount',
211 ]);
212
213 - act(() => {
213 + await act(async () => {
214 renderer.unmount();
215 });
216
217 assertLog(['useLayoutEffect One unmount', 'useLayoutEffect Two unmount']);
218 });
219
220 - it('useEffect and useLayoutEffect is called twice when there is no unmount', () => {
220 + it('useEffect and useLayoutEffect is called twice when there is no unmount', async () => {
221 function App({text}) {
222 React.useEffect(() => {
223 Scheduler.log('useEffect mount');
@@ -231,7 +231,7 @@ describe('StrictEffectsMode', () => {
231 }
232
233 let renderer;
234 - act(() => {
234 + await act(async () => {
235 renderer = ReactTestRenderer.create(<App text={'mount'} />, {
236 unstable_isConcurrent: true,
237 });
@@ -248,20 +248,20 @@ describe('StrictEffectsMode', () => {
248 assertLog(['useLayoutEffect mount', 'useEffect mount']);
249 }
250
251 - act(() => {
251 + await act(async () => {
252 renderer.update(<App text={'update'} />);
253 });
254
255 assertLog(['useLayoutEffect mount', 'useEffect mount']);
256
257 - act(() => {
257 + await act(async () => {
258 renderer.unmount();
259 });
260
261 assertLog([]);
262 });
263
264 - it('passes the right context to class component lifecycles', () => {
264 + it('passes the right context to class component lifecycles', async () => {
265 class App extends React.PureComponent {
266 test() {}
267
@@ -285,7 +285,7 @@ describe('StrictEffectsMode', () => {
285 }
286 }
287
288 - act(() => {
288 + await act(async () => {
289 ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});
290 });
291
@@ -300,7 +300,7 @@ describe('StrictEffectsMode', () => {
300 }
301 });
302
303 - it('double invoking works for class components', () => {
303 + it('double invoking works for class components', async () => {
304 class App extends React.PureComponent {
305 componentDidMount() {
306 Scheduler.log('componentDidMount');
@@ -320,7 +320,7 @@ describe('StrictEffectsMode', () => {
320 }
321
322 let renderer;
323 - act(() => {
323 + await act(async () => {
324 renderer = ReactTestRenderer.create(<App text={'mount'} />, {
325 unstable_isConcurrent: true,
326 });
@@ -336,20 +336,20 @@ describe('StrictEffectsMode', () => {
336 assertLog(['componentDidMount']);
337 }
338
339 - act(() => {
339 + await act(async () => {
340 renderer.update(<App text={'update'} />);
341 });
342
343 assertLog(['componentDidUpdate']);
344
345 - act(() => {
345 + await act(async () => {
346 renderer.unmount();
347 });
348
349 assertLog(['componentWillUnmount']);
350 });
351
352 - it('should not double invoke class lifecycles in legacy mode', () => {
352 + it('should not double invoke class lifecycles in legacy mode', async () => {
353 class App extends React.PureComponent {
354 componentDidMount() {
355 Scheduler.log('componentDidMount');
@@ -368,14 +368,14 @@ describe('StrictEffectsMode', () => {
368 }
369 }
370
371 - act(() => {
371 + await act(async () => {
372 ReactTestRenderer.create(<App text={'mount'} />);
373 });
374
375 assertLog(['componentDidMount']);
376 });
377
378 - it('double flushing passive effects only results in one double invoke', () => {
378 + it('double flushing passive effects only results in one double invoke', async () => {
379 function App({text}) {
380 const [state, setState] = React.useState(0);
381 React.useEffect(() => {
@@ -395,7 +395,7 @@ describe('StrictEffectsMode', () => {
395 return text;
396 }
397
398 - act(() => {
398 + await act(async () => {
399 ReactTestRenderer.create(<App text={'mount'} />, {
400 unstable_isConcurrent: true,
401 });
@@ -430,7 +430,7 @@ describe('StrictEffectsMode', () => {
430 }
431 });
432
433 - it('newly mounted components after initial mount get double invoked', () => {
433 + it('newly mounted components after initial mount get double invoked', async () => {
434 let _setShowChild;
435 function Child() {
436 React.useEffect(() => {
@@ -460,7 +460,7 @@ describe('StrictEffectsMode', () => {
460 return showChild && <Child />;
461 }
462
463 - act(() => {
463 + await act(async () => {
464 ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});
465 });
466
@@ -477,7 +477,7 @@ describe('StrictEffectsMode', () => {
477 assertLog(['App useLayoutEffect mount', 'App useEffect mount']);
478 }
479
480 - act(() => {
480 + await act(async () => {
481 _setShowChild(true);
482 });
483
@@ -506,7 +506,7 @@ describe('StrictEffectsMode', () => {
506 }
507 });
508
509 - it('classes and functions are double invoked together correctly', () => {
509 + it('classes and functions are double invoked together correctly', async () => {
510 class ClassChild extends React.PureComponent {
511 componentDidMount() {
512 Scheduler.log('componentDidMount');
@@ -543,7 +543,7 @@ describe('StrictEffectsMode', () => {
543 }
544
545 let renderer;
546 - act(() => {
546 + await act(async () => {
547 renderer = ReactTestRenderer.create(<App text={'mount'} />, {
548 unstable_isConcurrent: true,
549 });
@@ -569,7 +569,7 @@ describe('StrictEffectsMode', () => {
569 ]);
570 }
571
572 - act(() => {
572 + await act(async () => {
573 renderer.update(<App text={'mount'} />);
574 });
575
@@ -580,7 +580,7 @@ describe('StrictEffectsMode', () => {
580 'useEffect mount',
581 ]);
582
583 - act(() => {
583 + await act(async () => {
584 renderer.unmount();
585 });
586
packages/react-reconciler/src/__tests__/StrictEffectsModeDefaults-test.internal.js
+37 -37
@@ -37,7 +37,7 @@ describe('StrictEffectsMode defaults', () => {
37 ReactFeatureFlags.createRootStrictEffectsByDefault = __DEV__;
38 });
39
40 - it('should not double invoke effects in legacy mode', () => {
40 + it('should not double invoke effects in legacy mode', async () => {
41 function App({text}) {
42 React.useEffect(() => {
43 Scheduler.log('useEffect mount');
@@ -52,14 +52,14 @@ describe('StrictEffectsMode defaults', () => {
52 return text;
53 }
54
55 - act(() => {
55 + await act(async () => {
56 ReactNoop.renderLegacySyncRoot(<App text={'mount'} />);
57 });
58
59 assertLog(['useLayoutEffect mount', 'useEffect mount']);
60 });
61
62 - it('should not double invoke class lifecycles in legacy mode', () => {
62 + it('should not double invoke class lifecycles in legacy mode', async () => {
63 class App extends React.PureComponent {
64 componentDidMount() {
65 Scheduler.log('componentDidMount');
@@ -78,7 +78,7 @@ describe('StrictEffectsMode defaults', () => {
78 }
79 }
80
81 - act(() => {
81 + await act(async () => {
82 ReactNoop.renderLegacySyncRoot(<App text={'mount'} />);
83 });
84
@@ -194,7 +194,7 @@ describe('StrictEffectsMode defaults', () => {
194 });
195 });
196
197 - it('double invoking for effects for modern roots', () => {
197 + it('double invoking for effects for modern roots', async () => {
198 function App({text}) {
199 React.useEffect(() => {
200 Scheduler.log('useEffect mount');
@@ -208,7 +208,7 @@ describe('StrictEffectsMode defaults', () => {
208
209 return text;
210 }
211 - act(() => {
211 + await act(async () => {
212 ReactNoop.render(<App text={'mount'} />);
213 });
214
@@ -221,7 +221,7 @@ describe('StrictEffectsMode defaults', () => {
221 'useEffect mount',
222 ]);
223
224 - act(() => {
224 + await act(async () => {
225 ReactNoop.render(<App text={'update'} />);
226 });
227
@@ -232,14 +232,14 @@ describe('StrictEffectsMode defaults', () => {
232 'useEffect mount',
233 ]);
234
235 - act(() => {
235 + await act(async () => {
236 ReactNoop.render(null);
237 });
238
239 assertLog(['useLayoutEffect unmount', 'useEffect unmount']);
240 });
241
242 - it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
242 + it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {
243 function App({text}) {
244 React.useEffect(() => {
245 Scheduler.log('useEffect One mount');
@@ -254,7 +254,7 @@ describe('StrictEffectsMode defaults', () => {
254 return text;
255 }
256
257 - act(() => {
257 + await act(async () => {
258 ReactNoop.render(<App text={'mount'} />);
259 });
260
@@ -267,7 +267,7 @@ describe('StrictEffectsMode defaults', () => {
267 'useEffect Two mount',
268 ]);
269
270 - act(() => {
270 + await act(async () => {
271 ReactNoop.render(<App text={'update'} />);
272 });
273
@@ -278,14 +278,14 @@ describe('StrictEffectsMode defaults', () => {
278 'useEffect Two mount',
279 ]);
280
281 - act(() => {
281 + await act(async () => {
282 ReactNoop.render(null);
283 });
284
285 assertLog(['useEffect One unmount', 'useEffect Two unmount']);
286 });
287
288 - it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
288 + it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {
289 function App({text}) {
290 React.useLayoutEffect(() => {
291 Scheduler.log('useLayoutEffect One mount');
@@ -300,7 +300,7 @@ describe('StrictEffectsMode defaults', () => {
300 return text;
301 }
302
303 - act(() => {
303 + await act(async () => {
304 ReactNoop.render(<App text={'mount'} />);
305 });
306
@@ -313,7 +313,7 @@ describe('StrictEffectsMode defaults', () => {
313 'useLayoutEffect Two mount',
314 ]);
315
316 - act(() => {
316 + await act(async () => {
317 ReactNoop.render(<App text={'update'} />);
318 });
319
@@ -324,14 +324,14 @@ describe('StrictEffectsMode defaults', () => {
324 'useLayoutEffect Two mount',
325 ]);
326
327 - act(() => {
327 + await act(async () => {
328 ReactNoop.render(null);
329 });
330
331 assertLog(['useLayoutEffect One unmount', 'useLayoutEffect Two unmount']);
332 });
333
334 - it('useEffect and useLayoutEffect is called twice when there is no unmount', () => {
334 + it('useEffect and useLayoutEffect is called twice when there is no unmount', async () => {
335 function App({text}) {
336 React.useEffect(() => {
337 Scheduler.log('useEffect mount');
@@ -344,7 +344,7 @@ describe('StrictEffectsMode defaults', () => {
344 return text;
345 }
346
347 - act(() => {
347 + await act(async () => {
348 ReactNoop.render(<App text={'mount'} />);
349 });
350
@@ -355,13 +355,13 @@ describe('StrictEffectsMode defaults', () => {
355 'useEffect mount',
356 ]);
357
358 - act(() => {
358 + await act(async () => {
359 ReactNoop.render(<App text={'update'} />);
360 });
361
362 assertLog(['useLayoutEffect mount', 'useEffect mount']);
363
364 - act(() => {
364 + await act(async () => {
365 ReactNoop.render(null);
366 });
367
@@ -369,7 +369,7 @@ describe('StrictEffectsMode defaults', () => {
369 });
370
371 //@gate useModernStrictMode
372 - it('disconnects refs during double invoking', () => {
372 + it('disconnects refs during double invoking', async () => {
373 const onRefMock = jest.fn();
374 function App({text}) {
375 return (
@@ -382,7 +382,7 @@ describe('StrictEffectsMode defaults', () => {
382 );
383 }
384
385 - act(() => {
385 + await act(async () => {
386 ReactNoop.render(<App text={'mount'} />);
387 });
388
@@ -392,7 +392,7 @@ describe('StrictEffectsMode defaults', () => {
392 expect(onRefMock.mock.calls[2][0]).not.toBeNull();
393 });
394
395 - it('passes the right context to class component lifecycles', () => {
395 + it('passes the right context to class component lifecycles', async () => {
396 class App extends React.PureComponent {
397 test() {}
398
@@ -416,7 +416,7 @@ describe('StrictEffectsMode defaults', () => {
416 }
417 }
418
419 - act(() => {
419 + await act(async () => {
420 ReactNoop.render(<App />);
421 });
422
@@ -427,7 +427,7 @@ describe('StrictEffectsMode defaults', () => {
427 ]);
428 });
429
430 - it('double invoking works for class components', () => {
430 + it('double invoking works for class components', async () => {
431 class App extends React.PureComponent {
432 componentDidMount() {
433 Scheduler.log('componentDidMount');
@@ -446,7 +446,7 @@ describe('StrictEffectsMode defaults', () => {
446 }
447 }
448
449 - act(() => {
449 + await act(async () => {
450 ReactNoop.render(<App text={'mount'} />);
451 });
452
@@ -456,20 +456,20 @@ describe('StrictEffectsMode defaults', () => {
456 'componentDidMount',
457 ]);
458
459 - act(() => {
459 + await act(async () => {
460 ReactNoop.render(<App text={'update'} />);
461 });
462
463 assertLog(['componentDidUpdate']);
464
465 - act(() => {
465 + await act(async () => {
466 ReactNoop.render(null);
467 });
468
469 assertLog(['componentWillUnmount']);
470 });
471
472 - it('double flushing passive effects only results in one double invoke', () => {
472 + it('double flushing passive effects only results in one double invoke', async () => {
473 function App({text}) {
474 const [state, setState] = React.useState(0);
475 React.useEffect(() => {
@@ -489,7 +489,7 @@ describe('StrictEffectsMode defaults', () => {
489 return text;
490 }
491
492 - act(() => {
492 + await act(async () => {
493 ReactNoop.render(<App text={'mount'} />);
494 });
495
@@ -509,7 +509,7 @@ describe('StrictEffectsMode defaults', () => {
509 ]);
510 });
511
512 - it('newly mounted components after initial mount get double invoked', () => {
512 + it('newly mounted components after initial mount get double invoked', async () => {
513 let _setShowChild;
514 function Child() {
515 React.useEffect(() => {
@@ -539,7 +539,7 @@ describe('StrictEffectsMode defaults', () => {
539 return showChild && <Child />;
540 }
541
542 - act(() => {
542 + await act(async () => {
543 ReactNoop.render(<App />);
544 });
545
@@ -552,7 +552,7 @@ describe('StrictEffectsMode defaults', () => {
552 'App useEffect mount',
553 ]);
554
555 - act(() => {
555 + await act(async () => {
556 _setShowChild(true);
557 });
558
@@ -570,7 +570,7 @@ describe('StrictEffectsMode defaults', () => {
570 ]);
571 });
572
573 - it('classes and functions are double invoked together correctly', () => {
573 + it('classes and functions are double invoked together correctly', async () => {
574 class ClassChild extends React.PureComponent {
575 componentDidMount() {
576 Scheduler.log('componentDidMount');
@@ -606,7 +606,7 @@ describe('StrictEffectsMode defaults', () => {
606 );
607 }
608
609 - act(() => {
609 + await act(async () => {
610 ReactNoop.render(<App text={'mount'} />);
611 });
612
@@ -622,7 +622,7 @@ describe('StrictEffectsMode defaults', () => {
622 'useEffect mount',
623 ]);
624
625 - act(() => {
625 + await act(async () => {
626 ReactNoop.render(<App text={'mount'} />);
627 });
628
@@ -633,7 +633,7 @@ describe('StrictEffectsMode defaults', () => {
633 'useEffect mount',
634 ]);
635
636 - act(() => {
636 + await act(async () => {
637 ReactNoop.render(null);
638 });
639
packages/react-reconciler/src/__tests__/useEffectEvent-test.js
+33 -27
@@ -604,7 +604,7 @@ describe('useEffectEvent', () => {
604 ReactNoop.render(<Counter value={1} />);
605 await waitForAll(['Effect value: 1', 'Event value: 1']);
606
607 - act(() => ReactNoop.render(<Counter value={2} />));
607 + await act(async () => ReactNoop.render(<Counter value={2} />));
608 assertLog(['Effect value: 2', 'Event value: 2']);
609 });
610
@@ -742,52 +742,58 @@ describe('useEffectEvent', () => {
742 return <Text text={`Welcome to the ${roomId} room!`} />;
743 }
744
745 - act(() => ReactNoop.render(<ChatRoom roomId="general" theme="light" />));
746 - assertLog(['Welcome to the general room!']);
745 + await act(async () =>
746 + ReactNoop.render(<ChatRoom roomId="general" theme="light" />),
747 + );
748 + await act(async () => jest.runAllTimers());
749 + assertLog(['Welcome to the general room!', 'Connected! theme: light']);
750 expect(ReactNoop).toMatchRenderedOutput(
751 <span prop="Welcome to the general room!" />,
752 );
753
751 - jest.advanceTimersByTime(100);
752 - Scheduler.unstable_advanceTime(100);
753 - assertLog(['Connected! theme: light']);
754 -
754 // change roomId only
756 - act(() => ReactNoop.render(<ChatRoom roomId="music" theme="light" />));
757 - assertLog(['Welcome to the music room!']);
755 + await act(async () =>
756 + ReactNoop.render(<ChatRoom roomId="music" theme="light" />),
757 + );
758 + await act(async () => jest.runAllTimers());
759 + assertLog([
760 + 'Welcome to the music room!',
761 + // should trigger a reconnect
762 + 'Connected! theme: light',
763 + ]);
764 +
765 expect(ReactNoop).toMatchRenderedOutput(
766 <span prop="Welcome to the music room!" />,
767 );
761 - jest.advanceTimersByTime(100);
762 - Scheduler.unstable_advanceTime(100);
763 - // should trigger a reconnect
764 - assertLog(['Connected! theme: light']);
768
769 // change theme only
767 - act(() => ReactNoop.render(<ChatRoom roomId="music" theme="dark" />));
770 + await act(async () =>
771 + ReactNoop.render(<ChatRoom roomId="music" theme="dark" />),
772 + );
773 + await act(async () => jest.runAllTimers());
774 + // should not trigger a reconnect
775 assertLog(['Welcome to the music room!']);
776 expect(ReactNoop).toMatchRenderedOutput(
777 <span prop="Welcome to the music room!" />,
778 );
772 - jest.advanceTimersByTime(100);
773 - Scheduler.unstable_advanceTime(100);
774 - // should not trigger a reconnect
775 - await waitForAll([]);
779
780 // change roomId only
778 - act(() => ReactNoop.render(<ChatRoom roomId="travel" theme="dark" />));
779 - assertLog(['Welcome to the travel room!']);
781 + await act(async () =>
782 + ReactNoop.render(<ChatRoom roomId="travel" theme="dark" />),
783 + );
784 + await act(async () => jest.runAllTimers());
785 + assertLog([
786 + 'Welcome to the travel room!',
787 + // should trigger a reconnect
788 + 'Connected! theme: dark',
789 + ]);
790 expect(ReactNoop).toMatchRenderedOutput(
791 <span prop="Welcome to the travel room!" />,
792 );
783 - jest.advanceTimersByTime(100);
784 - Scheduler.unstable_advanceTime(100);
785 - // should trigger a reconnect
786 - assertLog(['Connected! theme: dark']);
793 });
794
795 // @gate enableUseEffectEventHook
790 - it('integration: implements the docs logVisit example', () => {
796 + it('integration: implements the docs logVisit example', async () => {
797 class AddToCartButton extends React.PureComponent {
798 addToCart = () => {
799 this.props.onClick();
@@ -835,7 +841,7 @@ describe('useEffectEvent', () => {
841 }
842
843 const button = React.createRef(null);
838 - act(() =>
844 + await act(async () =>
845 ReactNoop.render(
846 <AppShell>
847 <Page url="/shop/1" />
@@ -846,7 +852,7 @@ describe('useEffectEvent', () => {
852 act(button.current.addToCart);
853 assertLog(['Add to cart']);
854
849 - act(() =>
855 + await act(async () =>
856 ReactNoop.render(
857 <AppShell>
858 <Page url="/shop/2" />
packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js
+4 -4
@@ -1666,7 +1666,7 @@ describe('useMutableSource', () => {
1666 }
1667
1668 // Mount ComponentA with data version 1
1669 - act(() => {
1669 + await act(async () => {
1670 ReactNoop.render(
1671 <React.Profiler id="root" onRender={onRender}>
1672 <ComponentA />
@@ -1703,7 +1703,7 @@ describe('useMutableSource', () => {
1703 if (__DEV__) {
1704 describe('dev warnings', () => {
1705 // @gate enableUseMutableSource
1706 - it('should warn if the subscribe function does not return an unsubscribe function', () => {
1706 + it('should warn if the subscribe function does not return an unsubscribe function', async () => {
1707 const source = createSource('one');
1708 const mutableSource = createMutableSource(
1709 source,
@@ -1712,8 +1712,8 @@ describe('useMutableSource', () => {
1712
1713 const brokenSubscribe = () => {};
1714
1715 - expect(() => {
1716 - act(() => {
1715 + await expect(async () => {
1716 + await act(async () => {
1717 ReactNoop.render(
1718 <Component
1719 label="only"
packages/react-reconciler/src/__tests__/useMutableSourceHydration-test.js
+5 -5
@@ -142,7 +142,7 @@ describe('useMutableSourceHydration', () => {
142 }
143
144 // @gate enableUseMutableSource
145 - it('should render and hydrate', () => {
145 + it('should render and hydrate', async () => {
146 const source = createSource('one');
147 const mutableSource = createMutableSource(source, param => param.version);
148
@@ -165,7 +165,7 @@ describe('useMutableSourceHydration', () => {
165 assertLog(['only:one']);
166 expect(source.listenerCount).toBe(0);
167
168 - act(() => {
168 + await act(async () => {
169 ReactDOMClient.hydrateRoot(container, <TestComponent />, {
170 mutableSources: [mutableSource],
171 });
@@ -176,7 +176,7 @@ describe('useMutableSourceHydration', () => {
176
177 // @gate enableUseMutableSource
178 // @gate enableClientRenderFallbackOnTextMismatch
179 - it('should detect a tear before hydrating a component', () => {
179 + it('should detect a tear before hydrating a component', async () => {
180 const source = createSource('one');
181 const mutableSource = createMutableSource(source, param => param.version);
182
@@ -199,8 +199,8 @@ describe('useMutableSourceHydration', () => {
199 assertLog(['only:one']);
200 expect(source.listenerCount).toBe(0);
201
202 - expect(() => {
203 - act(() => {
202 + await expect(async () => {
203 + await act(async () => {
204 ReactDOMClient.hydrateRoot(container, <TestComponent />, {
205 mutableSources: [mutableSource],
206 onRecoverableError(error) {
packages/react-reconciler/src/__tests__/useRef-test.internal.js
+23 -23
@@ -50,7 +50,7 @@ describe('useRef', () => {
50 return <span prop={props.text} />;
51 }
52
53 - it('creates a ref object initialized with the provided value', () => {
53 + it('creates a ref object initialized with the provided value', async () => {
54 jest.useFakeTimers();
55
56 function useDebouncedCallback(callback, ms, inputs) {
@@ -82,7 +82,7 @@ describe('useRef', () => {
82 return null;
83 }
84
85 - act(() => {
85 + await act(async () => {
86 ReactNoop.render(<App />);
87 });
88 assertLog([]);
@@ -134,7 +134,7 @@ describe('useRef', () => {
134 });
135
136 if (__DEV__) {
137 - it('should never warn when attaching to children', () => {
137 + it('should never warn when attaching to children', async () => {
138 class Component extends React.Component {
139 render() {
140 return null;
@@ -152,16 +152,16 @@ describe('useRef', () => {
152 );
153 }
154
155 - act(() => {
155 + await act(async () => {
156 ReactNoop.render(<Example phase="mount" />);
157 });
158 - act(() => {
158 + await act(async () => {
159 ReactNoop.render(<Example phase="update" />);
160 });
161 });
162
163 // @gate enableUseRefAccessWarning
164 - it('should warn about reads during render', () => {
164 + it('should warn about reads during render', async () => {
165 function Example() {
166 const ref = useRef(123);
167 let value;
@@ -173,12 +173,12 @@ describe('useRef', () => {
173 return value;
174 }
175
176 - act(() => {
176 + await act(async () => {
177 ReactNoop.render(<Example />);
178 });
179 });
180
181 - it('should not warn about lazy init during render', () => {
181 + it('should not warn about lazy init during render', async () => {
182 function Example() {
183 const ref1 = useRef(null);
184 const ref2 = useRef(undefined);
@@ -192,17 +192,17 @@ describe('useRef', () => {
192 return null;
193 }
194
195 - act(() => {
195 + await act(async () => {
196 ReactNoop.render(<Example />);
197 });
198
199 // Should not warn after an update either.
200 - act(() => {
200 + await act(async () => {
201 ReactNoop.render(<Example />);
202 });
203 });
204
205 - it('should not warn about lazy init outside of render', () => {
205 + it('should not warn about lazy init outside of render', async () => {
206 function Example() {
207 // eslint-disable-next-line no-unused-vars
208 const [didMount, setDidMount] = useState(false);
@@ -216,13 +216,13 @@ describe('useRef', () => {
216 return null;
217 }
218
219 - act(() => {
219 + await act(async () => {
220 ReactNoop.render(<Example />);
221 });
222 });
223
224 // @gate enableUseRefAccessWarning
225 - it('should warn about unconditional lazy init during render', () => {
225 + it('should warn about unconditional lazy init during render', async () => {
226 function Example() {
227 const ref1 = useRef(null);
228 const ref2 = useRef(undefined);
@@ -251,19 +251,19 @@ describe('useRef', () => {
251 }
252
253 let shouldExpectWarning = true;
254 - act(() => {
254 + await act(async () => {
255 ReactNoop.render(<Example />);
256 });
257
258 // Should not warn again on update.
259 shouldExpectWarning = false;
260 - act(() => {
260 + await act(async () => {
261 ReactNoop.render(<Example />);
262 });
263 });
264
265 // @gate enableUseRefAccessWarning
266 - it('should warn about reads to ref after lazy init pattern', () => {
266 + it('should warn about reads to ref after lazy init pattern', async () => {
267 function Example() {
268 const ref1 = useRef(null);
269 const ref2 = useRef(undefined);
@@ -291,13 +291,13 @@ describe('useRef', () => {
291 return value;
292 }
293
294 - act(() => {
294 + await act(async () => {
295 ReactNoop.render(<Example />);
296 });
297 });
298
299 // @gate enableUseRefAccessWarning
300 - it('should warn about writes to ref after lazy init pattern', () => {
300 + it('should warn about writes to ref after lazy init pattern', async () => {
301 function Example() {
302 const ref1 = useRef(null);
303 const ref2 = useRef(undefined);
@@ -323,12 +323,12 @@ describe('useRef', () => {
323 return null;
324 }
325
326 - act(() => {
326 + await act(async () => {
327 ReactNoop.render(<Example />);
328 });
329 });
330
331 - it('should not warn about reads or writes within effect', () => {
331 + it('should not warn about reads or writes within effect', async () => {
332 function Example() {
333 const ref = useRef(123);
334 useLayoutEffect(() => {
@@ -344,21 +344,21 @@ describe('useRef', () => {
344 return null;
345 }
346
347 - act(() => {
347 + await act(async () => {
348 ReactNoop.render(<Example />);
349 });
350
351 ReactNoop.flushPassiveEffects();
352 });
353
354 - it('should not warn about reads or writes outside of render phase (e.g. event handler)', () => {
354 + it('should not warn about reads or writes outside of render phase (e.g. event handler)', async () => {
355 let ref;
356 function Example() {
357 ref = useRef(123);
358 return null;
359 }
360
361 - act(() => {
361 + await act(async () => {
362 ReactNoop.render(<Example />);
363 });
364
packages/react-reconciler/src/__tests__/useSyncExternalStore-test.js
+3 -3
@@ -195,19 +195,19 @@ describe('useSyncExternalStore', () => {
195 }
196
197 const root = ReactNoop.createRoot();
198 - act(() => {
198 + await act(async () => {
199 // Start a render that reads from the store and yields value
200 root.render(<App />);
201 });
202 assertLog(['value:initial']);
203
204 - await act(() => {
204 + await act(async () => {
205 store.set('value:changed');
206 });
207 assertLog(['value:changed']);
208
209 // If cached value was updated, we expect a re-render
210 - await act(() => {
210 + await act(async () => {
211 store.set('value:initial');
212 });
213 assertLog(['value:initial']);
packages/react-refresh/src/__tests__/ReactFresh-test.js
+4 -2
@@ -17,6 +17,7 @@ let ReactDOMClient;
17 let ReactFreshRuntime;
18 let Scheduler;
19 let act;
20 +let internalAct;
21 let createReactClass;
22 let waitFor;
23 let assertLog;
@@ -33,7 +34,8 @@ describe('ReactFresh', () => {
34 ReactDOM = require('react-dom');
35 ReactDOMClient = require('react-dom/client');
36 Scheduler = require('scheduler');
36 - act = require('jest-react').act;
37 + act = require('react-dom/test-utils').act;
38 + internalAct = require('jest-react').act;
39
40 const InternalTestUtils = require('internal-test-utils');
41 waitFor = InternalTestUtils.waitFor;
@@ -2480,7 +2482,7 @@ describe('ReactFresh', () => {
2482 expect(el.firstChild.textContent).toBe('0');
2483 expect(el.firstChild.style.color).toBe('red');
2484
2483 - await act(async () => {
2485 + await internalAct(async () => {
2486 el.firstChild.dispatchEvent(
2487 new MouseEvent('click', {
2488 bubbles: true,
packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js
+1 -1
@@ -31,7 +31,7 @@ describe('ReactFreshIntegration', () => {
31 ReactFreshRuntime = require('react-refresh/runtime');
32 ReactFreshRuntime.injectIntoGlobalHook(global);
33 ReactDOM = require('react-dom');
34 - act = require('jest-react').act;
34 + act = require('react-dom/test-utils').act;
35 container = document.createElement('div');
36 document.body.appendChild(container);
37 exportsObj = undefined;
packages/react-server-dom-relay/src/__tests__/ReactFlightDOMRelay-test.internal.js
+2 -2
@@ -85,7 +85,7 @@ describe('ReactFlightDOMRelay', () => {
85 });
86 });
87
88 - it('can render a Client Component using a module reference and render there', () => {
88 + it('can render a Client Component using a module reference and render there', async () => {
89 function UserClient(props) {
90 return (
91 <span>
@@ -110,7 +110,7 @@ describe('ReactFlightDOMRelay', () => {
110
111 const container = document.createElement('div');
112 const root = ReactDOMClient.createRoot(container);
113 - act(() => {
113 + await act(async () => {
114 root.render(modelClient.greeting);
115 });
116
packages/use-subscription/src/__tests__/useSubscription-test.js
+32 -24
@@ -81,7 +81,7 @@ describe('useSubscription', () => {
81
82 const observable = createBehaviorSubject();
83 let renderer;
84 - act(() => {
84 + await act(async () => {
85 renderer = ReactTestRenderer.create(
86 <Subscription source={observable} />,
87 {unstable_isConcurrent: true},
@@ -90,14 +90,14 @@ describe('useSubscription', () => {
90 assertLog(['default']);
91
92 // Updates while subscribed should re-render the child component
93 - act(() => observable.next(123));
93 + await act(async () => observable.next(123));
94 assertLog([123]);
95 - act(() => observable.next('abc'));
95 + await act(async () => observable.next('abc'));
96 assertLog(['abc']);
97
98 // Unmounting the subscriber should remove listeners
99 - act(() => renderer.update(<div />));
100 - act(() => observable.next(456));
99 + await act(async () => renderer.update(<div />));
100 + await act(async () => observable.next(456));
101 await waitForAll([]);
102 });
103
@@ -133,21 +133,23 @@ describe('useSubscription', () => {
133
134 let observable = createReplaySubject('initial');
135 let renderer;
136 - act(() => {
136 + await act(async () => {
137 renderer = ReactTestRenderer.create(
138 <Subscription source={observable} />,
139 {unstable_isConcurrent: true},
140 );
141 });
142 assertLog(['initial']);
143 - act(() => observable.next('updated'));
143 + await act(async () => observable.next('updated'));
144 assertLog(['updated']);
145
146 await waitForAll([]);
147
148 // Unsetting the subscriber prop should reset subscribed values
149 observable = createReplaySubject(undefined);
150 - act(() => renderer.update(<Subscription source={observable} />));
150 + await act(async () =>
151 + renderer.update(<Subscription source={observable} />),
152 + );
153 assertLog(['default']);
154 });
155
@@ -182,7 +184,7 @@ describe('useSubscription', () => {
184 expect(subscriptions).toHaveLength(0);
185
186 let renderer;
185 - act(() => {
187 + await act(async () => {
188 renderer = ReactTestRenderer.create(
189 <Subscription source={observableA} />,
190 {unstable_isConcurrent: true},
@@ -195,18 +197,20 @@ describe('useSubscription', () => {
197 expect(subscriptions[0]).toBe(observableA);
198
199 // Unsetting the subscriber prop should reset subscribed values
198 - act(() => renderer.update(<Subscription source={observableB} />));
200 + await act(async () =>
201 + renderer.update(<Subscription source={observableB} />),
202 + );
203
204 assertLog(['b-0']);
205 expect(subscriptions).toHaveLength(2);
206 expect(subscriptions[1]).toBe(observableB);
207
208 // Updates to the old subscribable should not re-render the child component
205 - act(() => observableA.next('a-1'));
209 + await act(async () => observableA.next('a-1'));
210 await waitForAll([]);
211
212 // Updates to the bew subscribable should re-render the child component
209 - act(() => observableB.next('b-1'));
213 + await act(async () => observableB.next('b-1'));
214 assertLog(['b-1']);
215
216 expect(subscriptions).toHaveLength(2);
@@ -241,7 +245,7 @@ describe('useSubscription', () => {
245 expect(subscriptions).toHaveLength(0);
246
247 let renderer;
244 - act(() => {
248 + await act(async () => {
249 renderer = ReactTestRenderer.create(
250 <Subscription source={observableA} />,
251 {unstable_isConcurrent: true},
@@ -254,17 +258,19 @@ describe('useSubscription', () => {
258 expect(subscriptions[0]).toBe(observableA);
259
260 // Unsetting the subscriber prop should reset subscribed values
257 - act(() => renderer.update(<Subscription source={observableB} />));
261 + await act(async () =>
262 + renderer.update(<Subscription source={observableB} />),
263 + );
264 assertLog(['b-0']);
265 expect(subscriptions).toHaveLength(2);
266 expect(subscriptions[1]).toBe(observableB);
267
268 // Updates to the old subscribable should not re-render the child component
263 - act(() => observableA.next('a-1'));
269 + await act(async () => observableA.next('a-1'));
270 await waitForAll([]);
271
272 // Updates to the bew subscribable should re-render the child component
267 - act(() => observableB.next('b-1'));
273 + await act(async () => observableB.next('b-1'));
274 assertLog(['b-1']);
275
276 expect(subscriptions).toHaveLength(2);
@@ -329,7 +335,7 @@ describe('useSubscription', () => {
335 const observableB = createBehaviorSubject('b-0');
336
337 let renderer;
332 - act(() => {
338 + await act(async () => {
339 renderer = ReactTestRenderer.create(<Parent observed={observableA} />, {
340 unstable_isConcurrent: true,
341 });
@@ -353,7 +359,7 @@ describe('useSubscription', () => {
359 });
360
361 // Update again
356 - act(() => renderer.update(<Parent observed={observableA} />));
362 + await act(async () => renderer.update(<Parent observed={observableA} />));
363
364 // Flush everything and ensure that the correct subscribable is used
365 // We expect the last emitted update to be rendered (because of the commit phase value check)
@@ -432,7 +438,7 @@ describe('useSubscription', () => {
438 const observableB = createBehaviorSubject('b-0');
439
440 let renderer;
435 - act(() => {
441 + await act(async () => {
442 renderer = ReactTestRenderer.create(<Parent observed={observableA} />, {
443 unstable_isConcurrent: true,
444 });
@@ -474,12 +480,12 @@ describe('useSubscription', () => {
480
481 // Updates from the new subscribable should be ignored.
482 log.splice(0);
477 - act(() => observableB.next('b-1'));
483 + await act(async () => observableB.next('b-1'));
484 await waitForAll([]);
485 expect(log).toEqual([]);
486 });
487
482 - it('should guard against updates that happen after unmounting', () => {
488 + it('should guard against updates that happen after unmounting', async () => {
489 function Child({value = 'default'}) {
490 Scheduler.log(value);
491 return null;
@@ -529,7 +535,7 @@ describe('useSubscription', () => {
535 });
536
537 let renderer;
532 - act(() => {
538 + await act(async () => {
539 renderer = ReactTestRenderer.create(
540 <Subscription source={eventHandler} />,
541 {unstable_isConcurrent: true},
@@ -563,7 +569,7 @@ describe('useSubscription', () => {
569 }
570
571 let renderer;
566 - act(() => {
572 + await act(async () => {
573 renderer = ReactTestRenderer.create(
574 <Subscription subscription={subscription1} />,
575 {unstable_isConcurrent: true},
@@ -571,7 +577,9 @@ describe('useSubscription', () => {
577 });
578 await waitForAll([]);
579
574 - act(() => renderer.update(<Subscription subscription={subscription2} />));
580 + await act(async () =>
581 + renderer.update(<Subscription subscription={subscription2} />),
582 + );
583 await waitForAll([]);
584 });
585