Skip to content

Commit 19c92d3

Browse files
committed
Codemod tests to waitFor pattern (8/?)
This converts some of our test suite to use the `waitFor` test pattern, instead of the `expect(Scheduler).toFlushAndYield` pattern. Most of these changes are automated with jscodeshift, with some slight manual cleanup in certain cases. See #26285 for full context.
1 parent e98695d commit 19c92d3

15 files changed

+547
-512
lines changed

packages/react-reconciler/src/__tests__/ReactSuspenseEffectsSemantics-test.js

Lines changed: 120 additions & 119 deletions
Large diffs are not rendered by default.

packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js

Lines changed: 127 additions & 140 deletions
Large diffs are not rendered by default.

packages/react-reconciler/src/__tests__/useMutableSourceHydration-test.js

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ let Scheduler;
1616
let act;
1717
let createMutableSource;
1818
let useMutableSource;
19+
let waitFor;
20+
let assertLog;
1921

2022
describe('useMutableSourceHydration', () => {
2123
beforeEach(() => {
@@ -33,6 +35,10 @@ describe('useMutableSourceHydration', () => {
3335
React.createMutableSource || React.unstable_createMutableSource;
3436
useMutableSource =
3537
React.useMutableSource || React.unstable_useMutableSource;
38+
39+
const InternalTestUtils = require('internal-test-utils');
40+
waitFor = InternalTestUtils.waitFor;
41+
assertLog = InternalTestUtils.assertLog;
3642
});
3743

3844
const defaultGetSnapshot = source => source.value;
@@ -156,15 +162,15 @@ describe('useMutableSourceHydration', () => {
156162

157163
const htmlString = ReactDOMServer.renderToString(<TestComponent />);
158164
container.innerHTML = htmlString;
159-
expect(Scheduler).toHaveYielded(['only:one']);
165+
assertLog(['only:one']);
160166
expect(source.listenerCount).toBe(0);
161167

162168
act(() => {
163169
ReactDOMClient.hydrateRoot(container, <TestComponent />, {
164170
mutableSources: [mutableSource],
165171
});
166172
});
167-
expect(Scheduler).toHaveYielded(['only:one']);
173+
assertLog(['only:one']);
168174
expect(source.listenerCount).toBe(1);
169175
});
170176

@@ -190,7 +196,7 @@ describe('useMutableSourceHydration', () => {
190196

191197
const htmlString = ReactDOMServer.renderToString(<TestComponent />);
192198
container.innerHTML = htmlString;
193-
expect(Scheduler).toHaveYielded(['only:one']);
199+
assertLog(['only:one']);
194200
expect(source.listenerCount).toBe(0);
195201

196202
expect(() => {
@@ -211,7 +217,7 @@ describe('useMutableSourceHydration', () => {
211217
],
212218
{withoutStack: 1},
213219
);
214-
expect(Scheduler).toHaveYielded([
220+
assertLog([
215221
'only:two',
216222
'only:two',
217223
'Log error: Text content does not match server-rendered HTML.',
@@ -221,7 +227,7 @@ describe('useMutableSourceHydration', () => {
221227
});
222228

223229
// @gate enableUseMutableSource
224-
it('should detect a tear between hydrating components', () => {
230+
it('should detect a tear between hydrating components', async () => {
225231
const source = createSource('one');
226232
const mutableSource = createMutableSource(source, param => param.version);
227233

@@ -249,11 +255,11 @@ describe('useMutableSourceHydration', () => {
249255

250256
const htmlString = ReactDOMServer.renderToString(<TestComponent />);
251257
container.innerHTML = htmlString;
252-
expect(Scheduler).toHaveYielded(['a:one', 'b:one']);
258+
assertLog(['a:one', 'b:one']);
253259
expect(source.listenerCount).toBe(0);
254260

255-
expect(() => {
256-
act(() => {
261+
await expect(async () => {
262+
await act(async () => {
257263
React.startTransition(() => {
258264
ReactDOMClient.hydrateRoot(container, <TestComponent />, {
259265
mutableSources: [mutableSource],
@@ -262,15 +268,15 @@ describe('useMutableSourceHydration', () => {
262268
},
263269
});
264270
});
265-
expect(Scheduler).toFlushAndYieldThrough(['a:one']);
271+
await waitFor(['a:one']);
266272
source.value = 'two';
267273
});
268274
}).toErrorDev(
269275
'Warning: An error occurred during hydration. ' +
270276
'The server HTML was replaced with client content in <div>.',
271277
{withoutStack: true},
272278
);
273-
expect(Scheduler).toHaveYielded([
279+
assertLog([
274280
'a:two',
275281
'b:two',
276282
// TODO: Before onRecoverableError, this error was never surfaced to the
@@ -288,7 +294,7 @@ describe('useMutableSourceHydration', () => {
288294
});
289295

290296
// @gate enableUseMutableSource
291-
it('should detect a tear between hydrating components reading from different parts of a source', () => {
297+
it('should detect a tear between hydrating components reading from different parts of a source', async () => {
292298
const source = createComplexSource('a:one', 'b:one');
293299
const mutableSource = createMutableSource(source, param => param.version);
294300

@@ -318,10 +324,10 @@ describe('useMutableSourceHydration', () => {
318324
</>,
319325
);
320326
container.innerHTML = htmlString;
321-
expect(Scheduler).toHaveYielded(['0:a:one', '1:b:one']);
327+
assertLog(['0:a:one', '1:b:one']);
322328

323-
expect(() => {
324-
act(() => {
329+
await expect(async () => {
330+
await act(async () => {
325331
const fragment = (
326332
<>
327333
<Component
@@ -346,15 +352,15 @@ describe('useMutableSourceHydration', () => {
346352
},
347353
});
348354
});
349-
expect(Scheduler).toFlushAndYieldThrough(['0:a:one']);
355+
await waitFor(['0:a:one']);
350356
source.valueB = 'b:two';
351357
});
352358
}).toErrorDev(
353359
'Warning: An error occurred during hydration. ' +
354360
'The server HTML was replaced with client content in <div>.',
355361
{withoutStack: true},
356362
);
357-
expect(Scheduler).toHaveYielded([
363+
assertLog([
358364
'0:a:one',
359365
'1:b:two',
360366
// TODO: Before onRecoverableError, this error was never surfaced to the

packages/react-reconciler/src/__tests__/useRef-test.internal.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ describe('useRef', () => {
2222
let useLayoutEffect;
2323
let useRef;
2424
let useState;
25+
let waitForAll;
26+
let assertLog;
2527

2628
beforeEach(() => {
2729
React = require('react');
@@ -37,6 +39,10 @@ describe('useRef', () => {
3739
useLayoutEffect = React.useLayoutEffect;
3840
useRef = React.useRef;
3941
useState = React.useState;
42+
43+
const InternalTestUtils = require('internal-test-utils');
44+
waitForAll = InternalTestUtils.waitForAll;
45+
assertLog = InternalTestUtils.assertLog;
4046
});
4147

4248
function Text(props) {
@@ -79,31 +85,31 @@ describe('useRef', () => {
7985
act(() => {
8086
ReactNoop.render(<App />);
8187
});
82-
expect(Scheduler).toHaveYielded([]);
88+
assertLog([]);
8389

8490
ping(1);
8591
ping(2);
8692
ping(3);
8793

88-
expect(Scheduler).toHaveYielded([]);
94+
assertLog([]);
8995

9096
jest.advanceTimersByTime(100);
9197

92-
expect(Scheduler).toHaveYielded(['ping: 3']);
98+
assertLog(['ping: 3']);
9399

94100
ping(4);
95101
jest.advanceTimersByTime(20);
96102
ping(5);
97103
ping(6);
98104
jest.advanceTimersByTime(80);
99105

100-
expect(Scheduler).toHaveYielded([]);
106+
assertLog([]);
101107

102108
jest.advanceTimersByTime(20);
103-
expect(Scheduler).toHaveYielded(['ping: 6']);
109+
assertLog(['ping: 6']);
104110
});
105111

106-
it('should return the same ref during re-renders', () => {
112+
it('should return the same ref during re-renders', async () => {
107113
function Counter() {
108114
const ref = useRef('val');
109115
const [count, setCount] = useState(0);
@@ -121,10 +127,10 @@ describe('useRef', () => {
121127
}
122128

123129
ReactNoop.render(<Counter />);
124-
expect(Scheduler).toFlushAndYield([3]);
130+
await waitForAll([3]);
125131

126132
ReactNoop.render(<Counter />);
127-
expect(Scheduler).toFlushAndYield([3]);
133+
await waitForAll([3]);
128134
});
129135

130136
if (__DEV__) {

packages/react-reconciler/src/__tests__/useSyncExternalStore-test.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ let useImperativeHandle;
2020
let useRef;
2121
let useState;
2222
let startTransition;
23+
let waitFor;
24+
let waitForAll;
25+
let assertLog;
2326

2427
// This tests the native useSyncExternalStore implementation, not the shim.
2528
// Tests that apply to both the native implementation and the shim should go
@@ -41,6 +44,11 @@ describe('useSyncExternalStore', () => {
4144
useSyncExternalStore = React.useSyncExternalStore;
4245
startTransition = React.startTransition;
4346

47+
const InternalTestUtils = require('internal-test-utils');
48+
waitFor = InternalTestUtils.waitFor;
49+
waitForAll = InternalTestUtils.waitForAll;
50+
assertLog = InternalTestUtils.assertLog;
51+
4452
act = require('jest-react').act;
4553
});
4654

@@ -122,13 +130,13 @@ describe('useSyncExternalStore', () => {
122130
root.render(<App store={store1} />);
123131
});
124132

125-
expect(Scheduler).toFlushAndYieldThrough(['A0', 'B0']);
133+
await waitFor(['A0', 'B0']);
126134

127135
// During an interleaved event, the store is mutated.
128136
store1.set(1);
129137

130138
// Then we continue rendering.
131-
expect(Scheduler).toFlushAndYield([
139+
await waitForAll([
132140
// C reads a newer value from the store than A or B, which means they
133141
// are inconsistent.
134142
'C1',
@@ -152,13 +160,13 @@ describe('useSyncExternalStore', () => {
152160
});
153161

154162
// Start a concurrent render that reads from the store, then yield.
155-
expect(Scheduler).toFlushAndYieldThrough(['A0', 'B0']);
163+
await waitFor(['A0', 'B0']);
156164

157165
// During an interleaved event, the store is mutated.
158166
store2.set(1);
159167

160168
// Then we continue rendering.
161-
expect(Scheduler).toFlushAndYield([
169+
await waitForAll([
162170
// C reads a newer value from the store than A or B, which means they
163171
// are inconsistent.
164172
'C1',
@@ -191,17 +199,17 @@ describe('useSyncExternalStore', () => {
191199
// Start a render that reads from the store and yields value
192200
root.render(<App />);
193201
});
194-
expect(Scheduler).toHaveYielded(['value:initial']);
202+
assertLog(['value:initial']);
195203

196204
await act(() => {
197205
store.set('value:changed');
198206
});
199-
expect(Scheduler).toHaveYielded(['value:changed']);
207+
assertLog(['value:changed']);
200208

201209
// If cached value was updated, we expect a re-render
202210
await act(() => {
203211
store.set('value:initial');
204212
});
205-
expect(Scheduler).toHaveYielded(['value:initial']);
213+
assertLog(['value:initial']);
206214
});
207215
});

packages/react-refresh/src/__tests__/ReactFresh-test.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ let ReactFreshRuntime;
1818
let Scheduler;
1919
let act;
2020
let createReactClass;
21+
let waitFor;
22+
let assertLog;
2123

2224
describe('ReactFresh', () => {
2325
let container;
@@ -32,6 +34,11 @@ describe('ReactFresh', () => {
3234
ReactDOMClient = require('react-dom/client');
3335
Scheduler = require('scheduler');
3436
act = require('jest-react').act;
37+
38+
const InternalTestUtils = require('internal-test-utils');
39+
waitFor = InternalTestUtils.waitFor;
40+
assertLog = InternalTestUtils.assertLog;
41+
3542
createReactClass = require('create-react-class/factory')(
3643
React.Component,
3744
React.isValidElement,
@@ -2441,7 +2448,7 @@ describe('ReactFresh', () => {
24412448

24422449
const root = ReactDOMClient.createRoot(container);
24432450
root.render(<AppV1 offscreen={true} />);
2444-
expect(Scheduler).toFlushAndYieldThrough(['App#layout']);
2451+
await waitFor(['App#layout']);
24452452
const el = container.firstChild;
24462453
expect(el.hidden).toBe(true);
24472454
expect(el.firstChild).toBe(null); // Offscreen content not flushed yet.
@@ -2468,7 +2475,7 @@ describe('ReactFresh', () => {
24682475
expect(el.firstChild).toBe(null);
24692476

24702477
// Process the offscreen updates.
2471-
expect(Scheduler).toFlushAndYieldThrough(['Hello#layout']);
2478+
await waitFor(['Hello#layout']);
24722479
expect(container.firstChild).toBe(el);
24732480
expect(el.firstChild.textContent).toBe('0');
24742481
expect(el.firstChild.style.color).toBe('red');
@@ -2481,7 +2488,7 @@ describe('ReactFresh', () => {
24812488
);
24822489
});
24832490

2484-
expect(Scheduler).toHaveYielded(['Hello#layout']);
2491+
assertLog(['Hello#layout']);
24852492
expect(el.firstChild.textContent).toBe('1');
24862493
expect(el.firstChild.style.color).toBe('red');
24872494

@@ -2507,7 +2514,7 @@ describe('ReactFresh', () => {
25072514
expect(el.firstChild.style.color).toBe('red');
25082515

25092516
// Process the offscreen updates.
2510-
expect(Scheduler).toFlushAndYieldThrough(['Hello#layout']);
2517+
await waitFor(['Hello#layout']);
25112518
expect(container.firstChild).toBe(el);
25122519
expect(el.firstChild.textContent).toBe('1');
25132520
expect(el.firstChild.style.color).toBe('orange');

packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.internal.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ const {format: prettyFormat} = require('pretty-format');
1919
// Isolate noop renderer
2020
jest.resetModules();
2121
const ReactNoop = require('react-noop-renderer');
22-
const Scheduler = require('scheduler');
22+
23+
const InternalTestUtils = require('internal-test-utils');
24+
const waitForAll = InternalTestUtils.waitForAll;
2325

2426
// Kind of hacky, but we nullify all the instances to test the tree structure
2527
// with jasmine's deep equality function, and test the instances separate. We
@@ -1015,7 +1017,7 @@ describe('ReactTestRenderer', () => {
10151017
);
10161018
});
10171019

1018-
it('can concurrently render context with a "primary" renderer', () => {
1020+
it('can concurrently render context with a "primary" renderer', async () => {
10191021
const Context = React.createContext(null);
10201022
const Indirection = React.Fragment;
10211023
const App = () => (
@@ -1026,7 +1028,7 @@ describe('ReactTestRenderer', () => {
10261028
</Context.Provider>
10271029
);
10281030
ReactNoop.render(<App />);
1029-
expect(Scheduler).toFlushWithoutYielding();
1031+
await waitForAll([]);
10301032
ReactTestRenderer.create(<App />);
10311033
});
10321034

packages/react-test-renderer/src/__tests__/ReactTestRendererAct-test.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ let React;
44
let ReactTestRenderer;
55
let Scheduler;
66
let act;
7+
let assertLog;
78

89
describe('ReactTestRenderer.act()', () => {
910
beforeEach(() => {
@@ -12,6 +13,9 @@ describe('ReactTestRenderer.act()', () => {
1213
ReactTestRenderer = require('react-test-renderer');
1314
Scheduler = require('scheduler');
1415
act = ReactTestRenderer.act;
16+
17+
const InternalTestUtils = require('internal-test-utils');
18+
assertLog = InternalTestUtils.assertLog;
1519
});
1620

1721
// @gate __DEV__
@@ -91,7 +95,7 @@ describe('ReactTestRenderer.act()', () => {
9195
await act(async () => {
9296
root.update(<App />);
9397
});
94-
expect(Scheduler).toHaveYielded([
98+
assertLog([
9599
// Should not flush effects without also flushing microtasks
96100
// First render:
97101
'Effect',

0 commit comments

Comments
 (0)