Skip to content

Commit 4b9c939

Browse files
committed
Codemod tests to waitFor pattern (1/?)
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 e524467 commit 4b9c939

15 files changed

+698
-905
lines changed

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
describe('DebugTracing', () => {
1313
let React;
1414
let ReactTestRenderer;
15-
let Scheduler;
15+
let waitForPaint;
1616

1717
let logs;
1818

@@ -27,7 +27,8 @@ describe('DebugTracing', () => {
2727

2828
React = require('react');
2929
ReactTestRenderer = require('react-test-renderer');
30-
Scheduler = require('scheduler');
30+
const InternalTestUtils = require('internal-test-utils');
31+
waitForPaint = InternalTestUtils.waitForPaint;
3132

3233
logs = [];
3334

@@ -100,7 +101,7 @@ describe('DebugTracing', () => {
100101
});
101102

102103
// @gate experimental && build === 'development' && enableDebugTracing && enableCPUSuspense
103-
it('should log sync render with CPU suspense', () => {
104+
it('should log sync render with CPU suspense', async () => {
104105
function Example() {
105106
console.log('<Example/>');
106107
return null;
@@ -129,7 +130,7 @@ describe('DebugTracing', () => {
129130

130131
logs.splice(0);
131132

132-
expect(Scheduler).toFlushUntilNextPaint([]);
133+
await waitForPaint([]);
133134

134135
expect(logs).toEqual([
135136
`group: ⚛️ render (${RETRY_LANE_STRING})`,

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

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
let React;
1111
let Scheduler;
12+
let waitForAll;
13+
let assertLog;
1214
let ReactNoop;
1315
let useState;
1416
let act;
@@ -32,6 +34,10 @@ describe('act warnings', () => {
3234
startTransition = React.startTransition;
3335
getCacheForType = React.unstable_getCacheForType;
3436
caches = [];
37+
38+
const InternalTestUtils = require('internal-test-utils');
39+
waitForAll = InternalTestUtils.waitForAll;
40+
assertLog = InternalTestUtils.assertLog;
3541
});
3642

3743
function createTextCache() {
@@ -134,17 +140,17 @@ describe('act warnings', () => {
134140
}
135141
}
136142

137-
function withActEnvironment(value, scope) {
143+
async function withActEnvironment(value, scope) {
138144
const prevValue = global.IS_REACT_ACT_ENVIRONMENT;
139145
global.IS_REACT_ACT_ENVIRONMENT = value;
140146
try {
141-
return scope();
147+
return await scope();
142148
} finally {
143149
global.IS_REACT_ACT_ENVIRONMENT = prevValue;
144150
}
145151
}
146152

147-
test('warns about unwrapped updates only if environment flag is enabled', () => {
153+
test('warns about unwrapped updates only if environment flag is enabled', async () => {
148154
let setState;
149155
function App() {
150156
const [state, _setState] = useState(0);
@@ -154,34 +160,34 @@ describe('act warnings', () => {
154160

155161
const root = ReactNoop.createRoot();
156162
root.render(<App />);
157-
expect(Scheduler).toFlushAndYield([0]);
163+
await waitForAll([0]);
158164
expect(root).toMatchRenderedOutput('0');
159165

160166
// Default behavior. Flag is undefined. No warning.
161167
expect(global.IS_REACT_ACT_ENVIRONMENT).toBe(undefined);
162168
setState(1);
163-
expect(Scheduler).toFlushAndYield([1]);
169+
await waitForAll([1]);
164170
expect(root).toMatchRenderedOutput('1');
165171

166172
// Flag is true. Warn.
167-
withActEnvironment(true, () => {
173+
await withActEnvironment(true, async () => {
168174
expect(() => setState(2)).toErrorDev(
169175
'An update to App inside a test was not wrapped in act',
170176
);
171-
expect(Scheduler).toFlushAndYield([2]);
177+
await waitForAll([2]);
172178
expect(root).toMatchRenderedOutput('2');
173179
});
174180

175181
// Flag is false. No warning.
176-
withActEnvironment(false, () => {
182+
await withActEnvironment(false, async () => {
177183
setState(3);
178-
expect(Scheduler).toFlushAndYield([3]);
184+
await waitForAll([3]);
179185
expect(root).toMatchRenderedOutput('3');
180186
});
181187
});
182188

183189
// @gate __DEV__
184-
test('act warns if the environment flag is not enabled', () => {
190+
test('act warns if the environment flag is not enabled', async () => {
185191
let setState;
186192
function App() {
187193
const [state, _setState] = useState(0);
@@ -191,7 +197,7 @@ describe('act warnings', () => {
191197

192198
const root = ReactNoop.createRoot();
193199
root.render(<App />);
194-
expect(Scheduler).toFlushAndYield([0]);
200+
await waitForAll([0]);
195201
expect(root).toMatchRenderedOutput('0');
196202

197203
// Default behavior. Flag is undefined. Warn.
@@ -204,20 +210,20 @@ describe('act warnings', () => {
204210
'The current testing environment is not configured to support act(...)',
205211
{withoutStack: true},
206212
);
207-
expect(Scheduler).toHaveYielded([1]);
213+
assertLog([1]);
208214
expect(root).toMatchRenderedOutput('1');
209215

210216
// Flag is true. Don't warn.
211-
withActEnvironment(true, () => {
217+
await withActEnvironment(true, () => {
212218
act(() => {
213219
setState(2);
214220
});
215-
expect(Scheduler).toHaveYielded([2]);
221+
assertLog([2]);
216222
expect(root).toMatchRenderedOutput('2');
217223
});
218224

219225
// Flag is false. Warn.
220-
withActEnvironment(false, () => {
226+
await withActEnvironment(false, () => {
221227
expect(() => {
222228
act(() => {
223229
setState(1);
@@ -226,13 +232,13 @@ describe('act warnings', () => {
226232
'The current testing environment is not configured to support act(...)',
227233
{withoutStack: true},
228234
);
229-
expect(Scheduler).toHaveYielded([1]);
235+
assertLog([1]);
230236
expect(root).toMatchRenderedOutput('1');
231237
});
232238
});
233239

234-
test('warns if root update is not wrapped', () => {
235-
withActEnvironment(true, () => {
240+
test('warns if root update is not wrapped', async () => {
241+
await withActEnvironment(true, () => {
236242
const root = ReactNoop.createRoot();
237243
expect(() => root.render('Hi')).toErrorDev(
238244
// TODO: Better error message that doesn't make it look like "Root" is
@@ -244,7 +250,7 @@ describe('act warnings', () => {
244250
});
245251

246252
// @gate __DEV__
247-
test('warns if class update is not wrapped', () => {
253+
test('warns if class update is not wrapped', async () => {
248254
let app;
249255
class App extends React.Component {
250256
state = {count: 0};
@@ -254,7 +260,7 @@ describe('act warnings', () => {
254260
}
255261
}
256262

257-
withActEnvironment(true, () => {
263+
await withActEnvironment(true, () => {
258264
const root = ReactNoop.createRoot();
259265
act(() => {
260266
root.render(<App />);
@@ -266,18 +272,18 @@ describe('act warnings', () => {
266272
});
267273

268274
// @gate __DEV__
269-
test('warns even if update is synchronous', () => {
275+
test('warns even if update is synchronous', async () => {
270276
let setState;
271277
function App() {
272278
const [state, _setState] = useState(0);
273279
setState = _setState;
274280
return <Text text={state} />;
275281
}
276282

277-
withActEnvironment(true, () => {
283+
await withActEnvironment(true, () => {
278284
const root = ReactNoop.createRoot();
279285
act(() => root.render(<App />));
280-
expect(Scheduler).toHaveYielded([0]);
286+
assertLog([0]);
281287
expect(root).toMatchRenderedOutput('0');
282288

283289
// Even though this update is synchronous, we should still fire a warning,
@@ -286,14 +292,14 @@ describe('act warnings', () => {
286292
'An update to App inside a test was not wrapped in act(...)',
287293
);
288294

289-
expect(Scheduler).toHaveYielded([1]);
295+
assertLog([1]);
290296
expect(root).toMatchRenderedOutput('1');
291297
});
292298
});
293299

294300
// @gate __DEV__
295301
// @gate enableLegacyCache
296-
test('warns if Suspense retry is not wrapped', () => {
302+
test('warns if Suspense retry is not wrapped', async () => {
297303
function App() {
298304
return (
299305
<Suspense fallback={<Text text="Loading..." />}>
@@ -302,12 +308,12 @@ describe('act warnings', () => {
302308
);
303309
}
304310

305-
withActEnvironment(true, () => {
311+
await withActEnvironment(true, () => {
306312
const root = ReactNoop.createRoot();
307313
act(() => {
308314
root.render(<App />);
309315
});
310-
expect(Scheduler).toHaveYielded(['Suspend! [Async]', 'Loading...']);
316+
assertLog(['Suspend! [Async]', 'Loading...']);
311317
expect(root).toMatchRenderedOutput('Loading...');
312318

313319
// This is a retry, not a ping, because we already showed a fallback.
@@ -321,7 +327,7 @@ describe('act warnings', () => {
321327

322328
// @gate __DEV__
323329
// @gate enableLegacyCache
324-
test('warns if Suspense ping is not wrapped', () => {
330+
test('warns if Suspense ping is not wrapped', async () => {
325331
function App({showMore}) {
326332
return (
327333
<Suspense fallback={<Text text="Loading..." />}>
@@ -330,20 +336,20 @@ describe('act warnings', () => {
330336
);
331337
}
332338

333-
withActEnvironment(true, () => {
339+
await withActEnvironment(true, () => {
334340
const root = ReactNoop.createRoot();
335341
act(() => {
336342
root.render(<App showMore={false} />);
337343
});
338-
expect(Scheduler).toHaveYielded(['(empty)']);
344+
assertLog(['(empty)']);
339345
expect(root).toMatchRenderedOutput('(empty)');
340346

341347
act(() => {
342348
startTransition(() => {
343349
root.render(<App showMore={true} />);
344350
});
345351
});
346-
expect(Scheduler).toHaveYielded(['Suspend! [Async]', 'Loading...']);
352+
assertLog(['Suspend! [Async]', 'Loading...']);
347353
expect(root).toMatchRenderedOutput('(empty)');
348354

349355
// This is a ping, not a retry, because no fallback is showing.

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

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ let React;
22
let ReactFeatureFlags;
33
let ReactNoop;
44
let Scheduler;
5+
let waitForAll;
6+
let assertLog;
57
let ReactCache;
68
let Suspense;
79
let TextResource;
@@ -18,6 +20,10 @@ describe('ReactBlockingMode', () => {
1820
ReactCache = require('react-cache');
1921
Suspense = React.Suspense;
2022

23+
const InternalTestUtils = require('internal-test-utils');
24+
waitForAll = InternalTestUtils.waitForAll;
25+
assertLog = InternalTestUtils.assertLog;
26+
2127
TextResource = ReactCache.unstable_createResource(
2228
([text, ms = 0]) => {
2329
return new Promise((resolve, reject) =>
@@ -52,7 +58,7 @@ describe('ReactBlockingMode', () => {
5258
}
5359
}
5460

55-
it('updates flush without yielding in the next event', () => {
61+
it('updates flush without yielding in the next event', async () => {
5662
const root = ReactNoop.createRoot();
5763

5864
root.render(
@@ -66,12 +72,11 @@ describe('ReactBlockingMode', () => {
6672
// Nothing should have rendered yet
6773
expect(root).toMatchRenderedOutput(null);
6874

69-
// Everything should render immediately in the next event
70-
expect(Scheduler).toFlushAndYield(['A', 'B', 'C']);
75+
await waitForAll(['A', 'B', 'C']);
7176
expect(root).toMatchRenderedOutput('ABC');
7277
});
7378

74-
it('layout updates flush synchronously in same event', () => {
79+
it('layout updates flush synchronously in same event', async () => {
7580
const {useLayoutEffect} = React;
7681

7782
function App() {
@@ -84,9 +89,9 @@ describe('ReactBlockingMode', () => {
8489
const root = ReactNoop.createRoot();
8590
root.render(<App />);
8691
expect(root).toMatchRenderedOutput(null);
87-
expect(Scheduler).toHaveYielded([]);
92+
assertLog([]);
8893

89-
expect(Scheduler).toFlushAndYield(['Hi', 'Layout effect']);
94+
await waitForAll(['Hi', 'Layout effect']);
9095
expect(root).toMatchRenderedOutput('Hi');
9196
});
9297

@@ -106,15 +111,15 @@ describe('ReactBlockingMode', () => {
106111
</Suspense>,
107112
);
108113

109-
expect(Scheduler).toFlushAndYield(['A', 'Suspend! [B]', 'C', 'Loading...']);
114+
await waitForAll(['A', 'Suspend! [B]', 'C', 'Loading...']);
110115
// In Legacy Mode, A and B would mount in a hidden primary tree. In
111116
// Concurrent Mode, nothing in the primary tree should mount. But the
112117
// fallback should mount immediately.
113118
expect(root).toMatchRenderedOutput('Loading...');
114119

115120
await jest.advanceTimersByTime(1000);
116-
expect(Scheduler).toHaveYielded(['Promise resolved [B]']);
117-
expect(Scheduler).toFlushAndYield(['A', 'B', 'C']);
121+
assertLog(['Promise resolved [B]']);
122+
await waitForAll(['A', 'B', 'C']);
118123
expect(root).toMatchRenderedOutput(
119124
<>
120125
<span>A</span>
@@ -124,7 +129,7 @@ describe('ReactBlockingMode', () => {
124129
);
125130
});
126131

127-
it('flushSync does not flush batched work', () => {
132+
it('flushSync does not flush batched work', async () => {
128133
const {useState, forwardRef, useImperativeHandle} = React;
129134
const root = ReactNoop.createRoot();
130135

@@ -143,8 +148,7 @@ describe('ReactBlockingMode', () => {
143148
</>,
144149
);
145150

146-
// Mount
147-
expect(Scheduler).toFlushAndYield(['A0', 'B0']);
151+
await waitForAll(['A0', 'B0']);
148152
expect(root).toMatchRenderedOutput('A0B0');
149153

150154
// Schedule a batched update to the first sibling
@@ -159,15 +163,13 @@ describe('ReactBlockingMode', () => {
159163

160164
// Now flush the first update
161165
if (gate(flags => flags.enableUnifiedSyncLane)) {
162-
expect(Scheduler).toHaveYielded(['A1', 'B1']);
166+
assertLog(['A1', 'B1']);
163167
expect(root).toMatchRenderedOutput('A1B1');
164168
} else {
165-
// Only the second update should have flushed synchronously
166-
expect(Scheduler).toHaveYielded(['B1']);
169+
assertLog(['B1']);
167170
expect(root).toMatchRenderedOutput('A0B1');
168171

169-
// Now flush the first update
170-
expect(Scheduler).toFlushAndYield(['A1']);
172+
await waitForAll(['A1']);
171173
expect(root).toMatchRenderedOutput('A1B1');
172174
}
173175
});

0 commit comments

Comments
 (0)