@samitouri / QOS-React / commits / 42eff4bc78

[tests] Fix assertions not flushed before act (#28745)

Fixes some easy cases blocking https://github.com/facebook/react/pull/28737, I'll follow up with more complex/interesting cases in other PRs.

Ricky committed Apr 10, 2024 at 10:33 UTC 42eff4bc78a3636953c55096ca0b220c611a74cc
9 files changed +29 -23
packages/react-dom/src/__tests__/ReactCompositeComponent-test.js
+2 -4
@@ -913,15 +913,13 @@ describe('ReactCompositeComponent', () => {
913 await act(() => {
914 root.render(<Wrapper name="A" />);
915 });
916 +
917 + assertLog(['A componentWillMount', 'A render', 'A componentDidMount']);
918 await act(() => {
919 root.render(<Wrapper name="B" />);
920 });
921
922 assertLog([
921 - 'A componentWillMount',
922 - 'A render',
923 - 'A componentDidMount',
924 -
923 'B componentWillMount',
924 'B render',
925 'A componentWillUnmount',
packages/react-dom/src/__tests__/ReactDOMFizzDeferredValue-test.js
+2
@@ -111,9 +111,11 @@ describe('ReactDOMFizzForm', () => {
111 await readIntoContainer(stream);
112 expect(container.textContent).toEqual('Loading...');
113
114 + assertLog(['Loading...']);
115 // After hydration, it's updated to the final value
116 await act(() => ReactDOMClient.hydrateRoot(container, <App />));
117 expect(container.textContent).toEqual('Final');
118 + assertLog(['Loading...', 'Final']);
119 },
120 );
121
packages/react-dom/src/__tests__/ReactDOMNativeEventHeuristic-test.js
+2 -1
@@ -297,6 +297,7 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
297 });
298 expect(container.textContent).toEqual('not hovered');
299
300 + assertLog(['not hovered']);
301 await act(async () => {
302 // Note: React does not use native mouseenter/mouseleave events
303 // but we should still correctly determine their priority.
@@ -308,7 +309,7 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
309 dispatchAndSetCurrentEvent(target.current, mouseEnterEvent);
310
311 // Since mouse end is not discrete, should not have updated yet
311 - assertLog(['not hovered']);
312 + assertLog([]);
313 expect(container.textContent).toEqual('not hovered');
314
315 await waitFor(['hovered']);
packages/react-dom/src/__tests__/ReactDOMRoot-test.js
+2 -1
@@ -342,12 +342,13 @@ describe('ReactDOMRoot', () => {
342 root.render(<Foo value="a" />);
343 });
344
345 + assertLog(['a']);
346 expect(container.textContent).toEqual('a');
347
348 await act(async () => {
349 root.render(<Foo value="b" />);
350
350 - assertLog(['a']);
351 + assertLog([]);
352 expect(container.textContent).toEqual('a');
353
354 await waitFor(['b']);
packages/react-dom/src/__tests__/ReactDOMSuspensePlaceholder-test.js
+4 -2
@@ -17,6 +17,7 @@ let Suspense;
17 let Scheduler;
18 let act;
19 let textCache;
20 +let assertLog;
21
22 describe('ReactDOMSuspensePlaceholder', () => {
23 let container;
@@ -31,6 +32,7 @@ describe('ReactDOMSuspensePlaceholder', () => {
32 ReactDOMClient = require('react-dom/client');
33 Scheduler = require('scheduler');
34 act = require('internal-test-utils').act;
35 + assertLog = require('internal-test-utils').assertLog;
36 Suspense = React.Suspense;
37 container = document.createElement('div');
38 document.body.appendChild(container);
@@ -157,11 +159,11 @@ describe('ReactDOMSuspensePlaceholder', () => {
159 });
160
161 expect(container.textContent).toEqual('Loading...');
160 -
162 + assertLog(['A', 'Suspend! [B]', 'Loading...']);
163 await act(() => {
164 resolveText('B');
165 });
164 -
166 + assertLog(['A', 'B', 'C']);
167 expect(container.textContent).toEqual('ABC');
168 });
169
packages/react-dom/src/__tests__/ReactEmptyComponent-test.js
+3 -6
@@ -115,17 +115,14 @@ describe('ReactEmptyComponent', () => {
115 root1.render(instance1);
116 });
117
118 + assertLog(['mount undefined', 'update DIV']);
119 +
120 const root2 = ReactDOMClient.createRoot(container2);
121 await act(() => {
122 root2.render(instance2);
123 });
124
123 - assertLog([
124 - 'mount undefined',
125 - 'update DIV',
126 - 'mount DIV',
127 - 'update undefined',
128 - ]);
125 + assertLog(['mount DIV', 'update undefined']);
126 });
127
128 it('should be able to switch in a list of children', async () => {
packages/react-reconciler/src/__tests__/ReactUpdaters-test.internal.js
+6 -2
@@ -112,11 +112,13 @@ describe('updaters', () => {
112 root.render(<Parent />);
113 });
114 expect(allSchedulerTags).toEqual([[HostRoot]]);
115 + assertLog(['onCommitRoot']);
116
117 await act(() => {
118 root.render(<Parent />);
119 });
120 expect(allSchedulerTags).toEqual([[HostRoot], [HostRoot]]);
121 + assertLog(['onCommitRoot']);
122 });
123
124 it('should report a function component as the scheduler for a hooks update', async () => {
@@ -148,12 +150,13 @@ describe('updaters', () => {
150 expect(scheduleForA).not.toBeNull();
151 expect(scheduleForB).not.toBeNull();
152 expect(allSchedulerTypes).toEqual([[null]]);
153 + assertLog(['onCommitRoot']);
154
155 await act(() => {
156 scheduleForA();
157 });
158 expect(allSchedulerTypes).toEqual([[null], [SchedulingComponentA]]);
156 -
159 + assertLog(['onCommitRoot']);
160 await act(() => {
161 scheduleForB();
162 });
@@ -162,6 +165,7 @@ describe('updaters', () => {
165 [SchedulingComponentA],
166 [SchedulingComponentB],
167 ]);
168 + assertLog(['onCommitRoot']);
169 });
170
171 it('should report a class component as the scheduler for a setState update', async () => {
@@ -180,7 +184,7 @@ describe('updaters', () => {
184 root.render(<Parent />);
185 });
186 expect(allSchedulerTypes).toEqual([[null]]);
183 -
187 + assertLog(['onCommitRoot']);
188 expect(instance).not.toBeNull();
189 await act(() => {
190 instance.setState({});
packages/use-subscription/src/__tests__/useSubscription-test.js
+3 -7
@@ -338,6 +338,8 @@ describe('useSubscription', () => {
338 observableB.next('b-3');
339 });
340
341 + assertLog(['Grandchild: b-0', 'Child: b-3', 'Grandchild: b-3']);
342 +
343 // Update again
344 await act(() => root.render(<Parent observed={observableA} />));
345
@@ -345,13 +347,7 @@ describe('useSubscription', () => {
347 // We expect the last emitted update to be rendered (because of the commit phase value check)
348 // But the intermediate ones should be ignored,
349 // And the final rendered output should be the higher-priority observable.
348 - assertLog([
349 - 'Grandchild: b-0',
350 - 'Child: b-3',
351 - 'Grandchild: b-3',
352 - 'Child: a-0',
353 - 'Grandchild: a-0',
354 - ]);
350 + assertLog(['Child: a-0', 'Grandchild: a-0']);
351 expect(log).toEqual([
352 'Parent.componentDidMount',
353 'Parent.componentDidUpdate',
packages/use-sync-external-store/src/__tests__/useSyncExternalStoreShared-test.js
+5
@@ -660,14 +660,17 @@ describe('Shared useSyncExternalStore behavior (shim and built-in)', () => {
660 // Object.is algorithm to compare values.
661 await act(() => root.render(<App />));
662 expect(container.textContent).toEqual('NaN');
663 + assertLog([NaN]);
664
665 // Update to real number
666 await act(() => store.set(123));
667 expect(container.textContent).toEqual('123');
668 + assertLog([123]);
669
670 // Update back to NaN
671 await act(() => store.set('not a number'));
672 expect(container.textContent).toEqual('NaN');
673 + assertLog([NaN]);
674 });
675
676 describe('extra features implemented in user-space', () => {
@@ -968,6 +971,7 @@ describe('Shared useSyncExternalStore behavior (shim and built-in)', () => {
971 ),
972 );
973
974 + assertLog(['A']);
975 expect(container.textContent).toEqual('A');
976
977 if (__DEV__ && gate(flags => flags.enableUseSyncExternalStoreShim)) {
@@ -1017,6 +1021,7 @@ describe('Shared useSyncExternalStore behavior (shim and built-in)', () => {
1021 ),
1022 );
1023
1024 + assertLog(['A']);
1025 expect(container.textContent).toEqual('A');
1026
1027 if (__DEV__ && gate(flags => flags.enableUseSyncExternalStoreShim)) {