Skip to content

Commit 72c890e

Browse files
authored
Convert more Suspense tests to use act (2/n) (#26610)
Many of our Suspense-related tests were written before the `act` API was introduced, and use the lower level `waitFor` helpers instead. So they are less resilient to changes in implementation details than they could be. This converts some of our test suite to use `act` in more places. I found these while working on a PR to expand our fallback throttling mechanism to include all renders that result from a promise resolving, even if there are no more fallbacks in the tree. I think this covers all the remaining tests that are affected.
1 parent 21021fb commit 72c890e

13 files changed

+422
-429
lines changed

packages/react-cache/src/__tests__/ReactCacheOld-test.internal.js

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ let textResourceShouldFail;
2121
let waitForAll;
2222
let assertLog;
2323
let waitForThrow;
24+
let act;
2425

2526
describe('ReactCache', () => {
2627
beforeEach(() => {
@@ -40,6 +41,7 @@ describe('ReactCache', () => {
4041
waitForAll = InternalTestUtils.waitForAll;
4142
assertLog = InternalTestUtils.assertLog;
4243
waitForThrow = InternalTestUtils.waitForThrow;
44+
act = InternalTestUtils.act;
4345

4446
TextResource = createResource(
4547
([text, ms = 0]) => {
@@ -145,11 +147,14 @@ describe('ReactCache', () => {
145147
await waitForAll(['Suspend! [Hi]', 'Loading...']);
146148

147149
textResourceShouldFail = true;
148-
jest.advanceTimersByTime(100);
149-
assertLog(['Promise rejected [Hi]']);
150-
151-
await waitForThrow('Failed to load: Hi');
152-
assertLog(['Error! [Hi]', 'Error! [Hi]']);
150+
let error;
151+
try {
152+
await act(() => jest.advanceTimersByTime(100));
153+
} catch (e) {
154+
error = e;
155+
}
156+
expect(error.message).toMatch('Failed to load: Hi');
157+
assertLog(['Promise rejected [Hi]', 'Error! [Hi]', 'Error! [Hi]']);
153158

154159
// Should throw again on a subsequent read
155160
root.update(<App />);
@@ -217,9 +222,8 @@ describe('ReactCache', () => {
217222
assertLog(['Promise resolved [2]']);
218223
await waitForAll([1, 2, 'Suspend! [3]']);
219224

220-
jest.advanceTimersByTime(100);
221-
assertLog(['Promise resolved [3]']);
222-
await waitForAll([1, 2, 3]);
225+
await act(() => jest.advanceTimersByTime(100));
226+
assertLog(['Promise resolved [3]', 1, 2, 3]);
223227

224228
expect(root).toMatchRenderedOutput('123');
225229

@@ -234,13 +238,17 @@ describe('ReactCache', () => {
234238

235239
await waitForAll([1, 'Suspend! [4]', 'Loading...']);
236240

237-
jest.advanceTimersByTime(100);
238-
assertLog(['Promise resolved [4]']);
239-
await waitForAll([1, 4, 'Suspend! [5]']);
240-
241-
jest.advanceTimersByTime(100);
242-
assertLog(['Promise resolved [5]']);
243-
await waitForAll([1, 4, 5]);
241+
await act(() => jest.advanceTimersByTime(100));
242+
assertLog([
243+
'Promise resolved [4]',
244+
1,
245+
4,
246+
'Suspend! [5]',
247+
'Promise resolved [5]',
248+
1,
249+
4,
250+
5,
251+
]);
244252

245253
expect(root).toMatchRenderedOutput('145');
246254

@@ -262,13 +270,18 @@ describe('ReactCache', () => {
262270
'Suspend! [2]',
263271
'Loading...',
264272
]);
265-
jest.advanceTimersByTime(100);
266-
assertLog(['Promise resolved [2]']);
267-
await waitForAll([1, 2, 'Suspend! [3]']);
268273

269-
jest.advanceTimersByTime(100);
270-
assertLog(['Promise resolved [3]']);
271-
await waitForAll([1, 2, 3]);
274+
await act(() => jest.advanceTimersByTime(100));
275+
assertLog([
276+
'Promise resolved [2]',
277+
1,
278+
2,
279+
'Suspend! [3]',
280+
'Promise resolved [3]',
281+
1,
282+
2,
283+
3,
284+
]);
272285
expect(root).toMatchRenderedOutput('123');
273286
});
274287

@@ -291,9 +304,8 @@ describe('ReactCache', () => {
291304

292305
await waitForAll(['Loading...']);
293306

294-
jest.advanceTimersByTime(1000);
295-
assertLog(['Promise resolved [B]', 'Promise resolved [A]']);
296-
await waitForAll(['Result']);
307+
await act(() => jest.advanceTimersByTime(1000));
308+
assertLog(['Promise resolved [B]', 'Promise resolved [A]', 'Result']);
297309
expect(root).toMatchRenderedOutput('Result');
298310
});
299311

packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ let waitFor;
4242
let waitForAll;
4343
let assertLog;
4444
let waitForPaint;
45+
let clientAct;
4546

4647
function resetJSDOM(markup) {
4748
// Test Environment
@@ -74,6 +75,7 @@ describe('ReactDOMFizzServer', () => {
7475
waitFor = InternalTestUtils.waitFor;
7576
waitForPaint = InternalTestUtils.waitForPaint;
7677
assertLog = InternalTestUtils.assertLog;
78+
clientAct = InternalTestUtils.act;
7779

7880
if (gate(flags => flags.source)) {
7981
// The `with-selector` module composes the main `use-sync-external-store`
@@ -1191,8 +1193,8 @@ describe('ReactDOMFizzServer', () => {
11911193
expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);
11921194

11931195
// We now resolve it on the client.
1194-
resolveText('Hello');
1195-
await waitForAll([]);
1196+
await clientAct(() => resolveText('Hello'));
1197+
assertLog([]);
11961198

11971199
// The client rendered HTML is now in place.
11981200
expect(getVisibleChildren(container)).toEqual(
@@ -2884,10 +2886,10 @@ describe('ReactDOMFizzServer', () => {
28842886
</div>,
28852887
);
28862888

2887-
await act(() => {
2889+
await clientAct(() => {
28882890
resolveText('Yay!');
28892891
});
2890-
await waitForAll(['Yay!']);
2892+
assertLog(['Yay!']);
28912893
expect(getVisibleChildren(container)).toEqual(
28922894
<div>
28932895
<span />
@@ -4310,10 +4312,10 @@ describe('ReactDOMFizzServer', () => {
43104312
<h1>Loading...</h1>
43114313
</div>,
43124314
);
4313-
await unsuspend();
4315+
await clientAct(() => unsuspend());
43144316
// Since our client components only throw on the very first render there are no
43154317
// new throws in this pass
4316-
await waitForAll([]);
4318+
assertLog([]);
43174319
expect(mockError.mock.calls).toEqual([]);
43184320

43194321
expect(getVisibleChildren(container)).toEqual(

packages/react-dom/src/__tests__/ReactDOMFloat-test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ let waitForAll;
3737
let waitForThrow;
3838
let assertLog;
3939
let Scheduler;
40+
let clientAct;
4041

4142
function resetJSDOM(markup) {
4243
// Test Environment
@@ -71,6 +72,7 @@ describe('ReactDOMFloat', () => {
7172
waitForAll = InternalTestUtils.waitForAll;
7273
waitForThrow = InternalTestUtils.waitForThrow;
7374
assertLog = InternalTestUtils.assertLog;
75+
clientAct = InternalTestUtils.act;
7476

7577
textCache = new Map();
7678
loadCache = new Set();
@@ -1186,7 +1188,7 @@ body {
11861188
// events have already fired. This requires the load to be awaited for the commit to have a chance to flush
11871189
// We could change this by tracking the loadingState's fulfilled status directly on the loadingState similar
11881190
// to thenables however this slightly increases the fizz runtime code size.
1189-
await loadStylesheets();
1191+
await clientAct(() => loadStylesheets());
11901192
assertLog(['load stylesheet: foo']);
11911193
expect(getMeaningfulChildren(document)).toEqual(
11921194
<html>

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ let assertLog;
77
let ReactCache;
88
let Suspense;
99
let TextResource;
10+
let act;
1011

1112
describe('ReactBlockingMode', () => {
1213
beforeEach(() => {
@@ -23,6 +24,7 @@ describe('ReactBlockingMode', () => {
2324
const InternalTestUtils = require('internal-test-utils');
2425
waitForAll = InternalTestUtils.waitForAll;
2526
assertLog = InternalTestUtils.assertLog;
27+
act = InternalTestUtils.act;
2628

2729
TextResource = ReactCache.unstable_createResource(
2830
([text, ms = 0]) => {
@@ -117,9 +119,8 @@ describe('ReactBlockingMode', () => {
117119
// fallback should mount immediately.
118120
expect(root).toMatchRenderedOutput('Loading...');
119121

120-
await jest.advanceTimersByTime(1000);
121-
assertLog(['Promise resolved [B]']);
122-
await waitForAll(['A', 'B', 'C']);
122+
await act(() => jest.advanceTimersByTime(1000));
123+
assertLog(['Promise resolved [B]', 'A', 'B', 'C']);
123124
expect(root).toMatchRenderedOutput(
124125
<>
125126
<span>A</span>

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3623,9 +3623,8 @@ describe('ReactHooksWithNoopRenderer', () => {
36233623
</>,
36243624
);
36253625

3626-
await resolveText('A');
3627-
assertLog(['Promise resolved [A]']);
3628-
await waitForAll(['A']);
3626+
await act(() => resolveText('A'));
3627+
assertLog(['Promise resolved [A]', 'A']);
36293628
expect(ReactNoop).toMatchRenderedOutput(
36303629
<>
36313630
<span prop="A" />

0 commit comments

Comments
 (0)