Codemod tests to waitFor pattern (2/?) (#26296)
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.
Andrew Clark committed
Mar 3, 2023 at 17:01 UTC
ce8a72fd4e7a6de12e57dc9db59b4b6ce92daa3b
14 files changed
+449
-388
packages/react-cache/src/__tests__/ReactCacheOld-test.internal.js
+34
-42
@@ -18,6 +18,8 @@ let Scheduler;
18
let Suspense;
19
let TextResource;
20
let textResourceShouldFail;
21
+let waitForAll;
22
+let assertLog;
23
24
describe('ReactCache', () => {
25
beforeEach(() => {
@@ -33,6 +35,10 @@ describe('ReactCache', () => {
35
ReactTestRenderer = require('react-test-renderer');
36
Scheduler = require('scheduler');
37
38
+ const InternalTestUtils = require('internal-test-utils');
39
+ waitForAll = InternalTestUtils.waitForAll;
40
+ assertLog = InternalTestUtils.assertLog;
41
+
42
TextResource = createResource(
43
([text, ms = 0]) => {
44
let listeners = null;
@@ -105,7 +111,7 @@ describe('ReactCache', () => {
111
}
112
}
113
108
- it('throws a promise if the requested value is not in the cache', () => {
114
+ it('throws a promise if the requested value is not in the cache', async () => {
115
function App() {
116
return (
117
<Suspense fallback={<Text text="Loading..." />}>
@@ -118,11 +124,11 @@ describe('ReactCache', () => {
124
unstable_isConcurrent: true,
125
});
126
121
- expect(Scheduler).toFlushAndYield(['Suspend! [Hi]', 'Loading...']);
127
+ await waitForAll(['Suspend! [Hi]', 'Loading...']);
128
129
jest.advanceTimersByTime(100);
124
- expect(Scheduler).toHaveYielded(['Promise resolved [Hi]']);
125
- expect(Scheduler).toFlushAndYield(['Hi']);
130
+ assertLog(['Promise resolved [Hi]']);
131
+ await waitForAll(['Hi']);
132
});
133
134
it('throws an error on the subsequent read if the promise is rejected', async () => {
@@ -138,22 +144,22 @@ describe('ReactCache', () => {
144
unstable_isConcurrent: true,
145
});
146
141
- expect(Scheduler).toFlushAndYield(['Suspend! [Hi]', 'Loading...']);
147
+ await waitForAll(['Suspend! [Hi]', 'Loading...']);
148
149
textResourceShouldFail = true;
150
jest.advanceTimersByTime(100);
145
- expect(Scheduler).toHaveYielded(['Promise rejected [Hi]']);
151
+ assertLog(['Promise rejected [Hi]']);
152
153
expect(Scheduler).toFlushAndThrow('Failed to load: Hi');
148
- expect(Scheduler).toHaveYielded(['Error! [Hi]', 'Error! [Hi]']);
154
+ assertLog(['Error! [Hi]', 'Error! [Hi]']);
155
156
// Should throw again on a subsequent read
157
root.update(<App />);
158
expect(Scheduler).toFlushAndThrow('Failed to load: Hi');
153
- expect(Scheduler).toHaveYielded(['Error! [Hi]', 'Error! [Hi]']);
159
+ assertLog(['Error! [Hi]', 'Error! [Hi]']);
160
});
161
156
- it('warns if non-primitive key is passed to a resource without a hash function', () => {
162
+ it('warns if non-primitive key is passed to a resource without a hash function', async () => {
163
const BadTextResource = createResource(([text, ms = 0]) => {
164
return new Promise((resolve, reject) =>
165
setTimeout(() => {
@@ -177,8 +183,8 @@ describe('ReactCache', () => {
183
);
184
185
if (__DEV__) {
180
- expect(() => {
181
- expect(Scheduler).toFlushAndYield(['App', 'Loading...']);
186
+ expect(async () => {
187
+ await waitForAll(['App', 'Loading...']);
188
}).toErrorDev([
189
'Invalid key type. Expected a string, number, symbol, or ' +
190
'boolean, but instead received: Hi,100\n\n' +
@@ -186,7 +192,7 @@ describe('ReactCache', () => {
192
'function as the second argument to createResource().',
193
]);
194
} else {
189
- expect(Scheduler).toFlushAndYield(['App', 'Loading...']);
195
+ await waitForAll(['App', 'Loading...']);
196
}
197
});
198
@@ -204,19 +210,19 @@ describe('ReactCache', () => {
210
unstable_isConcurrent: true,
211
},
212
);
207
- expect(Scheduler).toFlushAndYield([
213
+ await waitForAll([
214
'Suspend! [1]',
215
'Suspend! [2]',
216
'Suspend! [3]',
217
'Loading...',
218
]);
219
jest.advanceTimersByTime(100);
214
- expect(Scheduler).toHaveYielded([
220
+ assertLog([
221
'Promise resolved [1]',
222
'Promise resolved [2]',
223
'Promise resolved [3]',
224
]);
219
- expect(Scheduler).toFlushAndYield([1, 2, 3]);
225
+ await waitForAll([1, 2, 3]);
226
expect(root).toMatchRenderedOutput('123');
227
228
// Render 1, 4, 5
@@ -228,18 +234,10 @@ describe('ReactCache', () => {
234
</Suspense>,
235
);
236
231
- expect(Scheduler).toFlushAndYield([
232
- 1,
233
- 'Suspend! [4]',
234
- 'Suspend! [5]',
235
- 'Loading...',
236
- ]);
237
+ await waitForAll([1, 'Suspend! [4]', 'Suspend! [5]', 'Loading...']);
238
jest.advanceTimersByTime(100);
238
- expect(Scheduler).toHaveYielded([
239
- 'Promise resolved [4]',
240
- 'Promise resolved [5]',
241
- ]);
242
- expect(Scheduler).toFlushAndYield([1, 4, 5]);
239
+ assertLog(['Promise resolved [4]', 'Promise resolved [5]']);
240
+ await waitForAll([1, 4, 5]);
241
expect(root).toMatchRenderedOutput('145');
242
243
// We've now rendered values 1, 2, 3, 4, 5, over our limit of 3. The least
@@ -253,7 +251,7 @@ describe('ReactCache', () => {
251
</Suspense>,
252
);
253
256
- expect(Scheduler).toFlushAndYield([
254
+ await waitForAll([
255
// 1 is still cached
256
1,
257
// 2 and 3 suspend because they were evicted from the cache
@@ -262,11 +260,8 @@ describe('ReactCache', () => {
260
'Loading...',
261
]);
262
jest.advanceTimersByTime(100);
265
- expect(Scheduler).toHaveYielded([
266
- 'Promise resolved [2]',
267
- 'Promise resolved [3]',
268
- ]);
269
- expect(Scheduler).toFlushAndYield([1, 2, 3]);
263
+ assertLog(['Promise resolved [2]', 'Promise resolved [3]']);
264
+ await waitForAll([1, 2, 3]);
265
expect(root).toMatchRenderedOutput('123');
266
});
267
@@ -287,18 +282,15 @@ describe('ReactCache', () => {
282
},
283
);
284
290
- expect(Scheduler).toFlushAndYield(['Loading...']);
285
+ await waitForAll(['Loading...']);
286
287
jest.advanceTimersByTime(1000);
293
- expect(Scheduler).toHaveYielded([
294
- 'Promise resolved [B]',
295
- 'Promise resolved [A]',
296
- ]);
297
- expect(Scheduler).toFlushAndYield(['Result']);
288
+ assertLog(['Promise resolved [B]', 'Promise resolved [A]']);
289
+ await waitForAll(['Result']);
290
expect(root).toMatchRenderedOutput('Result');
291
});
292
301
- it('if a thenable resolves multiple times, does not update the first cached value', () => {
293
+ it('if a thenable resolves multiple times, does not update the first cached value', async () => {
294
let resolveThenable;
295
const BadTextResource = createResource(
296
([text, ms = 0]) => {
@@ -349,7 +341,7 @@ describe('ReactCache', () => {
341
},
342
);
343
352
- expect(Scheduler).toFlushAndYield(['Suspend! [Hi]', 'Loading...']);
344
+ await waitForAll(['Suspend! [Hi]', 'Loading...']);
345
346
resolveThenable('Hi');
347
// This thenable improperly resolves twice. We should not update the
@@ -365,8 +357,8 @@ describe('ReactCache', () => {
357
},
358
);
359
368
- expect(Scheduler).toHaveYielded([]);
369
- expect(Scheduler).toFlushAndYield(['Hi']);
360
+ assertLog([]);
361
+ await waitForAll(['Hi']);
362
expect(root).toMatchRenderedOutput('Hi');
363
});
364
packages/react-client/src/__tests__/ReactFlight-test.js
+9
-6
@@ -20,6 +20,7 @@ let ReactNoopFlightClient;
20
let ErrorBoundary;
21
let NoErrorExpected;
22
let Scheduler;
23
+let assertLog;
24
25
describe('ReactFlight', () => {
26
beforeEach(() => {
@@ -33,6 +34,8 @@ describe('ReactFlight', () => {
34
ReactNoopFlightClient = require('react-noop-renderer/flight-client');
35
act = require('jest-react').act;
36
Scheduler = require('scheduler');
37
+ const InternalTestUtils = require('internal-test-utils');
38
+ assertLog = InternalTestUtils.assertLog;
39
40
ErrorBoundary = class extends React.Component {
41
state = {hasError: false, error: null};
@@ -808,13 +811,13 @@ describe('ReactFlight', () => {
811
const ClientDoublerModuleRef = clientReference(ClientDoubler);
812
813
const transport = ReactNoopFlightServer.render(<App />);
811
- expect(Scheduler).toHaveYielded([]);
814
+ assertLog([]);
815
816
await act(async () => {
817
ReactNoop.render(await ReactNoopFlightClient.read(transport));
818
});
819
817
- expect(Scheduler).toHaveYielded(['ClientDoubler']);
820
+ assertLog(['ClientDoubler']);
821
expect(ReactNoop).toMatchRenderedOutput(
822
<>
823
<div prop=":S1:">:S1:</div>
@@ -997,7 +1000,7 @@ describe('ReactFlight', () => {
1000
1001
const transport = ReactNoopFlightServer.render(<Foo />);
1002
1000
- expect(Scheduler).toHaveYielded(['suspended']);
1003
+ assertLog(['suspended']);
1004
1005
await act(async () => {
1006
resolve();
@@ -1005,7 +1008,7 @@ describe('ReactFlight', () => {
1008
jest.runAllImmediates();
1009
});
1010
1008
- expect(Scheduler).toHaveYielded(['rendered']);
1011
+ assertLog(['rendered']);
1012
1013
await act(async () => {
1014
ServerContext._currentRenderer = null;
@@ -1045,7 +1048,7 @@ describe('ReactFlight', () => {
1048
1049
const transport = ReactNoopFlightServer.render(model);
1050
1048
- expect(Scheduler).toHaveYielded([]);
1051
+ assertLog([]);
1052
1053
await act(async () => {
1054
ServerContext._currentRenderer = null;
@@ -1054,7 +1057,7 @@ describe('ReactFlight', () => {
1057
ReactNoop.render(flightModel.foo);
1058
});
1059
1057
- expect(Scheduler).toHaveYielded(['ClientBar']);
1060
+ assertLog(['ClientBar']);
1061
expect(ReactNoop).toMatchRenderedOutput(<span>hi this is server</span>);
1062
1063
expect(() => {
packages/react-debug-tools/src/__tests__/ReactDevToolsHooksIntegration-test.js
+5
-1
@@ -19,6 +19,7 @@ describe('React hooks DevTools integration', () => {
19
let overrideHookState;
20
let scheduleUpdate;
21
let setSuspenseHandler;
22
+ let waitForAll;
23
24
global.IS_REACT_ACT_ENVIRONMENT = true;
25
@@ -41,6 +42,9 @@ describe('React hooks DevTools integration', () => {
42
ReactTestRenderer = require('react-test-renderer');
43
Scheduler = require('scheduler');
44
45
+ const InternalTestUtils = require('internal-test-utils');
46
+ waitForAll = InternalTestUtils.waitForAll;
47
+
48
act = ReactTestRenderer.act;
49
});
50
@@ -256,7 +260,7 @@ describe('React hooks DevTools integration', () => {
260
),
261
);
262
259
- expect(Scheduler).toFlushAndYield([]);
263
+ await waitForAll([]);
264
// Ensure we timeout any suspense time.
265
jest.advanceTimersByTime(1000);
266
const fiber = renderer.root._currentFiber().child;
packages/react-devtools-shared/src/__tests__/TimelineProfiler-test.js
+83
-69
@@ -20,6 +20,10 @@ describe('Timeline profiler', () => {
20
let store;
21
let unmountFns;
22
let utils;
23
+ let waitFor;
24
+ let waitForAll;
25
+ let waitForPaint;
26
+ let assertLog;
27
28
beforeEach(() => {
29
utils = require('./utils');
@@ -44,6 +48,12 @@ describe('Timeline profiler', () => {
48
ReactDOMClient = require('react-dom/client');
49
Scheduler = require('scheduler');
50
51
+ const InternalTestUtils = require('internal-test-utils');
52
+ waitFor = InternalTestUtils.waitFor;
53
+ waitForAll = InternalTestUtils.waitForAll;
54
+ waitForPaint = InternalTestUtils.waitForPaint;
55
+ assertLog = InternalTestUtils.assertLog;
56
+
57
store = global.store;
58
});
59
@@ -151,7 +161,7 @@ describe('Timeline profiler', () => {
161
`);
162
});
163
154
- it('should mark concurrent render without suspends or state updates', () => {
164
+ it('should mark concurrent render without suspends or state updates', async () => {
165
renderRootHelper(<div />);
166
167
expect(clearedMarks).toMatchInlineSnapshot(`
@@ -162,7 +172,7 @@ describe('Timeline profiler', () => {
172
173
clearPendingMarks();
174
165
- expect(Scheduler).toFlushUntilNextPaint([]);
175
+ await waitForPaint([]);
176
177
expect(clearedMarks).toMatchInlineSnapshot(`
178
[
@@ -196,8 +206,7 @@ describe('Timeline profiler', () => {
206
renderRootHelper(<Foo />);
207
});
208
199
- // Do one step of work.
200
- expect(Scheduler).toFlushAndYieldThrough(['Foo']);
209
+ await waitFor(['Foo']);
210
211
expect(clearedMarks).toMatchInlineSnapshot(`
212
[
@@ -291,7 +300,11 @@ describe('Timeline profiler', () => {
300
});
301
302
it('should mark concurrent render with suspense that resolves', async () => {
294
- const fakeSuspensePromise = Promise.resolve(true);
303
+ let resolveFakePromise;
304
+ const fakeSuspensePromise = new Promise(
305
+ resolve => (resolveFakePromise = resolve),
306
+ );
307
+
308
function Example() {
309
throw fakeSuspensePromise;
310
}
@@ -310,7 +323,7 @@ describe('Timeline profiler', () => {
323
324
clearPendingMarks();
325
313
- expect(Scheduler).toFlushUntilNextPaint([]);
326
+ await waitForPaint([]);
327
328
expect(clearedMarks).toMatchInlineSnapshot(`
329
[
@@ -333,7 +346,7 @@ describe('Timeline profiler', () => {
346
347
clearPendingMarks();
348
336
- await fakeSuspensePromise;
349
+ await resolveFakePromise();
350
expect(clearedMarks).toMatchInlineSnapshot(`
351
[
352
"--suspense-resolved-0-Example",
@@ -342,7 +355,11 @@ describe('Timeline profiler', () => {
355
});
356
357
it('should mark concurrent render with suspense that rejects', async () => {
345
- const fakeSuspensePromise = Promise.reject(new Error('error'));
358
+ let rejectFakePromise;
359
+ const fakeSuspensePromise = new Promise(
360
+ (_, reject) => (rejectFakePromise = reject),
361
+ );
362
+
363
function Example() {
364
throw fakeSuspensePromise;
365
}
@@ -361,7 +378,7 @@ describe('Timeline profiler', () => {
378
379
clearPendingMarks();
380
364
- expect(Scheduler).toFlushUntilNextPaint([]);
381
+ await waitForPaint([]);
382
383
expect(clearedMarks).toMatchInlineSnapshot(`
384
[
@@ -384,7 +401,10 @@ describe('Timeline profiler', () => {
401
402
clearPendingMarks();
403
387
- await expect(fakeSuspensePromise).rejects.toThrow();
404
+ await expect(() => {
405
+ rejectFakePromise(new Error('error'));
406
+ return fakeSuspensePromise;
407
+ }).rejects.toThrow();
408
expect(clearedMarks).toMatchInlineSnapshot(`
409
[
410
"--suspense-rejected-0-Example",
@@ -392,7 +412,7 @@ describe('Timeline profiler', () => {
412
`);
413
});
414
395
- it('should mark cascading class component state updates', () => {
415
+ it('should mark cascading class component state updates', async () => {
416
class Example extends React.Component {
417
state = {didMount: false};
418
componentDidMount() {
@@ -413,7 +433,7 @@ describe('Timeline profiler', () => {
433
434
clearPendingMarks();
435
416
- expect(Scheduler).toFlushUntilNextPaint([]);
436
+ await waitForPaint([]);
437
438
expect(clearedMarks).toMatchInlineSnapshot(`
439
[
@@ -446,7 +466,7 @@ describe('Timeline profiler', () => {
466
`);
467
});
468
449
- it('should mark cascading class component force updates', () => {
469
+ it('should mark cascading class component force updates', async () => {
470
class Example extends React.Component {
471
componentDidMount() {
472
this.forceUpdate();
@@ -466,7 +486,7 @@ describe('Timeline profiler', () => {
486
487
clearPendingMarks();
488
469
- expect(Scheduler).toFlushUntilNextPaint([]);
489
+ await waitForPaint([]);
490
491
expect(clearedMarks).toMatchInlineSnapshot(`
492
[
@@ -499,7 +519,7 @@ describe('Timeline profiler', () => {
519
`);
520
});
521
502
- it('should mark render phase state updates for class component', () => {
522
+ it('should mark render phase state updates for class component', async () => {
523
class Example extends React.Component {
524
state = {didRender: false};
525
render() {
@@ -525,7 +545,7 @@ describe('Timeline profiler', () => {
545
errorMessage = message;
546
});
547
528
- expect(Scheduler).toFlushUntilNextPaint([]);
548
+ await waitForPaint([]);
549
550
expect(console.error).toHaveBeenCalledTimes(1);
551
expect(errorMessage).toContain(
@@ -552,7 +572,7 @@ describe('Timeline profiler', () => {
572
`);
573
});
574
555
- it('should mark render phase force updates for class component', () => {
575
+ it('should mark render phase force updates for class component', async () => {
576
let forced = false;
577
class Example extends React.Component {
578
render() {
@@ -579,7 +599,7 @@ describe('Timeline profiler', () => {
599
errorMessage = message;
600
});
601
582
- expect(Scheduler).toFlushUntilNextPaint([]);
602
+ await waitForPaint([]);
603
604
expect(console.error).toHaveBeenCalledTimes(1);
605
expect(errorMessage).toContain(
@@ -606,7 +626,7 @@ describe('Timeline profiler', () => {
626
`);
627
});
628
609
- it('should mark cascading layout updates', () => {
629
+ it('should mark cascading layout updates', async () => {
630
function Example() {
631
const [didMount, setDidMount] = React.useState(false);
632
React.useLayoutEffect(() => {
@@ -625,7 +645,7 @@ describe('Timeline profiler', () => {
645
646
clearPendingMarks();
647
628
- expect(Scheduler).toFlushUntilNextPaint([]);
648
+ await waitForPaint([]);
649
650
expect(clearedMarks).toMatchInlineSnapshot(`
651
[
@@ -660,7 +680,7 @@ describe('Timeline profiler', () => {
680
`);
681
});
682
663
- it('should mark cascading passive updates', () => {
683
+ it('should mark cascading passive updates', async () => {
684
function Example() {
685
const [didMount, setDidMount] = React.useState(false);
686
React.useEffect(() => {
@@ -671,7 +691,7 @@ describe('Timeline profiler', () => {
691
692
renderRootHelper(<Example />);
693
674
- expect(Scheduler).toFlushAndYield([]);
694
+ await waitForAll([]);
695
696
expect(clearedMarks).toMatchInlineSnapshot(`
697
[
@@ -709,7 +729,7 @@ describe('Timeline profiler', () => {
729
`);
730
});
731
712
- it('should mark render phase updates', () => {
732
+ it('should mark render phase updates', async () => {
733
function Example() {
734
const [didRender, setDidRender] = React.useState(false);
735
if (!didRender) {
@@ -720,7 +740,7 @@ describe('Timeline profiler', () => {
740
741
renderRootHelper(<Example />);
742
723
- expect(Scheduler).toFlushAndYield([]);
743
+ await waitForAll([]);
744
745
expect(clearedMarks).toMatchInlineSnapshot(`
746
[
@@ -840,7 +860,7 @@ describe('Timeline profiler', () => {
860
861
clearPendingMarks();
862
843
- expect(Scheduler).toFlushUntilNextPaint([]);
863
+ await waitForPaint([]);
864
865
expect(clearedMarks).toMatchInlineSnapshot(`
866
[
@@ -927,10 +947,7 @@ describe('Timeline profiler', () => {
947
948
const unmount = renderRootHelper(<ComponentWithEffects />);
949
930
- expect(Scheduler).toFlushUntilNextPaint([
931
- 'layout 1 mount',
932
- 'layout 2 mount',
933
- ]);
950
+ await waitForPaint(['layout 1 mount', 'layout 2 mount']);
951
952
expect(clearedMarks).toMatchInlineSnapshot(`
953
[
@@ -957,7 +974,7 @@ describe('Timeline profiler', () => {
974
975
clearPendingMarks();
976
960
- expect(Scheduler).toFlushAndYield([
977
+ await waitForAll([
978
'passive 1 mount',
979
'passive 2 mount',
980
'passive 3 mount',
@@ -978,11 +995,11 @@ describe('Timeline profiler', () => {
995
996
clearPendingMarks();
997
981
- expect(Scheduler).toFlushAndYield([]);
998
+ await waitForAll([]);
999
1000
unmount();
1001
985
- expect(Scheduler).toHaveYielded([
1002
+ assertLog([
1003
'layout 1 unmount',
1004
'layout 2 unmount',
1005
'passive 1 unmount',
@@ -1063,7 +1080,7 @@ describe('Timeline profiler', () => {
1080
}
1081
1082
renderRootHelper(<App />);
1066
- expect(Scheduler).toFlushAndYield([]);
1083
+ await waitForAll([]);
1084
1085
clearedMarks.splice(0);
1086
@@ -1102,7 +1119,7 @@ describe('Timeline profiler', () => {
1119
}
1120
1121
renderRootHelper(<App />);
1105
- expect(Scheduler).toFlushAndYield([]);
1122
+ await waitForAll([]);
1123
1124
clearedMarks.splice(0);
1125
@@ -1110,7 +1127,7 @@ describe('Timeline profiler', () => {
1127
event.initEvent('mouseover', true, true);
1128
dispatchAndSetCurrentEvent(targetRef.current, event);
1129
1113
- expect(Scheduler).toFlushAndYield([]);
1130
+ await waitForAll([]);
1131
1132
expect(clearedMarks).toMatchInlineSnapshot(`
1133
[
@@ -1324,11 +1341,11 @@ describe('Timeline profiler', () => {
1341
});
1342
1343
// Do one step of work.
1327
- expect(Scheduler).toFlushAndYieldThrough(['Foo']);
1344
+ await waitFor(['Foo']);
1345
1346
// Finish flushing so React commits;
1347
// Unless we do this, the ProfilerStore won't collect Profiling data.
1331
- expect(Scheduler).toFlushAndYield(['Bar']);
1348
+ await waitForAll(['Bar']);
1349
1350
// Since we yielded, the batch should report two separate "render" chunks.
1351
const batch = getBatchOfWork(0);
@@ -1359,13 +1376,13 @@ describe('Timeline profiler', () => {
1376
</React.Suspense>,
1377
);
1378
1362
- expect(Scheduler).toHaveYielded(['suspended']);
1379
+ assertLog(['suspended']);
1380
1381
Scheduler.unstable_advanceTime(10);
1382
resolveFn();
1383
await suspensePromise;
1384
1368
- expect(Scheduler).toFlushAndYield(['resolved']);
1385
+ await waitForAll(['resolved']);
1386
1387
const timelineData = stopProfilingAndGetTimelineData();
1388
@@ -1417,13 +1434,13 @@ describe('Timeline profiler', () => {
1434
</React.Suspense>,
1435
);
1436
1420
- expect(Scheduler).toHaveYielded(['suspended']);
1437
+ assertLog(['suspended']);
1438
1439
Scheduler.unstable_advanceTime(10);
1440
rejectFn();
1441
await expect(suspensePromise).rejects.toThrow();
1442
1426
- expect(Scheduler).toHaveYielded(['rejected']);
1443
+ assertLog(['rejected']);
1444
1445
const timelineData = stopProfilingAndGetTimelineData();
1446
@@ -1475,13 +1492,13 @@ describe('Timeline profiler', () => {
1492
</React.Suspense>,
1493
);
1494
1478
- expect(Scheduler).toFlushAndYield(['suspended']);
1495
+ await waitForAll(['suspended']);
1496
1497
Scheduler.unstable_advanceTime(10);
1498
resolveFn();
1499
await suspensePromise;
1500
1484
- expect(Scheduler).toFlushAndYield(['resolved']);
1501
+ await waitForAll(['resolved']);
1502
1503
const timelineData = stopProfilingAndGetTimelineData();
1504
@@ -1533,13 +1550,13 @@ describe('Timeline profiler', () => {
1550
</React.Suspense>,
1551
);
1552
1536
- expect(Scheduler).toFlushAndYield(['suspended']);
1553
+ await waitForAll(['suspended']);
1554
1555
Scheduler.unstable_advanceTime(10);
1556
rejectFn();
1557
await expect(suspensePromise).rejects.toThrow();
1558
1542
- expect(Scheduler).toFlushAndYield(['rejected']);
1559
+ await waitForAll(['rejected']);
1560
1561
const timelineData = stopProfilingAndGetTimelineData();
1562
@@ -1566,7 +1583,7 @@ describe('Timeline profiler', () => {
1583
expect(timelineData.componentMeasures).toHaveLength(2);
1584
});
1585
1569
- it('should mark cascading class component state updates', () => {
1586
+ it('should mark cascading class component state updates', async () => {
1587
class Example extends React.Component {
1588
state = {didMount: false};
1589
componentDidMount() {
@@ -1583,7 +1600,7 @@ describe('Timeline profiler', () => {
1600
1601
renderRootHelper(<Example />);
1602
1586
- expect(Scheduler).toFlushUntilNextPaint(['mount', 'update']);
1603
+ await waitForPaint(['mount', 'update']);
1604
1605
const timelineData = stopProfilingAndGetTimelineData();
1606
expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);
@@ -1626,7 +1643,7 @@ describe('Timeline profiler', () => {
1643
`);
1644
});
1645
1629
- it('should mark cascading class component force updates', () => {
1646
+ it('should mark cascading class component force updates', async () => {
1647
let forced = false;
1648
class Example extends React.Component {
1649
componentDidMount() {
@@ -1642,7 +1659,7 @@ describe('Timeline profiler', () => {
1659
1660
renderRootHelper(<Example />);
1661
1645
- expect(Scheduler).toFlushUntilNextPaint(['mount', 'force update']);
1662
+ await waitForPaint(['mount', 'force update']);
1663
1664
const timelineData = stopProfilingAndGetTimelineData();
1665
expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);
@@ -1683,7 +1700,7 @@ describe('Timeline profiler', () => {
1700
`);
1701
});
1702
1686
- it('should mark render phase state updates for class component', () => {
1703
+ it('should mark render phase state updates for class component', async () => {
1704
class Example extends React.Component {
1705
state = {didRender: false};
1706
render() {
@@ -1705,7 +1722,7 @@ describe('Timeline profiler', () => {
1722
errorMessage = message;
1723
});
1724
1708
- expect(Scheduler).toFlushAndYield(['first render', 'second render']);
1725
+ await waitForAll(['first render', 'second render']);
1726
1727
expect(console.error).toHaveBeenCalledTimes(1);
1728
expect(errorMessage).toContain(
@@ -1753,7 +1770,7 @@ describe('Timeline profiler', () => {
1770
`);
1771
});
1772
1756
- it('should mark render phase force updates for class component', () => {
1773
+ it('should mark render phase force updates for class component', async () => {
1774
let forced = false;
1775
class Example extends React.Component {
1776
render() {
@@ -1774,7 +1791,7 @@ describe('Timeline profiler', () => {
1791
errorMessage = message;
1792
});
1793
1777
- expect(Scheduler).toFlushAndYield(['render', 'force update']);
1794
+ await waitForAll(['render', 'force update']);
1795
1796
expect(console.error).toHaveBeenCalledTimes(1);
1797
expect(errorMessage).toContain(
@@ -1820,7 +1837,7 @@ describe('Timeline profiler', () => {
1837
`);
1838
});
1839
1823
- it('should mark cascading layout updates', () => {
1840
+ it('should mark cascading layout updates', async () => {
1841
function Example() {
1842
const [didMount, setDidMount] = React.useState(false);
1843
React.useLayoutEffect(() => {
@@ -1834,7 +1851,7 @@ describe('Timeline profiler', () => {
1851
1852
renderRootHelper(<Example />);
1853
1837
- expect(Scheduler).toFlushAndYield(['mount', 'update']);
1854
+ await waitForAll(['mount', 'update']);
1855
1856
const timelineData = stopProfilingAndGetTimelineData();
1857
expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);
@@ -1884,7 +1901,7 @@ describe('Timeline profiler', () => {
1901
`);
1902
});
1903
1887
- it('should mark cascading passive updates', () => {
1904
+ it('should mark cascading passive updates', async () => {
1905
function Example() {
1906
const [didMount, setDidMount] = React.useState(false);
1907
React.useEffect(() => {
@@ -1897,7 +1914,7 @@ describe('Timeline profiler', () => {
1914
}
1915
1916
renderRootHelper(<Example />);
1900
- expect(Scheduler).toFlushAndYield(['mount', 'update']);
1917
+ await waitForAll(['mount', 'update']);
1918
1919
const timelineData = stopProfilingAndGetTimelineData();
1920
expect(timelineData.batchUIDToMeasuresMap.size).toBe(2);
@@ -1947,7 +1964,7 @@ describe('Timeline profiler', () => {
1964
`);
1965
});
1966
1950
- it('should mark render phase updates', () => {
1967
+ it('should mark render phase updates', async () => {
1968
function Example() {
1969
const [didRender, setDidRender] = React.useState(false);
1970
Scheduler.unstable_advanceTime(10);
@@ -1959,7 +1976,7 @@ describe('Timeline profiler', () => {
1976
}
1977
1978
renderRootHelper(<Example />);
1962
- expect(Scheduler).toFlushAndYield(['mount', 'update']);
1979
+ await waitForAll(['mount', 'update']);
1980
1981
const timelineData = stopProfilingAndGetTimelineData();
1982
// Render phase updates should be retried as part of the same batch.
@@ -2026,7 +2043,7 @@ describe('Timeline profiler', () => {
2043
</ErrorBoundary>,
2044
);
2045
2029
- expect(Scheduler).toHaveYielded([
2046
+ assertLog([
2047
'ErrorBoundary render',
2048
'ExampleThatThrows',
2049
'ExampleThatThrows',
@@ -2122,7 +2139,7 @@ describe('Timeline profiler', () => {
2139
</ErrorBoundary>,
2140
);
2141
2125
- expect(Scheduler).toFlushAndYield([
2142
+ await waitForAll([
2143
'ErrorBoundary render',
2144
'ExampleThatThrows',
2145
'ExampleThatThrows',
@@ -2253,22 +2270,19 @@ describe('Timeline profiler', () => {
2270
2271
const unmount = renderRootHelper(<ComponentWithEffects />);
2272
2256
- expect(Scheduler).toFlushUntilNextPaint([
2257
- 'layout 1 mount',
2258
- 'layout 2 mount',
2259
- ]);
2273
+ await waitForPaint(['layout 1 mount', 'layout 2 mount']);
2274
2261
- expect(Scheduler).toFlushAndYield([
2275
+ await waitForAll([
2276
'passive 1 mount',
2277
'passive 2 mount',
2278
'passive 3 mount',
2279
]);
2280
2267
- expect(Scheduler).toFlushAndYield([]);
2281
+ await waitForAll([]);
2282
2283
unmount();
2284
2271
- expect(Scheduler).toHaveYielded([
2285
+ assertLog([
2286
'layout 1 unmount',
2287
'layout 2 unmount',
2288
'passive 1 unmount',
@@ -2465,7 +2479,7 @@ describe('Timeline profiler', () => {
2479
2480
renderRootHelper(<CommponentWithChildren initialRender={false} />);
2481
2468
- expect(Scheduler).toFlushAndYield([
2482
+ await waitForAll([
2483
'Render ComponentWithChildren',
2484
'Render Child',
2485
'Render Child',
packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js
+6
-2
@@ -15,6 +15,7 @@ let ReactDOM;
15
let ReactDOMClient;
16
let Scheduler;
17
let act;
18
+let waitForAll;
19
20
const setUntrackedInputValue = Object.getOwnPropertyDescriptor(
21
HTMLInputElement.prototype,
@@ -33,6 +34,9 @@ describe('ReactDOMFiberAsync', () => {
34
act = require('jest-react').act;
35
Scheduler = require('scheduler');
36
37
+ const InternalTestUtils = require('internal-test-utils');
38
+ waitForAll = InternalTestUtils.waitForAll;
39
+
40
document.body.appendChild(container);
41
});
42
@@ -592,7 +596,7 @@ describe('ReactDOMFiberAsync', () => {
596
expect(containerC.textContent).toEqual('Finished');
597
});
598
595
- it('updates flush without yielding in the next event', () => {
599
+ it('updates flush without yielding in the next event', async () => {
600
const root = ReactDOMClient.createRoot(container);
601
602
function Text(props) {
@@ -612,7 +616,7 @@ describe('ReactDOMFiberAsync', () => {
616
expect(container.textContent).toEqual('');
617
618
// Everything should render immediately in the next event
615
- expect(Scheduler).toFlushAndYield(['A', 'B', 'C']);
619
+ await waitForAll(['A', 'B', 'C']);
620
expect(container.textContent).toEqual('ABC');
621
});
622
packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
+88
-78
@@ -38,6 +38,10 @@ let buffer = '';
38
let hasErrored = false;
39
let fatalError = undefined;
40
let renderOptions;
41
+let waitFor;
42
+let waitForAll;
43
+let assertLog;
44
+let waitForPaint;
45
46
function resetJSDOM(markup) {
47
// Test Environment
@@ -65,6 +69,12 @@ describe('ReactDOMFizzServer', () => {
69
70
PropTypes = require('prop-types');
71
72
+ const InternalTestUtils = require('internal-test-utils');
73
+ waitForAll = InternalTestUtils.waitForAll;
74
+ waitFor = InternalTestUtils.waitFor;
75
+ waitForPaint = InternalTestUtils.waitForPaint;
76
+ assertLog = InternalTestUtils.assertLog;
77
+
78
if (gate(flags => flags.source)) {
79
// The `with-selector` module composes the main `use-sync-external-store`
80
// entrypoint. In the compiled artifacts, this is resolved to the `shim`
@@ -562,7 +572,7 @@ describe('ReactDOMFizzServer', () => {
572
expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);
573
574
// Now we can client render it instead.
565
- expect(Scheduler).toFlushAndYield([]);
575
+ await waitForAll([]);
576
expectErrors(
577
errors,
578
[
@@ -684,7 +694,7 @@ describe('ReactDOMFizzServer', () => {
694
expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);
695
696
// Now we can client render it instead.
687
- expect(Scheduler).toFlushAndYield([]);
697
+ await waitForAll([]);
698
699
expectErrors(
700
errors,
@@ -843,7 +853,7 @@ describe('ReactDOMFizzServer', () => {
853
expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);
854
855
// Now we can client render it instead.
846
- expect(Scheduler).toFlushAndYield([]);
856
+ await waitForAll([]);
857
858
expectErrors(
859
errors,
@@ -1161,7 +1171,7 @@ describe('ReactDOMFizzServer', () => {
1171
});
1172
1173
// We still can't render it on the client.
1164
- expect(Scheduler).toFlushAndYield([]);
1174
+ await waitForAll([]);
1175
expectErrors(
1176
errors,
1177
[
@@ -1883,7 +1893,7 @@ describe('ReactDOMFizzServer', () => {
1893
expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);
1894
1895
// That will let us client render it instead.
1886
- expect(Scheduler).toFlushAndYield([]);
1896
+ await waitForAll([]);
1897
expectErrors(
1898
errors,
1899
[
@@ -2139,7 +2149,7 @@ describe('ReactDOMFizzServer', () => {
2149
);
2150
pipe(writable);
2151
});
2142
- expect(Scheduler).toHaveYielded(['server']);
2152
+ assertLog(['server']);
2153
2154
ReactDOMClient.hydrateRoot(container, <App />, {
2155
onRecoverableError(error) {
@@ -2149,9 +2159,9 @@ describe('ReactDOMFizzServer', () => {
2159
},
2160
});
2161
2152
- expect(() => {
2162
+ await expect(async () => {
2163
// The first paint switches to client rendering due to mismatch
2154
- expect(Scheduler).toFlushUntilNextPaint([
2164
+ await waitForPaint([
2165
'client',
2166
'Log recoverable error: Hydration failed because the initial ' +
2167
'UI does not match what was rendered on the server.',
@@ -2224,7 +2234,7 @@ describe('ReactDOMFizzServer', () => {
2234
);
2235
pipe(writable);
2236
});
2227
- expect(Scheduler).toHaveYielded(['server']);
2237
+ assertLog(['server']);
2238
2239
ReactDOMClient.hydrateRoot(container, <App />, {
2240
onRecoverableError(error) {
@@ -2235,9 +2245,9 @@ describe('ReactDOMFizzServer', () => {
2245
});
2246
2247
// The first paint uses the client due to mismatch forcing client render
2238
- expect(() => {
2248
+ await expect(async () => {
2249
// The first paint switches to client rendering due to mismatch
2240
- expect(Scheduler).toFlushUntilNextPaint([
2250
+ await waitForPaint([
2251
'client',
2252
'Log recoverable error: Hydration failed because the initial ' +
2253
'UI does not match what was rendered on the server.',
@@ -2304,7 +2314,7 @@ describe('ReactDOMFizzServer', () => {
2314
const {pipe} = renderToPipeableStream(<App />);
2315
pipe(writable);
2316
});
2307
- expect(Scheduler).toHaveYielded(['Yay!']);
2317
+ assertLog(['Yay!']);
2318
2319
const span = container.getElementsByTagName('span')[0];
2320
@@ -2319,8 +2329,8 @@ describe('ReactDOMFizzServer', () => {
2329
2330
// An error logged but instead of surfacing it to the UI, we switched
2331
// to client rendering.
2322
- expect(() => {
2323
- expect(Scheduler).toFlushAndYield([
2332
+ await expect(async () => {
2333
+ await waitForAll([
2334
'Yay!',
2335
'Hydration error',
2336
'There was an error while hydrating. Because the error happened ' +
@@ -2394,7 +2404,7 @@ describe('ReactDOMFizzServer', () => {
2404
const {pipe} = renderToPipeableStream(<App />);
2405
pipe(writable);
2406
});
2397
- expect(Scheduler).toHaveYielded(['Yay!']);
2407
+ assertLog(['Yay!']);
2408
2409
const [span1, span2, span3] = container.getElementsByTagName('span');
2410
@@ -2409,7 +2419,7 @@ describe('ReactDOMFizzServer', () => {
2419
2420
// An error logged but instead of surfacing it to the UI, we switched
2421
// to client rendering.
2412
- expect(Scheduler).toFlushAndYield([
2422
+ await waitForAll([
2423
'Yay!',
2424
'Hydration error',
2425
'There was an error while hydrating this Suspense boundary. Switched to client rendering.',
@@ -2484,7 +2494,7 @@ describe('ReactDOMFizzServer', () => {
2494
const {pipe} = renderToPipeableStream(<App />);
2495
pipe(writable);
2496
});
2487
- expect(Scheduler).toHaveYielded(['Yay!']);
2497
+ assertLog(['Yay!']);
2498
2499
// Hydrate the tree. Child will throw during render.
2500
isClient = true;
@@ -2497,7 +2507,7 @@ describe('ReactDOMFizzServer', () => {
2507
2508
// Because we failed to recover from the error, onRecoverableError
2509
// shouldn't be called.
2500
- expect(Scheduler).toFlushAndYield([]);
2510
+ await waitForAll([]);
2511
expect(getVisibleChildren(container)).toEqual('Oops!');
2512
2513
expectErrors(errors, [], []);
@@ -2541,7 +2551,7 @@ describe('ReactDOMFizzServer', () => {
2551
});
2552
pipe(writable);
2553
});
2544
- expect(Scheduler).toHaveYielded(['[s!] Oops.']);
2554
+ assertLog(['[s!] Oops.']);
2555
2556
// The server could not complete this boundary, so we'll retry on the client.
2557
const serverFallback = container.getElementsByTagName('p')[0];
@@ -2555,7 +2565,7 @@ describe('ReactDOMFizzServer', () => {
2565
},
2566
});
2567
// This should not report any errors yet.
2558
- expect(Scheduler).toFlushAndYield([]);
2568
+ await waitForAll([]);
2569
expect(getVisibleChildren(container)).toEqual(
2570
<div>
2571
<p>Loading...</p>
@@ -2573,7 +2583,7 @@ describe('ReactDOMFizzServer', () => {
2583
await act(async () => {
2584
resolveText('Yay!');
2585
});
2576
- expect(Scheduler).toFlushAndYield([
2586
+ await waitForAll([
2587
'Yay!',
2588
'[c!] The server could not finish this Suspense boundary, ' +
2589
'likely due to an error during server rendering. ' +
@@ -2626,7 +2636,7 @@ describe('ReactDOMFizzServer', () => {
2636
});
2637
pipe(writable);
2638
});
2629
- expect(Scheduler).toHaveYielded(['[s!] Oops.']);
2639
+ assertLog(['[s!] Oops.']);
2640
2641
// The server could not complete this boundary, so we'll retry on the client.
2642
const serverFallback = container.getElementsByTagName('p')[0];
@@ -2640,7 +2650,7 @@ describe('ReactDOMFizzServer', () => {
2650
},
2651
});
2652
// This should not report any errors yet.
2643
- expect(Scheduler).toFlushAndYield([]);
2653
+ await waitForAll([]);
2654
expect(getVisibleChildren(container)).toEqual(
2655
<div>
2656
<p>Loading...</p>
@@ -2667,7 +2677,7 @@ describe('ReactDOMFizzServer', () => {
2677
await act(async () => {
2678
resolveText('Yay!');
2679
});
2670
- expect(Scheduler).toFlushAndYield([
2680
+ await waitForAll([
2681
'Yay! (red)',
2682
'[c!] The server could not finish this Suspense boundary, ' +
2683
'likely due to an error during server rendering. ' +
@@ -2727,7 +2737,7 @@ describe('ReactDOMFizzServer', () => {
2737
);
2738
pipe(writable);
2739
});
2730
- expect(Scheduler).toHaveYielded(['[s!] Oops.']);
2740
+ assertLog(['[s!] Oops.']);
2741
2742
const serverFallback = container.getElementsByTagName('p')[0];
2743
expect(serverFallback.innerHTML).toBe('Loading...');
@@ -2744,7 +2754,7 @@ describe('ReactDOMFizzServer', () => {
2754
},
2755
);
2756
// This should not report any errors yet.
2747
- expect(Scheduler).toFlushAndYield([]);
2757
+ await waitForAll([]);
2758
expect(getVisibleChildren(container)).toEqual(
2759
<div>
2760
<p>Loading...</p>
@@ -2763,7 +2773,7 @@ describe('ReactDOMFizzServer', () => {
2773
root.render(<App fallbackText="More loading..." />);
2774
Scheduler.unstable_flushAll();
2775
jest.runAllTimers();
2766
- expect(Scheduler).toHaveYielded([
2776
+ assertLog([
2777
'[c!] The server could not finish this Suspense boundary, ' +
2778
'likely due to an error during server rendering. ' +
2779
'Switched to client rendering.',
@@ -2781,7 +2791,7 @@ describe('ReactDOMFizzServer', () => {
2791
await act(async () => {
2792
resolveText('Yay!');
2793
});
2784
- expect(Scheduler).toFlushAndYield(['Yay!']);
2794
+ await waitForAll(['Yay!']);
2795
expect(getVisibleChildren(container)).toEqual(
2796
<div>
2797
<span>Yay!</span>
@@ -2849,7 +2859,7 @@ describe('ReactDOMFizzServer', () => {
2859
const {pipe} = renderToPipeableStream(<App />);
2860
pipe(writable);
2861
});
2852
- expect(Scheduler).toHaveYielded(['Yay!']);
2862
+ assertLog(['Yay!']);
2863
2864
const [span1, span2, span3] = container.getElementsByTagName('span');
2865
@@ -2864,7 +2874,7 @@ describe('ReactDOMFizzServer', () => {
2874
2875
// An error logged but instead of surfacing it to the UI, we switched
2876
// to client rendering.
2867
- expect(Scheduler).toFlushAndYield([
2877
+ await waitForAll([
2878
'Hydration error',
2879
'There was an error while hydrating this Suspense boundary. Switched ' +
2880
'to client rendering.',
@@ -2880,7 +2890,7 @@ describe('ReactDOMFizzServer', () => {
2890
await act(async () => {
2891
resolveText('Yay!');
2892
});
2883
- expect(Scheduler).toFlushAndYield(['Yay!']);
2893
+ await waitForAll(['Yay!']);
2894
expect(getVisibleChildren(container)).toEqual(
2895
<div>
2896
<span />
@@ -2937,13 +2947,13 @@ describe('ReactDOMFizzServer', () => {
2947
});
2948
2949
// Partially render A, but yield before the render has finished
2940
- expect(Scheduler).toFlushAndYieldThrough(['Oops!', 'Oops!']);
2950
+ await waitFor(['Oops!', 'Oops!']);
2951
2952
// React will try rendering again synchronously. During the retry, A will
2953
// not throw. This simulates a concurrent data race that is fixed by
2954
// blocking the main thread.
2955
shouldThrow = false;
2946
- expect(Scheduler).toFlushAndYield([
2956
+ await waitForAll([
2957
// Finish initial render attempt
2958
'B',
2959
@@ -3001,7 +3011,7 @@ describe('ReactDOMFizzServer', () => {
3011
const {pipe} = renderToPipeableStream(<App />);
3012
pipe(writable);
3013
});
3004
- expect(Scheduler).toHaveYielded(['A', 'B']);
3014
+ assertLog(['A', 'B']);
3015
3016
// Hydrate the tree. Child will throw during hydration, but not when it
3017
// falls back to client rendering.
@@ -3014,7 +3024,7 @@ describe('ReactDOMFizzServer', () => {
3024
},
3025
});
3026
3017
- expect(Scheduler).toFlushAndYield([
3027
+ await waitForAll([
3028
'A',
3029
'B',
3030
@@ -3151,7 +3161,7 @@ describe('ReactDOMFizzServer', () => {
3161
},
3162
});
3163
3154
- expect(Scheduler).toFlushAndYield([]);
3164
+ await waitForAll([]);
3165
3166
expectErrors(
3167
errors,
@@ -3232,7 +3242,7 @@ describe('ReactDOMFizzServer', () => {
3242
},
3243
});
3244
3235
- expect(Scheduler).toFlushAndYield([]);
3245
+ await waitForAll([]);
3246
3247
expectErrors(
3248
errors,
@@ -3299,7 +3309,7 @@ describe('ReactDOMFizzServer', () => {
3309
},
3310
},
3311
);
3302
- expect(Scheduler).toFlushWithoutYielding();
3312
+ await waitForAll([]);
3313
});
3314
3315
describe('error escaping', () => {
@@ -3442,7 +3452,7 @@ describe('ReactDOMFizzServer', () => {
3452
errors.push({error, errorInfo});
3453
},
3454
});
3445
- expect(Scheduler).toFlushAndYield([]);
3455
+ await waitForAll([]);
3456
3457
// If escaping were not done we would get a message that says "bad hash"
3458
expectErrors(
@@ -3729,7 +3739,7 @@ describe('ReactDOMFizzServer', () => {
3739
// Now that the boundary resolves to it's children the hydration completes and discovers that there is a mismatch requiring
3740
// client-side rendering.
3741
await clientResolve();
3732
- expect(Scheduler).toFlushWithoutYielding();
3742
+ await waitForAll([]);
3743
expect(getVisibleChildren(container)).toEqual(
3744
<div>
3745
<p>A</p>
@@ -3808,8 +3818,8 @@ describe('ReactDOMFizzServer', () => {
3818
// Now that the boundary resolves to it's children the hydration completes and discovers that there is a mismatch requiring
3819
// client-side rendering.
3820
await clientResolve();
3811
- expect(() => {
3812
- expect(Scheduler).toFlushAndYield([
3821
+ await expect(async () => {
3822
+ await waitForAll([
3823
'Logged recoverable error: Text content does not match server-rendered HTML.',
3824
'Logged recoverable error: There was an error while hydrating this Suspense boundary. Switched to client rendering.',
3825
]);
@@ -3823,7 +3833,7 @@ describe('ReactDOMFizzServer', () => {
3833
</div>,
3834
);
3835
3826
- expect(Scheduler).toFlushAndYield([]);
3836
+ await waitForAll([]);
3837
});
3838
3839
// @gate enableClientRenderFallbackOnTextMismatch
@@ -3867,7 +3877,7 @@ describe('ReactDOMFizzServer', () => {
3877
);
3878
},
3879
});
3870
- expect(Scheduler).toFlushAndYield([
3880
+ await waitForAll([
3881
'Logged recoverable error: Text content does not match server-rendered HTML.',
3882
'Logged recoverable error: Text content does not match server-rendered HTML.',
3883
'Logged recoverable error: Text content does not match server-rendered HTML.',
@@ -3882,7 +3892,7 @@ describe('ReactDOMFizzServer', () => {
3892
</div>,
3893
);
3894
3885
- expect(Scheduler).toFlushAndYield([]);
3895
+ await waitForAll([]);
3896
if (__DEV__) {
3897
expect(mockError.mock.calls.length).toBe(1);
3898
expect(mockError.mock.calls[0]).toEqual([
@@ -3958,7 +3968,7 @@ describe('ReactDOMFizzServer', () => {
3968
);
3969
},
3970
});
3961
- expect(Scheduler).toFlushAndYield([
3971
+ await waitForAll([
3972
'Logged recoverable error: uh oh',
3973
'Logged recoverable error: Hydration failed because the initial UI does not match what was rendered on the server.',
3974
'Logged recoverable error: Hydration failed because the initial UI does not match what was rendered on the server.',
@@ -3973,7 +3983,7 @@ describe('ReactDOMFizzServer', () => {
3983
</div>,
3984
);
3985
3976
- expect(Scheduler).toFlushAndYield([]);
3986
+ await waitForAll([]);
3987
});
3988
3989
// @gate __DEV__
@@ -4050,7 +4060,7 @@ describe('ReactDOMFizzServer', () => {
4060
);
4061
},
4062
});
4053
- expect(Scheduler).toFlushAndYield([
4063
+ await waitForAll([
4064
'throwing: first error',
4065
// this repeated first error is the invokeGuardedCallback throw
4066
'throwing: first error',
@@ -4081,7 +4091,7 @@ describe('ReactDOMFizzServer', () => {
4091
</div>,
4092
);
4093
4084
- expect(Scheduler).toFlushAndYield([]);
4094
+ await waitForAll([]);
4095
expect(mockError.mock.calls).toEqual([]);
4096
} finally {
4097
console.error = originalConsoleError;
@@ -4181,7 +4191,7 @@ describe('ReactDOMFizzServer', () => {
4191
);
4192
},
4193
});
4184
- expect(Scheduler).toFlushAndYield([
4194
+ await waitForAll([
4195
'suspending',
4196
'throwing: first error',
4197
// There is no repeated first error because we already suspended and no
@@ -4202,7 +4212,7 @@ describe('ReactDOMFizzServer', () => {
4212
await unsuspend();
4213
// Since our client components only throw on the very first render there are no
4214
// new throws in this pass
4205
- expect(Scheduler).toFlushAndYield([]);
4215
+ await waitForAll([]);
4216
4217
expect(mockError.mock.calls).toEqual([]);
4218
} finally {
@@ -4304,7 +4314,7 @@ describe('ReactDOMFizzServer', () => {
4314
);
4315
},
4316
});
4307
- expect(Scheduler).toFlushAndYield([
4317
+ await waitForAll([
4318
'throwing: first error',
4319
// duplicate because first error is re-done in invokeGuardedCallback
4320
'throwing: first error',
@@ -4331,7 +4341,7 @@ describe('ReactDOMFizzServer', () => {
4341
await unsuspend();
4342
// Since our client components only throw on the very first render there are no
4343
// new throws in this pass
4334
- expect(Scheduler).toFlushAndYield([]);
4344
+ await waitForAll([]);
4345
expect(mockError.mock.calls).toEqual([]);
4346
} finally {
4347
console.error = originalConsoleError;
@@ -4365,7 +4375,7 @@ describe('ReactDOMFizzServer', () => {
4375
},
4376
});
4377
4368
- expect(Scheduler).toFlushAndYield([]);
4378
+ await waitForAll([]);
4379
expect(errors).toEqual([]);
4380
expect(getVisibleChildren(container)).toEqual(
4381
<div>
@@ -4374,7 +4384,7 @@ describe('ReactDOMFizzServer', () => {
4384
);
4385
4386
resolveText('A');
4377
- expect(Scheduler).toFlushAndYield([]);
4387
+ await waitForAll([]);
4388
expect(errors).toEqual([]);
4389
expect(getVisibleChildren(container)).toEqual(
4390
<div>
@@ -4411,7 +4421,7 @@ describe('ReactDOMFizzServer', () => {
4421
},
4422
});
4423
4414
- expect(Scheduler).toFlushAndYield([]);
4424
+ await waitForAll([]);
4425
expect(errors).toEqual([]);
4426
expect(getVisibleChildren(container)).toEqual(
4427
<div>
@@ -4421,7 +4431,7 @@ describe('ReactDOMFizzServer', () => {
4431
);
4432
4433
resolve({default: () => <p>lazy</p>});
4424
- expect(Scheduler).toFlushAndYield([]);
4434
+ await waitForAll([]);
4435
expect(errors).toEqual([]);
4436
expect(getVisibleChildren(container)).toEqual(
4437
<div>
@@ -4566,7 +4576,7 @@ describe('ReactDOMFizzServer', () => {
4576
errors.push(error.message);
4577
},
4578
});
4569
- expect(Scheduler).toFlushAndYield([]);
4579
+ await waitForAll([]);
4580
expect(errors).toEqual([]);
4581
expect(getVisibleChildren(container)).toEqual(
4582
<div>
@@ -4629,7 +4639,7 @@ describe('ReactDOMFizzServer', () => {
4639
errors.push(error.message);
4640
},
4641
});
4632
- expect(Scheduler).toFlushAndYield([]);
4642
+ await waitForAll([]);
4643
expect(errors).toEqual([]);
4644
expect(getVisibleChildren(container)).toEqual(
4645
<div id="app-div">
@@ -4679,7 +4689,7 @@ describe('ReactDOMFizzServer', () => {
4689
errors.push(error.message);
4690
},
4691
});
4682
- expect(Scheduler).toFlushAndYield([]);
4692
+ await waitForAll([]);
4693
expect(errors).toEqual([]);
4694
expect(getVisibleChildren(container)).toEqual(
4695
<div id="app-div">{['h', 'ello', 'w', 'orld']}</div>,
@@ -4724,7 +4734,7 @@ describe('ReactDOMFizzServer', () => {
4734
errors.push(error.message);
4735
},
4736
});
4727
- expect(Scheduler).toFlushAndYield([]);
4737
+ await waitForAll([]);
4738
expect(errors).toEqual([]);
4739
expect(getVisibleChildren(container)).toEqual(
4740
<div id="app-div">{['h', 'ello', 'w', 'orld']}</div>,
@@ -4762,7 +4772,7 @@ describe('ReactDOMFizzServer', () => {
4772
errors.push(error.message);
4773
},
4774
});
4765
- expect(Scheduler).toFlushAndYield([]);
4775
+ await waitForAll([]);
4776
expect(errors).toEqual([]);
4777
expect(getVisibleChildren(container)).toEqual(
4778
<div>
@@ -4800,7 +4810,7 @@ describe('ReactDOMFizzServer', () => {
4810
errors.push(error.message);
4811
},
4812
});
4803
- expect(Scheduler).toFlushAndYield([]);
4813
+ await waitForAll([]);
4814
expect(errors).toEqual([]);
4815
expect(getVisibleChildren(container)).toEqual(
4816
<div>
@@ -4857,7 +4867,7 @@ describe('ReactDOMFizzServer', () => {
4867
errors.push(error.message);
4868
},
4869
});
4860
- expect(Scheduler).toFlushAndYield([]);
4870
+ await waitForAll([]);
4871
expect(errors).toEqual([]);
4872
expect(getVisibleChildren(container)).toEqual(
4873
<div id="app-div">
@@ -4883,7 +4893,7 @@ describe('ReactDOMFizzServer', () => {
4893
'<div id="app-div">start<!--$-->firststartfirst suspendedfirstend<!--/$--><!--$-->secondstart<b>second suspended</b><!--/$-->end</div>',
4894
);
4895
4886
- expect(Scheduler).toFlushAndYield([]);
4896
+ await waitForAll([]);
4897
expect(errors).toEqual([]);
4898
expect(getVisibleChildren(container)).toEqual(
4899
<div id="app-div">
@@ -4939,7 +4949,7 @@ describe('ReactDOMFizzServer', () => {
4949
errors.push(error.message);
4950
},
4951
});
4942
- expect(Scheduler).toFlushAndYield([]);
4952
+ await waitForAll([]);
4953
expect(errors).toEqual([]);
4954
expect(getVisibleChildren(container)).toEqual(
4955
<div>
@@ -4985,7 +4995,7 @@ describe('ReactDOMFizzServer', () => {
4995
errors.push(error.message);
4996
},
4997
});
4988
- expect(Scheduler).toFlushAndYield([]);
4998
+ await waitForAll([]);
4999
expect(errors).toEqual([]);
5000
expect(getVisibleChildren(container)).toEqual(<title>hello</title>);
5001
});
@@ -5009,7 +5019,7 @@ describe('ReactDOMFizzServer', () => {
5019
errors.push(error.message);
5020
},
5021
});
5012
- expect(Scheduler).toFlushAndYield([]);
5022
+ await waitForAll([]);
5023
expect(errors).toEqual([]);
5024
expect(getVisibleChildren(container)).toEqual(<title>hello</title>);
5025
});
@@ -5044,7 +5054,7 @@ describe('ReactDOMFizzServer', () => {
5054
errors.push(error.message);
5055
},
5056
});
5047
- expect(Scheduler).toFlushAndYield([]);
5057
+ await waitForAll([]);
5058
if (gate(flags => flags.enableFloat)) {
5059
expect(errors).toEqual([]);
5060
// with float, the title doesn't render on the client or on the server
@@ -5117,7 +5127,7 @@ describe('ReactDOMFizzServer', () => {
5127
errors.push(error.message);
5128
},
5129
});
5120
- expect(Scheduler).toFlushAndYield([]);
5130
+ await waitForAll([]);
5131
expect(errors).toEqual([]);
5132
if (gate(flags => flags.enableFloat)) {
5133
// object titles are toStringed when float is on
@@ -5171,7 +5181,7 @@ describe('ReactDOMFizzServer', () => {
5181
expect(getVisibleChildren(container)).toEqual('ABC');
5182
5183
ReactDOMClient.hydrateRoot(container, <App />);
5174
- expect(Scheduler).toFlushAndYield([]);
5184
+ await waitForAll([]);
5185
expect(getVisibleChildren(container)).toEqual('ABC');
5186
});
5187
@@ -5219,7 +5229,7 @@ describe('ReactDOMFizzServer', () => {
5229
ContextA._currentRenderer = null;
5230
ServerContext._currentRenderer = null;
5231
ReactDOMClient.hydrateRoot(container, <App />);
5222
- expect(Scheduler).toFlushAndYield([]);
5232
+ await waitForAll([]);
5233
expect(getVisibleChildren(container)).toEqual(['AB', 'C']);
5234
});
5235
@@ -5273,7 +5283,7 @@ describe('ReactDOMFizzServer', () => {
5283
expect(getVisibleChildren(container)).toEqual('ABCD');
5284
5285
ReactDOMClient.hydrateRoot(container, <App />);
5276
- expect(Scheduler).toFlushAndYield([]);
5286
+ await waitForAll([]);
5287
expect(getVisibleChildren(container)).toEqual('ABCD');
5288
});
5289
@@ -5350,7 +5360,7 @@ describe('ReactDOMFizzServer', () => {
5360
reportedClientErrors.push(error);
5361
},
5362
});
5353
- expect(Scheduler).toFlushAndYield([]);
5363
+ await waitForAll([]);
5364
expect(getVisibleChildren(container)).toEqual('Oops!');
5365
expect(reportedClientErrors.length).toBe(1);
5366
if (__DEV__) {
@@ -5383,7 +5393,7 @@ describe('ReactDOMFizzServer', () => {
5393
expect(getVisibleChildren(container)).toEqual('Hi');
5394
5395
ReactDOMClient.hydrateRoot(container, <App />);
5386
- expect(Scheduler).toFlushAndYield([]);
5396
+ await waitForAll([]);
5397
expect(getVisibleChildren(container)).toEqual('Hi');
5398
});
5399
@@ -5437,7 +5447,7 @@ describe('ReactDOMFizzServer', () => {
5447
expect(getVisibleChildren(container)).toEqual(<button>0</button>);
5448
5449
ReactDOMClient.hydrateRoot(container, <App />);
5440
- expect(Scheduler).toFlushAndYield([]);
5450
+ await waitForAll([]);
5451
expect(getVisibleChildren(container)).toEqual(<button>0</button>);
5452
5453
ref.current.dispatchEvent(
@@ -5502,8 +5512,8 @@ describe('ReactDOMFizzServer', () => {
5512
errors.push(error);
5513
},
5514
});
5505
- expect(() => {
5506
- expect(Scheduler).toFlushAndYield([]);
5515
+ await expect(async () => {
5516
+ await waitForAll([]);
5517
}).toErrorDev(
5518
[
5519
'Expected server HTML to contain a matching <span> in <div>',
packages/react-dom/src/__tests__/ReactDOMFizzSuppressHydrationWarning-test.js
+23
-19
@@ -22,6 +22,7 @@ let container;
22
let buffer = '';
23
let hasErrored = false;
24
let fatalError = undefined;
25
+let waitForAll;
26
27
describe('ReactDOMFizzServerHydrationWarning', () => {
28
beforeEach(() => {
@@ -33,6 +34,9 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
34
ReactDOMFizzServer = require('react-dom/server');
35
Stream = require('stream');
36
37
+ const InternalTestUtils = require('internal-test-utils');
38
+ waitForAll = InternalTestUtils.waitForAll;
39
+
40
// Test Environment
41
const jsdom = new JSDOM(
42
'<!DOCTYPE html><html><head></head><body><div id="container">',
@@ -155,7 +159,7 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
159
Scheduler.unstable_yieldValue(error.message);
160
},
161
});
158
- expect(Scheduler).toFlushAndYield([]);
162
+ await waitForAll([]);
163
// The text mismatch should be *silently* fixed. Even in production.
164
expect(getVisibleChildren(container)).toEqual(
165
<div>
@@ -195,7 +199,7 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
199
Scheduler.unstable_yieldValue(error.message);
200
},
201
});
198
- expect(Scheduler).toFlushAndYield([]);
202
+ await waitForAll([]);
203
expect(getVisibleChildren(container)).toEqual(
204
<div>
205
<span>
@@ -236,8 +240,8 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
240
Scheduler.unstable_yieldValue(error.message);
241
},
242
});
239
- expect(() => {
240
- expect(Scheduler).toFlushAndYield([
243
+ await expect(async () => {
244
+ await waitForAll([
245
'Hydration failed because the initial UI does not match what was rendered on the server.',
246
'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
247
]);
@@ -283,7 +287,7 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
287
Scheduler.unstable_yieldValue(error.message);
288
},
289
});
286
- expect(Scheduler).toFlushAndYield([]);
290
+ await waitForAll([]);
291
expect(getVisibleChildren(container)).toEqual(
292
<div>
293
<span>{'Client'}</span>
@@ -319,8 +323,8 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
323
Scheduler.unstable_yieldValue(error.message);
324
},
325
});
322
- expect(() => {
323
- expect(Scheduler).toFlushAndYield([
326
+ await expect(async () => {
327
+ await waitForAll([
328
'Hydration failed because the initial UI does not match what was rendered on the server.',
329
'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
330
]);
@@ -367,8 +371,8 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
371
Scheduler.unstable_yieldValue(error.message);
372
},
373
});
370
- expect(() => {
371
- expect(Scheduler).toFlushAndYield([
374
+ await expect(async () => {
375
+ await waitForAll([
376
'Hydration failed because the initial UI does not match what was rendered on the server.',
377
'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
378
]);
@@ -418,8 +422,8 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
422
Scheduler.unstable_yieldValue(error.message);
423
},
424
});
421
- expect(() => {
422
- expect(Scheduler).toFlushAndYield([
425
+ await expect(async () => {
426
+ await waitForAll([
427
'Hydration failed because the initial UI does not match what was rendered on the server.',
428
'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
429
]);
@@ -467,8 +471,8 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
471
Scheduler.unstable_yieldValue(error.message);
472
},
473
});
470
- expect(() => {
471
- expect(Scheduler).toFlushAndYield([
474
+ await expect(async () => {
475
+ await waitForAll([
476
'Hydration failed because the initial UI does not match what was rendered on the server.',
477
'Hydration failed because the initial UI does not match what was rendered on the server.',
478
'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
@@ -521,7 +525,7 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
525
Scheduler.unstable_yieldValue(error.message);
526
},
527
});
524
- expect(Scheduler).toFlushAndYield([]);
528
+ await waitForAll([]);
529
expect(getVisibleChildren(container)).toEqual(
530
<div>
531
<span class="server" style="opacity:0" data-serveronly="server-only" />
@@ -558,7 +562,7 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
562
Scheduler.unstable_yieldValue(error.message);
563
},
564
});
561
- expect(Scheduler).toFlushAndYield([]);
565
+ await waitForAll([]);
566
expect(getVisibleChildren(container)).toEqual(
567
<div>
568
<p>Server HTML</p>
@@ -591,8 +595,8 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
595
Scheduler.unstable_yieldValue(error.message);
596
},
597
});
594
- expect(() => {
595
- expect(Scheduler).toFlushAndYield([
598
+ await expect(async () => {
599
+ await waitForAll([
600
'Hydration failed because the initial UI does not match what was rendered on the server.',
601
'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
602
]);
@@ -637,8 +641,8 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
641
Scheduler.unstable_yieldValue(error.message);
642
},
643
});
640
- expect(() => {
641
- expect(Scheduler).toFlushAndYield([
644
+ await expect(async () => {
645
+ await waitForAll([
646
'Hydration failed because the initial UI does not match what was rendered on the server.',
647
'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
648
]);
packages/react-dom/src/__tests__/ReactDOMFloat-test.js
+78
-68
@@ -33,6 +33,8 @@ let buffer = '';
33
let hasErrored = false;
34
let fatalError = undefined;
35
let renderOptions;
36
+let waitForAll;
37
+let assertLog;
38
39
function resetJSDOM(markup) {
40
// Test Environment
@@ -63,6 +65,10 @@ describe('ReactDOMFloat', () => {
65
Stream = require('stream');
66
Suspense = React.Suspense;
67
68
+ const InternalTestUtils = require('internal-test-utils');
69
+ waitForAll = InternalTestUtils.waitForAll;
70
+ assertLog = InternalTestUtils.assertLog;
71
+
72
textCache = new Map();
73
74
resetJSDOM('<!DOCTYPE html><html><head></head><body><div id="container">');
@@ -259,10 +265,14 @@ describe('ReactDOMFloat', () => {
265
root.render(children);
266
return expect(() => {
267
try {
262
- expect(Scheduler).toFlushWithoutYielding();
268
+ // TODO: Migrate this to waitForAll()
269
+ Scheduler.unstable_flushAll();
270
+ assertLog([]);
271
} catch (e) {
272
try {
265
- expect(Scheduler).toFlushWithoutYielding();
273
+ // TODO: Migrate this to waitForAll()
274
+ Scheduler.unstable_flushAll();
275
+ assertLog([]);
276
} catch (f) {}
277
}
278
});
@@ -283,11 +293,11 @@ describe('ReactDOMFloat', () => {
293
</>,
294
);
295
try {
286
- expect(Scheduler).toFlushWithoutYielding();
296
+ await waitForAll([]);
297
} catch (e) {
298
// for DOMExceptions that happen when expecting this test to fail we need
299
// to clear the scheduler first otherwise the expected failure will fail
290
- expect(Scheduler).toFlushWithoutYielding();
300
+ await waitForAll([]);
301
throw e;
302
}
303
expect(getMeaningfulChildren(document)).toEqual(
@@ -351,7 +361,7 @@ describe('ReactDOMFloat', () => {
361
<body>foo</body>
362
</html>,
363
);
354
- expect(Scheduler).toFlushWithoutYielding();
364
+ await waitForAll([]);
365
expect(getMeaningfulChildren(document)).toEqual(
366
<html>
367
<head>
@@ -476,7 +486,7 @@ describe('ReactDOMFloat', () => {
486
<script async={true} src="foo" />
487
</>,
488
);
479
- expect(Scheduler).toFlushWithoutYielding();
489
+ await waitForAll([]);
490
expect(getMeaningfulChildren(document)).toEqual(
491
<html>
492
<head>
@@ -494,7 +504,7 @@ describe('ReactDOMFloat', () => {
504
<script data-new="new" async={true} src="foo" />
505
</>,
506
);
497
- expect(Scheduler).toFlushWithoutYielding();
507
+ await waitForAll([]);
508
// we don't see the attribute because the resource is the same and was not reconstructed
509
expect(getMeaningfulChildren(document)).toEqual(
510
<html>
@@ -671,7 +681,7 @@ describe('ReactDOMFloat', () => {
681
</body>
682
</html>,
683
);
674
- expect(Scheduler).toFlushWithoutYielding();
684
+ await waitForAll([]);
685
expect(getMeaningfulChildren(document)).toEqual(
686
<html>
687
<head>
@@ -968,7 +978,7 @@ body {
978
</body>
979
</html>,
980
);
971
- expect(Scheduler).toFlushWithoutYielding();
981
+ await waitForAll([]);
982
983
expect(getMeaningfulChildren(document)).toEqual(
984
<html>
@@ -1107,7 +1117,7 @@ body {
1117
errors.push(err.digest);
1118
},
1119
});
1110
- expect(Scheduler).toFlushWithoutYielding();
1120
+ await waitForAll([]);
1121
expect(getMeaningfulChildren(document)).toEqual(
1122
<html>
1123
<head>
@@ -1157,7 +1167,7 @@ body {
1167
<body>Hello</body>
1168
</html>,
1169
);
1160
- expect(Scheduler).toFlushWithoutYielding();
1170
+ await waitForAll([]);
1171
expect(getMeaningfulChildren(document)).toEqual(
1172
<html>
1173
<head>
@@ -1627,7 +1637,7 @@ body {
1637
</body>
1638
</html>,
1639
);
1630
- expect(Scheduler).toFlushWithoutYielding();
1640
+ await waitForAll([]);
1641
expect(getMeaningfulChildren(document)).toEqual(
1642
<html>
1643
<head>
@@ -1649,7 +1659,7 @@ body {
1659
</body>
1660
</html>,
1661
);
1652
- expect(Scheduler).toFlushWithoutYielding();
1662
+ await waitForAll([]);
1663
expect(getMeaningfulChildren(document)).toEqual(
1664
<html>
1665
<head>
@@ -1694,7 +1704,7 @@ body {
1704
<Throw />
1705
</ErrorBoundary>,
1706
);
1697
- expect(Scheduler).toFlushWithoutYielding();
1707
+ await waitForAll([]);
1708
expect(getMeaningfulChildren(document)).toEqual(
1709
<html>
1710
<head>
@@ -2327,8 +2337,8 @@ body {
2337
);
2338
2339
const root = ReactDOMClient.hydrateRoot(document, <App url="foo" />);
2330
- expect(() => {
2331
- expect(Scheduler).toFlushWithoutYielding();
2340
+ await expect(async () => {
2341
+ await waitForAll([]);
2342
}).toErrorDev([
2343
'ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered something with type "object" as a second argument instead. This argument is reserved for future options and is currently disallowed. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.',
2344
'ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered something with type "object" as a second argument instead. This argument is reserved for future options and is currently disallowed. It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. Browsers do not perform DNS queries using CORS and setting this attribute on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.',
@@ -2343,8 +2353,8 @@ body {
2353
);
2354
2355
root.render(<App url="bar" />);
2346
- expect(() => {
2347
- expect(Scheduler).toFlushWithoutYielding();
2356
+ await expect(async () => {
2357
+ await waitForAll([]);
2358
}).toErrorDev([
2359
'ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered something with type "object" as a second argument instead. This argument is reserved for future options and is currently disallowed. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.',
2360
'ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered something with type "object" as a second argument instead. This argument is reserved for future options and is currently disallowed. It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. Browsers do not perform DNS queries using CORS and setting this attribute on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.',
@@ -2397,8 +2407,8 @@ body {
2407
);
2408
2409
const root = ReactDOMClient.hydrateRoot(document, <App url="foo" />);
2400
- expect(() => {
2401
- expect(Scheduler).toFlushWithoutYielding();
2410
+ await expect(async () => {
2411
+ await waitForAll([]);
2412
}).toErrorDev(
2413
'ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) to be a string but encountered something with type "boolean" instead. Try removing this option or passing a string value instead.',
2414
);
@@ -2414,8 +2424,8 @@ body {
2424
);
2425
2426
root.render(<App url="bar" />);
2417
- expect(() => {
2418
- expect(Scheduler).toFlushWithoutYielding();
2427
+ await expect(async () => {
2428
+ await waitForAll([]);
2429
}).toErrorDev(
2430
'ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) to be a string but encountered something with type "boolean" instead. Try removing this option or passing a string value instead.',
2431
);
@@ -2502,7 +2512,7 @@ body {
2512
);
2513
}
2514
ReactDOMClient.hydrateRoot(document, <ClientApp />);
2505
- expect(Scheduler).toFlushWithoutYielding();
2515
+ await waitForAll([]);
2516
expect(getMeaningfulChildren(document)).toEqual(
2517
<html>
2518
<head>
@@ -2724,7 +2734,7 @@ body {
2734
}
2735
2736
ReactDOMClient.hydrateRoot(document, <ClientApp />);
2727
- expect(Scheduler).toFlushWithoutYielding();
2737
+ await waitForAll([]);
2738
expect(getMeaningfulChildren(document)).toEqual(
2739
<html>
2740
<head>
@@ -2754,7 +2764,7 @@ body {
2764
2765
const root = ReactDOMClient.createRoot(document);
2766
root.render(<App />);
2757
- expect(Scheduler).toFlushWithoutYielding();
2767
+ await waitForAll([]);
2768
expect(getMeaningfulChildren(document)).toEqual(
2769
<html>
2770
<head>
@@ -2829,7 +2839,7 @@ body {
2839
}
2840
2841
ReactDOMClient.hydrateRoot(document, <ClientApp />);
2832
- expect(Scheduler).toFlushWithoutYielding();
2842
+ await waitForAll([]);
2843
expect(getMeaningfulChildren(document)).toEqual(
2844
<html>
2845
<head>
@@ -2858,7 +2868,7 @@ body {
2868
2869
const root = ReactDOMClient.createRoot(document);
2870
root.render(<App />);
2861
- expect(Scheduler).toFlushWithoutYielding();
2871
+ await waitForAll([]);
2872
expect(getMeaningfulChildren(document)).toEqual(
2873
<html>
2874
<head>
@@ -3050,7 +3060,7 @@ body {
3060
</body>
3061
</html>,
3062
);
3053
- expect(Scheduler).toFlushWithoutYielding();
3063
+ await waitForAll([]);
3064
3065
expect(getMeaningfulChildren(document)).toEqual(
3066
<html>
@@ -3088,7 +3098,7 @@ body {
3098
</body>
3099
</html>,
3100
);
3091
- expect(Scheduler).toFlushWithoutYielding();
3101
+ await waitForAll([]);
3102
3103
expect(getMeaningfulChildren(document)).toEqual(
3104
<html>
@@ -3171,7 +3181,7 @@ body {
3181
</body>
3182
</html>,
3183
);
3174
- expect(Scheduler).toFlushWithoutYielding();
3184
+ await waitForAll([]);
3185
expect(getMeaningfulChildren(document)).toEqual(
3186
<html>
3187
<head>
@@ -3206,7 +3216,7 @@ body {
3216
</body>
3217
</html>,
3218
);
3209
- expect(Scheduler).toFlushWithoutYielding();
3219
+ await waitForAll([]);
3220
3221
root.render(
3222
<html>
@@ -3214,7 +3224,7 @@ body {
3224
<body>hello world</body>
3225
</html>,
3226
);
3217
- expect(Scheduler).toFlushWithoutYielding();
3227
+ await waitForAll([]);
3228
expect(getMeaningfulChildren(document)).toEqual(
3229
<html>
3230
<head>
@@ -3256,8 +3266,8 @@ body {
3266
},
3267
},
3268
);
3259
- expect(() => {
3260
- expect(Scheduler).toFlushWithoutYielding();
3269
+ await expect(async () => {
3270
+ await waitForAll([]);
3271
}).toErrorDev(
3272
[
3273
'Warning: Text content did not match. Server: "server" Client: "client"',
@@ -3308,8 +3318,8 @@ body {
3318
},
3319
},
3320
);
3311
- expect(() => {
3312
- expect(Scheduler).toFlushWithoutYielding();
3321
+ await expect(async () => {
3322
+ await waitForAll([]);
3323
}).toErrorDev(
3324
[
3325
'Warning: Text content did not match. Server: "server" Client: "client"',
@@ -3342,7 +3352,7 @@ body {
3352
</body>
3353
</html>,
3354
);
3345
- expect(Scheduler).toFlushWithoutYielding();
3355
+ await waitForAll([]);
3356
expect(getMeaningfulChildren(document)).toEqual(
3357
<html>
3358
<head>
@@ -3364,7 +3374,7 @@ body {
3374
</body>
3375
</html>,
3376
);
3367
- expect(Scheduler).toFlushWithoutYielding();
3377
+ await waitForAll([]);
3378
// The reason we do not see preloads in the head is they are inserted synchronously
3379
// during render and then when the new singleton mounts it resets it's content, retaining only styles
3380
expect(getMeaningfulChildren(document)).toEqual(
@@ -3401,7 +3411,7 @@ body {
3411
container
3412
</>,
3413
);
3404
- expect(Scheduler).toFlushWithoutYielding();
3414
+ await waitForAll([]);
3415
expect(getMeaningfulChildren(document)).toEqual(
3416
<html>
3417
<head>
@@ -3461,7 +3471,7 @@ body {
3471
container
3472
</>,
3473
);
3464
- expect(Scheduler).toFlushWithoutYielding();
3474
+ await waitForAll([]);
3475
expect(getMeaningfulChildren(document)).toEqual(
3476
<html>
3477
<head>
@@ -3533,7 +3543,7 @@ body {
3543
);
3544
}
3545
root.render(<ClientApp />);
3536
- expect(Scheduler).toFlushWithoutYielding();
3546
+ await waitForAll([]);
3547
expect(getMeaningfulChildren(document)).toEqual(
3548
<html>
3549
<head>
@@ -3596,7 +3606,7 @@ body {
3606
container = document.getElementById('container');
3607
const root = ReactDOMClient.createRoot(container);
3608
root.render(<App />);
3599
- expect(Scheduler).toFlushWithoutYielding();
3609
+ await waitForAll([]);
3610
expect(getMeaningfulChildren(document)).toEqual(
3611
<html>
3612
<head>
@@ -3672,7 +3682,7 @@ body {
3682
</svg>
3683
</div>,
3684
);
3675
- expect(Scheduler).toFlushWithoutYielding();
3685
+ await waitForAll([]);
3686
expect(getMeaningfulChildren(document.body)).toEqual(
3687
<div>
3688
<svg>
@@ -3718,7 +3728,7 @@ body {
3728
</noscript>
3729
</div>,
3730
);
3721
- expect(Scheduler).toFlushWithoutYielding();
3731
+ await waitForAll([]);
3732
expect(getMeaningfulChildren(document.body)).toEqual(
3733
<div>
3734
{/* On the client, <noscript> never renders children */}
@@ -3793,8 +3803,8 @@ body {
3803
</body>
3804
</html>,
3805
);
3796
- expect(() => {
3797
- expect(Scheduler).toFlushWithoutYielding();
3806
+ await expect(async () => {
3807
+ await waitForAll([]);
3808
}).toErrorDev([
3809
'React encountered a <link rel="stylesheet" href="foo" ... /> with a `precedence` prop that also included the `onLoad` and `onError` props. The presence of loading and error handlers indicates an intent to manage the stylesheet loading state from your from your Component code and React will not hoist or deduplicate this stylesheet. If your intent was to have React hoist and deduplciate this stylesheet using the `precedence` prop remove the `onLoad` and `onError` props, otherwise remove the `precedence` prop.',
3810
]);
@@ -4064,7 +4074,7 @@ background-color: green;
4074
</body>
4075
</html>,
4076
);
4067
- expect(Scheduler).toFlushWithoutYielding();
4077
+ await waitForAll([]);
4078
4079
expect(getMeaningfulChildren(document)).toEqual(
4080
<html>
@@ -4095,7 +4105,7 @@ background-color: green;
4105
</body>
4106
</html>,
4107
);
4098
- expect(Scheduler).toFlushWithoutYielding();
4108
+ await waitForAll([]);
4109
expect(getMeaningfulChildren(document)).toEqual(
4110
<html>
4111
<head>
@@ -4493,7 +4503,7 @@ background-color: green;
4503
</body>
4504
</html>,
4505
);
4496
- expect(Scheduler).toFlushWithoutYielding();
4506
+ await waitForAll([]);
4507
// The async script with onLoad is inserted in the right place but does not cause the hydration
4508
// to fail.
4509
expect(getMeaningfulChildren(document)).toEqual(
@@ -4560,7 +4570,7 @@ background-color: green;
4570
</svg>
4571
</div>,
4572
);
4563
- expect(Scheduler).toFlushWithoutYielding();
4573
+ await waitForAll([]);
4574
expect(getMeaningfulChildren(document.body)).toEqual(
4575
<div>
4576
<svg>
@@ -4606,7 +4616,7 @@ background-color: green;
4616
</noscript>
4617
</div>,
4618
);
4609
- expect(Scheduler).toFlushWithoutYielding();
4619
+ await waitForAll([]);
4620
expect(getMeaningfulChildren(document.body)).toEqual(
4621
<div>
4622
{/* On the client, <noscript> never renders children */}
@@ -4708,7 +4718,7 @@ background-color: green;
4718
</body>
4719
</html>,
4720
);
4711
- expect(Scheduler).toFlushWithoutYielding();
4721
+ await waitForAll([]);
4722
expect(getMeaningfulChildren(document)).toEqual(
4723
<html>
4724
<head>
@@ -4723,7 +4733,7 @@ background-color: green;
4733
<body />
4734
</html>,
4735
);
4726
- expect(Scheduler).toFlushWithoutYielding();
4736
+ await waitForAll([]);
4737
expect(getMeaningfulChildren(document)).toEqual(
4738
<html>
4739
<head />
@@ -4742,7 +4752,7 @@ background-color: green;
4752
</div>,
4753
);
4754
});
4745
- expect(Scheduler).toFlushWithoutYielding();
4755
+ await waitForAll([]);
4756
4757
expect(getMeaningfulChildren(document.head)).toEqual(
4758
<meta name="foo" data-foo="data" content="bar" />,
@@ -4750,7 +4760,7 @@ background-color: green;
4760
expect(getMeaningfulChildren(container)).toEqual(<div />);
4761
4762
root.render(<div />);
4753
- expect(Scheduler).toFlushWithoutYielding();
4763
+ await waitForAll([]);
4764
expect(getMeaningfulChildren(document.head)).toEqual(undefined);
4765
});
4766
@@ -4784,7 +4794,7 @@ background-color: green;
4794
</body>
4795
</html>,
4796
);
4787
- expect(Scheduler).toFlushWithoutYielding();
4797
+ await waitForAll([]);
4798
expect(getMeaningfulChildren(document)).toEqual(
4799
<html>
4800
<head>
@@ -4799,7 +4809,7 @@ background-color: green;
4809
<body />
4810
</html>,
4811
);
4802
- expect(Scheduler).toFlushWithoutYielding();
4812
+ await waitForAll([]);
4813
expect(getMeaningfulChildren(document)).toEqual(
4814
<html>
4815
<head />
@@ -4818,7 +4828,7 @@ background-color: green;
4828
</div>,
4829
);
4830
});
4821
- expect(Scheduler).toFlushWithoutYielding();
4831
+ await waitForAll([]);
4832
4833
expect(getMeaningfulChildren(document.head)).toEqual(
4834
<link rel="foo" data-foo="data" href="foo" />,
@@ -4826,7 +4836,7 @@ background-color: green;
4836
expect(getMeaningfulChildren(container)).toEqual(<div />);
4837
4838
root.render(<div />);
4829
- expect(Scheduler).toFlushWithoutYielding();
4839
+ await waitForAll([]);
4840
expect(getMeaningfulChildren(document.head)).toEqual(undefined);
4841
});
4842
@@ -4860,7 +4870,7 @@ background-color: green;
4870
</body>
4871
</html>,
4872
);
4863
- expect(Scheduler).toFlushWithoutYielding();
4873
+ await waitForAll([]);
4874
expect(getMeaningfulChildren(document)).toEqual(
4875
<html>
4876
<head>
@@ -4875,7 +4885,7 @@ background-color: green;
4885
<body />
4886
</html>,
4887
);
4878
- expect(Scheduler).toFlushWithoutYielding();
4888
+ await waitForAll([]);
4889
expect(getMeaningfulChildren(document)).toEqual(
4890
<html>
4891
<head />
@@ -4894,7 +4904,7 @@ background-color: green;
4904
</div>,
4905
);
4906
});
4897
- expect(Scheduler).toFlushWithoutYielding();
4907
+ await waitForAll([]);
4908
4909
expect(getMeaningfulChildren(document.head)).toEqual(
4910
<title data-foo="foo">a title</title>,
@@ -4902,7 +4912,7 @@ background-color: green;
4912
expect(getMeaningfulChildren(container)).toEqual(<div />);
4913
4914
root.render(<div />);
4905
- expect(Scheduler).toFlushWithoutYielding();
4915
+ await waitForAll([]);
4916
expect(getMeaningfulChildren(document.head)).toEqual(undefined);
4917
});
4918
@@ -5031,7 +5041,7 @@ background-color: green;
5041
<meta name="after" />
5042
</>,
5043
);
5034
- expect(Scheduler).toFlushWithoutYielding();
5044
+ await waitForAll([]);
5045
expect(getMeaningfulChildren(document)).toEqual(
5046
<html>
5047
<head>
@@ -5051,7 +5061,7 @@ background-color: green;
5061
{null}
5062
</>,
5063
);
5054
- expect(Scheduler).toFlushWithoutYielding();
5064
+ await waitForAll([]);
5065
expect(getMeaningfulChildren(document)).toEqual(
5066
<html>
5067
<head />
@@ -5157,8 +5167,8 @@ background-color: green;
5167
},
5168
);
5169
try {
5160
- expect(() => {
5161
- expect(Scheduler).toFlushWithoutYielding();
5170
+ await expect(async () => {
5171
+ await waitForAll([]);
5172
}).toErrorDev(
5173
[
5174
'Warning: Text content did not match. Server: "server" Client: "client"',
@@ -5169,7 +5179,7 @@ background-color: green;
5179
} catch (e) {
5180
// When gates are false this test fails on a DOMException if you don't clear the scheduler after catching.
5181
// When gates are true this branch should not be hit
5172
- expect(Scheduler).toFlushWithoutYielding();
5182
+ await waitForAll([]);
5183
throw e;
5184
}
5185
expect(getMeaningfulChildren(document)).toEqual(
packages/react-dom/src/__tests__/ReactDeprecationWarnings-test.js
+5
-2
@@ -13,6 +13,7 @@ let React;
13
let ReactNoop;
14
let Scheduler;
15
let JSXDEVRuntime;
16
+let waitForAll;
17
18
describe('ReactDeprecationWarnings', () => {
19
beforeEach(() => {
@@ -20,6 +21,8 @@ describe('ReactDeprecationWarnings', () => {
21
React = require('react');
22
ReactNoop = require('react-noop-renderer');
23
Scheduler = require('scheduler');
24
+ const InternalTestUtils = require('internal-test-utils');
25
+ waitForAll = InternalTestUtils.waitForAll;
26
if (__DEV__) {
27
JSXDEVRuntime = require('react/jsx-dev-runtime');
28
}
@@ -86,7 +89,7 @@ describe('ReactDeprecationWarnings', () => {
89
);
90
});
91
89
- it('should warn when owner and self are the same for string refs', () => {
92
+ it('should warn when owner and self are the same for string refs', async () => {
93
class RefComponent extends React.Component {
94
render() {
95
return null;
@@ -102,7 +105,7 @@ describe('ReactDeprecationWarnings', () => {
105
}).toErrorDev([
106
'Component "Component" contains the string ref "refComponent". Support for string refs will be removed in a future major release.',
107
]);
105
- expect(Scheduler).toFlushWithoutYielding();
108
+ await waitForAll([]);
109
});
110
111
it('should warn when owner and self are different for string refs', () => {
packages/react/src/__tests__/ReactProfiler-test.internal.js
+53
-54
@@ -17,6 +17,9 @@ let Scheduler;
17
let ReactTestRenderer;
18
let act;
19
let AdvanceTime;
20
+let assertLog;
21
+let waitFor;
22
+let waitForAll;
23
24
function loadModules({
25
enableProfilerTimer = true,
@@ -49,6 +52,11 @@ function loadModules({
52
ReactTestRenderer = require('react-test-renderer');
53
}
54
55
+ const InternalTestUtils = require('internal-test-utils');
56
+ assertLog = InternalTestUtils.assertLog;
57
+ waitFor = InternalTestUtils.waitFor;
58
+ waitForAll = InternalTestUtils.waitForAll;
59
+
60
AdvanceTime = class extends React.Component {
61
static defaultProps = {
62
byAmount: 10,
@@ -188,7 +196,7 @@ describe(`onRender`, () => {
196
expect(callback).toHaveBeenCalledTimes(2);
197
});
198
191
- it('is not invoked until the commit phase', () => {
199
+ it('is not invoked until the commit phase', async () => {
200
const callback = jest.fn();
201
202
const Yield = ({value}) => {
@@ -209,9 +217,9 @@ describe(`onRender`, () => {
217
});
218
219
// Times are logged until a render is committed.
212
- expect(Scheduler).toFlushAndYieldThrough(['first']);
220
+ await waitFor(['first']);
221
expect(callback).toHaveBeenCalledTimes(0);
214
- expect(Scheduler).toFlushAndYield(['last']);
222
+ await waitForAll(['last']);
223
expect(callback).toHaveBeenCalledTimes(1);
224
});
225
@@ -248,7 +256,7 @@ describe(`onRender`, () => {
256
257
// TODO: unstable_now is called by more places than just the profiler.
258
// Rewrite this test so it's less fragile.
251
- expect(Scheduler).toHaveYielded([
259
+ assertLog([
260
'read current time',
261
'read current time',
262
'read current time',
@@ -669,7 +677,7 @@ describe(`onRender`, () => {
677
</React.Profiler>,
678
);
679
});
672
- expect(Scheduler).toHaveYielded(['false:false', 'true:false', 'true:true']);
680
+ assertLog(['false:false', 'true:false', 'true:true']);
681
682
expect(onRender).toHaveBeenCalledTimes(3);
683
expect(onRender.mock.calls[0][1]).toBe('mount');
@@ -711,7 +719,7 @@ describe(`onRender`, () => {
719
</React.Profiler>,
720
);
721
});
714
- expect(Scheduler).toHaveYielded([false, true]);
722
+ assertLog([false, true]);
723
724
// Verify that the nested update inside of the sync work is appropriately tagged.
725
expect(onRender).toHaveBeenCalledTimes(2);
@@ -720,7 +728,7 @@ describe(`onRender`, () => {
728
});
729
730
describe('with regard to interruptions', () => {
723
- it('should accumulate actual time after a scheduling interruptions', () => {
731
+ it('should accumulate actual time after a scheduling interruptions', async () => {
732
const callback = jest.fn();
733
734
const Yield = ({renderTime}) => {
@@ -741,11 +749,11 @@ describe(`onRender`, () => {
749
{unstable_isConcurrent: true},
750
);
751
});
744
- expect(Scheduler).toFlushAndYieldThrough(['Yield:2']);
752
+ await waitFor(['Yield:2']);
753
expect(callback).toHaveBeenCalledTimes(0);
754
755
// Resume render for remaining children.
748
- expect(Scheduler).toFlushAndYield(['Yield:3']);
756
+ await waitForAll(['Yield:3']);
757
758
// Verify that logged times include both durations above.
759
expect(callback).toHaveBeenCalledTimes(1);
@@ -756,7 +764,7 @@ describe(`onRender`, () => {
764
expect(call[5]).toBe(10); // commit time
765
});
766
759
- it('should not include time between frames', () => {
767
+ it('should not include time between frames', async () => {
768
const callback = jest.fn();
769
770
const Yield = ({renderTime}) => {
@@ -781,7 +789,7 @@ describe(`onRender`, () => {
789
{unstable_isConcurrent: true},
790
);
791
});
784
- expect(Scheduler).toFlushAndYieldThrough(['Yield:5']);
792
+ await waitFor(['Yield:5']);
793
expect(callback).toHaveBeenCalledTimes(0);
794
795
// Simulate time moving forward while frame is paused.
@@ -789,7 +797,7 @@ describe(`onRender`, () => {
797
798
// Flush the remaining work,
799
// Which should take an additional 10ms of simulated time.
792
- expect(Scheduler).toFlushAndYield(['Yield:10', 'Yield:17']);
800
+ await waitForAll(['Yield:10', 'Yield:17']);
801
expect(callback).toHaveBeenCalledTimes(2);
802
803
const [innerCall, outerCall] = callback.mock.calls;
@@ -808,7 +816,7 @@ describe(`onRender`, () => {
816
expect(outerCall[5]).toBe(87); // commit time
817
});
818
811
- it('should report the expected times when a high-pri update replaces a mount in-progress', () => {
819
+ it('should report the expected times when a high-pri update replaces a mount in-progress', async () => {
820
const callback = jest.fn();
821
822
const Yield = ({renderTime}) => {
@@ -831,7 +839,7 @@ describe(`onRender`, () => {
839
{unstable_isConcurrent: true},
840
);
841
});
834
- expect(Scheduler).toFlushAndYieldThrough(['Yield:10']);
842
+ await waitFor(['Yield:10']);
843
expect(callback).toHaveBeenCalledTimes(0);
844
845
// Simulate time moving forward while frame is paused.
@@ -846,7 +854,7 @@ describe(`onRender`, () => {
854
</React.Profiler>,
855
);
856
});
849
- expect(Scheduler).toHaveYielded(['Yield:5']);
857
+ assertLog(['Yield:5']);
858
859
// The initial work was thrown away in this case,
860
// So the actual and base times should only include the final rendered tree times.
@@ -860,11 +868,11 @@ describe(`onRender`, () => {
868
callback.mockReset();
869
870
// Verify no more unexpected callbacks from low priority work
863
- expect(Scheduler).toFlushWithoutYielding();
871
+ await waitForAll([]);
872
expect(callback).toHaveBeenCalledTimes(0);
873
});
874
867
- it('should report the expected times when a high-priority update replaces a low-priority update', () => {
875
+ it('should report the expected times when a high-priority update replaces a low-priority update', async () => {
876
const callback = jest.fn();
877
878
const Yield = ({renderTime}) => {
@@ -885,7 +893,7 @@ describe(`onRender`, () => {
893
894
// Render everything initially.
895
// This should take 21 seconds of actual and base time.
888
- expect(Scheduler).toFlushAndYield(['Yield:6', 'Yield:15']);
896
+ await waitForAll(['Yield:6', 'Yield:15']);
897
expect(callback).toHaveBeenCalledTimes(1);
898
let call = callback.mock.calls[0];
899
expect(call[2]).toBe(21); // actual time
@@ -908,14 +916,14 @@ describe(`onRender`, () => {
916
</React.Profiler>,
917
);
918
});
911
- expect(Scheduler).toFlushAndYieldThrough(['Yield:3']);
919
+ await waitFor(['Yield:3']);
920
expect(callback).toHaveBeenCalledTimes(0);
921
922
// Simulate time moving forward while frame is paused.
923
Scheduler.unstable_advanceTime(100); // 59 -> 159
924
925
// Render another 5ms of simulated time.
918
- expect(Scheduler).toFlushAndYieldThrough(['Yield:5']);
926
+ await waitFor(['Yield:5']);
927
expect(callback).toHaveBeenCalledTimes(0);
928
929
// Simulate time moving forward while frame is paused.
@@ -930,7 +938,7 @@ describe(`onRender`, () => {
938
</React.Profiler>,
939
);
940
});
933
- expect(Scheduler).toHaveYielded(['Yield:11']);
941
+ assertLog(['Yield:11']);
942
943
// The actual time should include only the most recent render,
944
// Because this lets us avoid a lot of commit phase reset complexity.
@@ -943,11 +951,11 @@ describe(`onRender`, () => {
951
expect(call[5]).toBe(275); // commit time
952
953
// Verify no more unexpected callbacks from low priority work
946
- expect(Scheduler).toFlushAndYield([]);
954
+ await waitForAll([]);
955
expect(callback).toHaveBeenCalledTimes(1);
956
});
957
950
- it('should report the expected times when a high-priority update interrupts a low-priority update', () => {
958
+ it('should report the expected times when a high-priority update interrupts a low-priority update', async () => {
959
const callback = jest.fn();
960
961
const Yield = ({renderTime}) => {
@@ -994,7 +1002,7 @@ describe(`onRender`, () => {
1002
// Render everything initially.
1003
// This simulates a total of 14ms of actual render time.
1004
// The base render time is also 14ms for the initial render.
997
- expect(Scheduler).toFlushAndYield([
1005
+ await waitForAll([
1006
'FirstComponent:1',
1007
'Yield:4',
1008
'SecondComponent:2',
@@ -1016,7 +1024,7 @@ describe(`onRender`, () => {
1024
React.startTransition(() => {
1025
first.setState({renderTime: 10});
1026
});
1019
- expect(Scheduler).toFlushAndYieldThrough(['FirstComponent:10']);
1027
+ await waitFor(['FirstComponent:10']);
1028
expect(callback).toHaveBeenCalledTimes(0);
1029
1030
// Simulate time moving forward while frame is paused.
@@ -1025,7 +1033,7 @@ describe(`onRender`, () => {
1033
// Interrupt with higher priority work.
1034
// This simulates a total of 37ms of actual render time.
1035
renderer.unstable_flushSync(() => second.setState({renderTime: 30}));
1028
- expect(Scheduler).toHaveYielded(['SecondComponent:30', 'Yield:7']);
1036
+ assertLog(['SecondComponent:30', 'Yield:7']);
1037
1038
// The actual time should include only the most recent render (37ms),
1039
// Because this greatly simplifies the commit phase logic.
@@ -1049,7 +1057,7 @@ describe(`onRender`, () => {
1057
// The tree contains 42ms of base render time at this point,
1058
// Reflecting the most recent (longer) render durations.
1059
// TODO: This actual time should decrease by 10ms once the scheduler supports resuming.
1052
- expect(Scheduler).toFlushAndYield(['FirstComponent:10', 'Yield:4']);
1060
+ await waitForAll(['FirstComponent:10', 'Yield:4']);
1061
expect(callback).toHaveBeenCalledTimes(1);
1062
call = callback.mock.calls[0];
1063
expect(call[2]).toBe(14); // actual time
@@ -1207,7 +1215,7 @@ describe(`onRender`, () => {
1215
);
1216
});
1217
1210
- it('should reset the fiber stack correct after a "complete" phase error', () => {
1218
+ it('should reset the fiber stack correct after a "complete" phase error', async () => {
1219
jest.resetModules();
1220
1221
loadModules({
@@ -1242,7 +1250,7 @@ describe(`onRender`, () => {
1250
<span>hi</span>
1251
</React.Profiler>,
1252
);
1245
- expect(Scheduler).toFlushWithoutYielding();
1253
+ await waitForAll([]);
1254
});
1255
});
1256
});
@@ -2381,12 +2389,12 @@ describe(`onNestedUpdateScheduled`, () => {
2389
);
2390
});
2391
2384
- expect(Scheduler).toHaveYielded(['Component:false', 'Component:true']);
2392
+ assertLog(['Component:false', 'Component:true']);
2393
expect(onNestedUpdateScheduled).toHaveBeenCalledTimes(1);
2394
expect(onNestedUpdateScheduled.mock.calls[0][0]).toBe('test');
2395
});
2396
2389
- it('is called when a function component schedules a batched update during a layout effect', () => {
2397
+ it('is called when a function component schedules a batched update during a layout effect', async () => {
2398
function Component() {
2399
const [didMount, setDidMount] = React.useState(false);
2400
React.useLayoutEffect(() => {
@@ -2409,7 +2417,7 @@ describe(`onNestedUpdateScheduled`, () => {
2417
<Component />
2418
</React.Profiler>,
2419
);
2412
- expect(Scheduler).toFlushAndYield(['Component:false', 'Component:true']);
2420
+ await waitForAll(['Component:false', 'Component:true']);
2421
2422
expect(onRender).toHaveBeenCalledTimes(2);
2423
expect(onRender.mock.calls[0][1]).toBe('mount');
@@ -2452,7 +2460,7 @@ describe(`onNestedUpdateScheduled`, () => {
2460
);
2461
});
2462
2455
- expect(Scheduler).toHaveYielded(['Component:false', 'Component:true']);
2463
+ assertLog(['Component:false', 'Component:true']);
2464
expect(onNestedUpdateScheduledOne).toHaveBeenCalledTimes(1);
2465
expect(onNestedUpdateScheduledOne.mock.calls[0][0]).toBe('one');
2466
expect(onNestedUpdateScheduledTwo).toHaveBeenCalledTimes(1);
@@ -2500,7 +2508,7 @@ describe(`onNestedUpdateScheduled`, () => {
2508
);
2509
});
2510
2503
- expect(Scheduler).toHaveYielded([
2511
+ assertLog([
2512
'ComponentRootOne:false',
2513
'ComponentRootTwo',
2514
'ComponentRootOne:true',
@@ -2530,7 +2538,7 @@ describe(`onNestedUpdateScheduled`, () => {
2538
);
2539
});
2540
2533
- expect(Scheduler).toHaveYielded(['Component:false', 'Component:true']);
2541
+ assertLog(['Component:false', 'Component:true']);
2542
expect(onNestedUpdateScheduled).not.toHaveBeenCalled();
2543
});
2544
@@ -2555,12 +2563,12 @@ describe(`onNestedUpdateScheduled`, () => {
2563
</React.Profiler>,
2564
);
2565
});
2558
- expect(Scheduler).toHaveYielded(['Component:false']);
2566
+ assertLog(['Component:false']);
2567
2568
act(() => {
2569
updateFnRef.current();
2570
});
2563
- expect(Scheduler).toHaveYielded(['Component:true']);
2571
+ assertLog(['Component:true']);
2572
expect(onNestedUpdateScheduled).not.toHaveBeenCalled();
2573
});
2574
@@ -2586,7 +2594,7 @@ describe(`onNestedUpdateScheduled`, () => {
2594
);
2595
});
2596
2589
- expect(Scheduler).toHaveYielded(['Component:false', 'Component:true']);
2597
+ assertLog(['Component:false', 'Component:true']);
2598
expect(onNestedUpdateScheduled).not.toHaveBeenCalled();
2599
});
2600
@@ -2617,10 +2625,7 @@ describe(`onNestedUpdateScheduled`, () => {
2625
);
2626
});
2627
2620
- expect(Scheduler).toHaveYielded([
2621
- 'Component:false:false',
2622
- 'Component:true:false',
2623
- ]);
2628
+ assertLog(['Component:false:false', 'Component:true:false']);
2629
expect(onNestedUpdateScheduled).toHaveBeenCalledTimes(1);
2630
expect(onNestedUpdateScheduled.mock.calls[0][0]).toBe('test');
2631
@@ -2634,10 +2639,7 @@ describe(`onNestedUpdateScheduled`, () => {
2639
);
2640
});
2641
2637
- expect(Scheduler).toHaveYielded([
2638
- 'Component:true:false',
2639
- 'Component:true:true',
2640
- ]);
2642
+ assertLog(['Component:true:false', 'Component:true:true']);
2643
expect(onNestedUpdateScheduled).toHaveBeenCalledTimes(2);
2644
expect(onNestedUpdateScheduled.mock.calls[1][0]).toBe('test');
2645
});
@@ -2669,7 +2671,7 @@ describe(`onNestedUpdateScheduled`, () => {
2671
);
2672
});
2673
2672
- expect(Scheduler).toHaveYielded(['Component:false', 'Component:true']);
2674
+ assertLog(['Component:false', 'Component:true']);
2675
expect(onNestedUpdateScheduled).toHaveBeenCalledTimes(1);
2676
expect(onNestedUpdateScheduled.mock.calls[0][0]).toBe('test');
2677
});
@@ -2708,7 +2710,7 @@ describe(`onNestedUpdateScheduled`, () => {
2710
</React.Profiler>,
2711
);
2712
});
2711
- expect(Scheduler).toHaveYielded(['Component:false:false']);
2713
+ assertLog(['Component:false:false']);
2714
expect(onNestedUpdateScheduled).not.toHaveBeenCalled();
2715
2716
act(() => {
@@ -2721,10 +2723,7 @@ describe(`onNestedUpdateScheduled`, () => {
2723
);
2724
});
2725
2724
- expect(Scheduler).toHaveYielded([
2725
- 'Component:true:false',
2726
- 'Component:true:true',
2727
- ]);
2726
+ assertLog(['Component:true:false', 'Component:true:true']);
2727
expect(onNestedUpdateScheduled).toHaveBeenCalledTimes(1);
2728
expect(onNestedUpdateScheduled.mock.calls[0][0]).toBe('test');
2729
});
@@ -2755,12 +2754,12 @@ describe(`onNestedUpdateScheduled`, () => {
2754
</React.Profiler>,
2755
);
2756
});
2758
- expect(Scheduler).toHaveYielded(['Component:false']);
2757
+ assertLog(['Component:false']);
2758
2759
act(() => {
2760
updateFnRef.current();
2761
});
2763
- expect(Scheduler).toHaveYielded(['Component:true']);
2762
+ assertLog(['Component:true']);
2763
expect(onNestedUpdateScheduled).not.toHaveBeenCalled();
2764
});
2765
packages/react/src/__tests__/ReactProfilerDevToolsIntegration-test.internal.js
+10
-4
@@ -17,6 +17,8 @@ describe('ReactProfiler DevTools integration', () => {
17
let Scheduler;
18
let AdvanceTime;
19
let hook;
20
+ let waitForAll;
21
+ let waitFor;
22
23
beforeEach(() => {
24
global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook = {
@@ -34,6 +36,10 @@ describe('ReactProfiler DevTools integration', () => {
36
React = require('react');
37
ReactTestRenderer = require('react-test-renderer');
38
39
+ const InternalTestUtils = require('internal-test-utils');
40
+ waitForAll = InternalTestUtils.waitForAll;
41
+ waitFor = InternalTestUtils.waitFor;
42
+
43
AdvanceTime = class extends React.Component {
44
static defaultProps = {
45
byAmount: 10,
@@ -138,7 +144,7 @@ describe('ReactProfiler DevTools integration', () => {
144
).toBe(7);
145
});
146
141
- it('regression test: #17159', () => {
147
+ it('regression test: #17159', async () => {
148
function Text({text}) {
149
Scheduler.unstable_yieldValue(text);
150
return text;
@@ -148,7 +154,7 @@ describe('ReactProfiler DevTools integration', () => {
154
155
// Commit something
156
root.update(<Text text="A" />);
151
- expect(Scheduler).toFlushAndYield(['A']);
157
+ await waitForAll(['A']);
158
expect(root).toMatchRenderedOutput('A');
159
160
// Advance time by many seconds, larger than the default expiration time
@@ -160,9 +166,9 @@ describe('ReactProfiler DevTools integration', () => {
166
});
167
168
// Update B should not instantly expire.
163
- expect(Scheduler).toFlushAndYieldThrough([]);
169
+ await waitFor([]);
170
165
- expect(Scheduler).toFlushAndYield(['B']);
171
+ await waitForAll(['B']);
172
expect(root).toMatchRenderedOutput('B');
173
});
174
});
packages/react/src/__tests__/forwardRef-test.internal.js
+18
-14
@@ -14,6 +14,7 @@ describe('forwardRef', () => {
14
let ReactFeatureFlags;
15
let ReactNoop;
16
let Scheduler;
17
+ let waitForAll;
18
19
beforeEach(() => {
20
jest.resetModules();
@@ -23,9 +24,12 @@ describe('forwardRef', () => {
24
React = require('react');
25
ReactNoop = require('react-noop-renderer');
26
Scheduler = require('scheduler');
27
+
28
+ const InternalTestUtils = require('internal-test-utils');
29
+ waitForAll = InternalTestUtils.waitForAll;
30
});
31
28
- it('should work without a ref to be forwarded', () => {
32
+ it('should work without a ref to be forwarded', async () => {
33
class Child extends React.Component {
34
render() {
35
Scheduler.unstable_yieldValue(this.props.value);
@@ -42,10 +46,10 @@ describe('forwardRef', () => {
46
));
47
48
ReactNoop.render(<RefForwardingComponent value={123} />);
45
- expect(Scheduler).toFlushAndYield([123]);
49
+ await waitForAll([123]);
50
});
51
48
- it('should forward a ref for a single child', () => {
52
+ it('should forward a ref for a single child', async () => {
53
class Child extends React.Component {
54
render() {
55
Scheduler.unstable_yieldValue(this.props.value);
@@ -64,11 +68,11 @@ describe('forwardRef', () => {
68
const ref = React.createRef();
69
70
ReactNoop.render(<RefForwardingComponent ref={ref} value={123} />);
67
- expect(Scheduler).toFlushAndYield([123]);
71
+ await waitForAll([123]);
72
expect(ref.current instanceof Child).toBe(true);
73
});
74
71
- it('should forward a ref for multiple children', () => {
75
+ it('should forward a ref for multiple children', async () => {
76
class Child extends React.Component {
77
render() {
78
Scheduler.unstable_yieldValue(this.props.value);
@@ -93,11 +97,11 @@ describe('forwardRef', () => {
97
<div />
98
</div>,
99
);
96
- expect(Scheduler).toFlushAndYield([123]);
100
+ await waitForAll([123]);
101
expect(ref.current instanceof Child).toBe(true);
102
});
103
100
- it('should maintain child instance and ref through updates', () => {
104
+ it('should maintain child instance and ref through updates', async () => {
105
class Child extends React.Component {
106
constructor(props) {
107
super(props);
@@ -125,16 +129,16 @@ describe('forwardRef', () => {
129
};
130
131
ReactNoop.render(<RefForwardingComponent ref={setRef} value={123} />);
128
- expect(Scheduler).toFlushAndYield([123]);
132
+ await waitForAll([123]);
133
expect(ref instanceof Child).toBe(true);
134
expect(setRefCount).toBe(1);
135
ReactNoop.render(<RefForwardingComponent ref={setRef} value={456} />);
132
- expect(Scheduler).toFlushAndYield([456]);
136
+ await waitForAll([456]);
137
expect(ref instanceof Child).toBe(true);
138
expect(setRefCount).toBe(1);
139
});
140
137
- it('should not break lifecycle error handling', () => {
141
+ it('should not break lifecycle error handling', async () => {
142
class ErrorBoundary extends React.Component {
143
state = {error: null};
144
componentDidCatch(error) {
@@ -175,7 +179,7 @@ describe('forwardRef', () => {
179
<RefForwardingComponent ref={ref} />
180
</ErrorBoundary>,
181
);
178
- expect(Scheduler).toFlushAndYield([
182
+ await waitForAll([
183
'ErrorBoundary.render: try',
184
'Wrapper',
185
'BadRender throw',
@@ -192,7 +196,7 @@ describe('forwardRef', () => {
196
expect(ref.current).toBe(null);
197
});
198
195
- it('should not re-run the render callback on a deep setState', () => {
199
+ it('should not re-run the render callback on a deep setState', async () => {
200
let inst;
201
202
class Inner extends React.Component {
@@ -219,9 +223,9 @@ describe('forwardRef', () => {
223
}
224
225
ReactNoop.render(<App />);
222
- expect(Scheduler).toFlushAndYield(['App', 'Forward', 'Middle', 'Inner']);
226
+ await waitForAll(['App', 'Forward', 'Middle', 'Inner']);
227
228
inst.setState({});
225
- expect(Scheduler).toFlushAndYield(['Inner']);
229
+ await waitForAll(['Inner']);
230
});
231
});
packages/react/src/__tests__/forwardRef-test.js
+31
-29
@@ -13,17 +13,19 @@ describe('forwardRef', () => {
13
let PropTypes;
14
let React;
15
let ReactNoop;
16
- let Scheduler;
16
+ let waitForAll;
17
18
beforeEach(() => {
19
jest.resetModules();
20
PropTypes = require('prop-types');
21
React = require('react');
22
ReactNoop = require('react-noop-renderer');
23
- Scheduler = require('scheduler');
23
+
24
+ const InternalTestUtils = require('internal-test-utils');
25
+ waitForAll = InternalTestUtils.waitForAll;
26
});
27
26
- it('should update refs when switching between children', () => {
28
+ it('should update refs when switching between children', async () => {
29
function FunctionComponent({forwardedRef, setRefOnDiv}) {
30
return (
31
<section>
@@ -40,25 +42,25 @@ describe('forwardRef', () => {
42
const ref = React.createRef();
43
44
ReactNoop.render(<RefForwardingComponent ref={ref} setRefOnDiv={true} />);
43
- expect(Scheduler).toFlushWithoutYielding();
45
+ await waitForAll([]);
46
expect(ref.current.type).toBe('div');
47
48
ReactNoop.render(<RefForwardingComponent ref={ref} setRefOnDiv={false} />);
47
- expect(Scheduler).toFlushWithoutYielding();
49
+ await waitForAll([]);
50
expect(ref.current.type).toBe('span');
51
});
52
51
- it('should support rendering null', () => {
53
+ it('should support rendering null', async () => {
54
const RefForwardingComponent = React.forwardRef((props, ref) => null);
55
56
const ref = React.createRef();
57
58
ReactNoop.render(<RefForwardingComponent ref={ref} />);
57
- expect(Scheduler).toFlushWithoutYielding();
59
+ await waitForAll([]);
60
expect(ref.current).toBe(null);
61
});
62
61
- it('should support rendering null for multiple children', () => {
63
+ it('should support rendering null for multiple children', async () => {
64
const RefForwardingComponent = React.forwardRef((props, ref) => null);
65
66
const ref = React.createRef();
@@ -70,11 +72,11 @@ describe('forwardRef', () => {
72
<div />
73
</div>,
74
);
73
- expect(Scheduler).toFlushWithoutYielding();
75
+ await waitForAll([]);
76
expect(ref.current).toBe(null);
77
});
78
77
- it('should support propTypes and defaultProps', () => {
79
+ it('should support propTypes and defaultProps', async () => {
80
function FunctionComponent({forwardedRef, optional, required}) {
81
return (
82
<div ref={forwardedRef}>
@@ -103,14 +105,14 @@ describe('forwardRef', () => {
105
ReactNoop.render(
106
<RefForwardingComponent ref={ref} optional="foo" required="bar" />,
107
);
106
- expect(Scheduler).toFlushWithoutYielding();
108
+ await waitForAll([]);
109
expect(ref.current.children).toEqual([
110
{text: 'foo', hidden: false},
111
{text: 'bar', hidden: false},
112
]);
113
114
ReactNoop.render(<RefForwardingComponent ref={ref} required="foo" />);
113
- expect(Scheduler).toFlushWithoutYielding();
115
+ await waitForAll([]);
116
expect(ref.current.children).toEqual([
117
{text: 'default', hidden: false},
118
{text: 'foo', hidden: false},
@@ -344,7 +346,7 @@ describe('forwardRef', () => {
346
);
347
});
348
347
- it('should not bailout if forwardRef is not wrapped in memo', () => {
349
+ it('should not bailout if forwardRef is not wrapped in memo', async () => {
350
const Component = props => <div {...props} />;
351
352
let renderCount = 0;
@@ -357,15 +359,15 @@ describe('forwardRef', () => {
359
const ref = React.createRef();
360
361
ReactNoop.render(<RefForwardingComponent ref={ref} optional="foo" />);
360
- expect(Scheduler).toFlushWithoutYielding();
362
+ await waitForAll([]);
363
expect(renderCount).toBe(1);
364
365
ReactNoop.render(<RefForwardingComponent ref={ref} optional="foo" />);
364
- expect(Scheduler).toFlushWithoutYielding();
366
+ await waitForAll([]);
367
expect(renderCount).toBe(2);
368
});
369
368
- it('should bailout if forwardRef is wrapped in memo', () => {
370
+ it('should bailout if forwardRef is wrapped in memo', async () => {
371
const Component = props => <div ref={props.forwardedRef} />;
372
373
let renderCount = 0;
@@ -380,13 +382,13 @@ describe('forwardRef', () => {
382
const ref = React.createRef();
383
384
ReactNoop.render(<RefForwardingComponent ref={ref} optional="foo" />);
383
- expect(Scheduler).toFlushWithoutYielding();
385
+ await waitForAll([]);
386
expect(renderCount).toBe(1);
387
388
expect(ref.current.type).toBe('div');
389
390
ReactNoop.render(<RefForwardingComponent ref={ref} optional="foo" />);
389
- expect(Scheduler).toFlushWithoutYielding();
391
+ await waitForAll([]);
392
expect(renderCount).toBe(1);
393
394
const differentRef = React.createRef();
@@ -394,18 +396,18 @@ describe('forwardRef', () => {
396
ReactNoop.render(
397
<RefForwardingComponent ref={differentRef} optional="foo" />,
398
);
397
- expect(Scheduler).toFlushWithoutYielding();
399
+ await waitForAll([]);
400
expect(renderCount).toBe(2);
401
402
expect(ref.current).toBe(null);
403
expect(differentRef.current.type).toBe('div');
404
405
ReactNoop.render(<RefForwardingComponent ref={ref} optional="bar" />);
404
- expect(Scheduler).toFlushWithoutYielding();
406
+ await waitForAll([]);
407
expect(renderCount).toBe(3);
408
});
409
408
- it('should custom memo comparisons to compose', () => {
410
+ it('should custom memo comparisons to compose', async () => {
411
const Component = props => <div ref={props.forwardedRef} />;
412
413
let renderCount = 0;
@@ -421,19 +423,19 @@ describe('forwardRef', () => {
423
const ref = React.createRef();
424
425
ReactNoop.render(<RefForwardingComponent ref={ref} a="0" b="0" c="1" />);
424
- expect(Scheduler).toFlushWithoutYielding();
426
+ await waitForAll([]);
427
expect(renderCount).toBe(1);
428
429
expect(ref.current.type).toBe('div');
430
431
// Changing either a or b rerenders
432
ReactNoop.render(<RefForwardingComponent ref={ref} a="0" b="1" c="1" />);
431
- expect(Scheduler).toFlushWithoutYielding();
433
+ await waitForAll([]);
434
expect(renderCount).toBe(2);
435
436
// Changing c doesn't rerender
437
ReactNoop.render(<RefForwardingComponent ref={ref} a="0" b="1" c="2" />);
436
- expect(Scheduler).toFlushWithoutYielding();
438
+ await waitForAll([]);
439
expect(renderCount).toBe(2);
440
441
const ComposedMemo = React.memo(
@@ -442,29 +444,29 @@ describe('forwardRef', () => {
444
);
445
446
ReactNoop.render(<ComposedMemo ref={ref} a="0" b="0" c="0" />);
445
- expect(Scheduler).toFlushWithoutYielding();
447
+ await waitForAll([]);
448
expect(renderCount).toBe(3);
449
450
// Changing just b no longer updates
451
ReactNoop.render(<ComposedMemo ref={ref} a="0" b="1" c="0" />);
450
- expect(Scheduler).toFlushWithoutYielding();
452
+ await waitForAll([]);
453
expect(renderCount).toBe(3);
454
455
// Changing just a and c updates
456
ReactNoop.render(<ComposedMemo ref={ref} a="2" b="2" c="2" />);
455
- expect(Scheduler).toFlushWithoutYielding();
457
+ await waitForAll([]);
458
expect(renderCount).toBe(4);
459
460
// Changing just c does not update
461
ReactNoop.render(<ComposedMemo ref={ref} a="2" b="2" c="3" />);
460
- expect(Scheduler).toFlushWithoutYielding();
462
+ await waitForAll([]);
463
expect(renderCount).toBe(4);
464
465
// Changing ref still rerenders
466
const differentRef = React.createRef();
467
468
ReactNoop.render(<ComposedMemo ref={differentRef} a="2" b="2" c="3" />);
467
- expect(Scheduler).toFlushWithoutYielding();
469
+ await waitForAll([]);
470
expect(renderCount).toBe(5);
471
472
expect(ref.current).toBe(null);
scripts/jest/config.build-devtools.js
+6
@@ -17,6 +17,12 @@ const packages = readdirSync(packagesRoot).filter(dir => {
17
if (dir.includes('react-devtools')) {
18
return false;
19
}
20
+ if (dir === 'internal-test-utils') {
21
+ // This is an internal package used only for testing. It's OK to read
22
+ // from source.
23
+ // TODO: Maybe let's have some convention for this?
24
+ return false;
25
+ }
26
const packagePath = join(packagesRoot, dir, 'package.json');
27
let stat;
28
try {