@samitouri / QOS-React-2 / commits / 5c633a48f9

Add back accidentally deleted test comments (#26294)

The codemod I used in #26288 accidentally caused some comments to be deleted. Because not all affected lines included comments, I didn't notice until after landing. This adds the comments back.

Andrew Clark committed Mar 3, 2023 at 14:34 UTC 5c633a48f9bdc212e27ae026c74148b42cc47efb
9 files changed +124
packages/react-reconciler/src/__tests__/ReactBatching-test.internal.js
+2
@@ -166,9 +166,11 @@ describe('ReactBlockingMode', () => {
166 assertLog(['A1', 'B1']);
167 expect(root).toMatchRenderedOutput('A1B1');
168 } else {
169 + // Only the second update should have flushed synchronously
170 assertLog(['B1']);
171 expect(root).toMatchRenderedOutput('A0B1');
172
173 + // Now flush the first update
174 await waitForAll(['A1']);
175 expect(root).toMatchRenderedOutput('A1B1');
176 }
packages/react-reconciler/src/__tests__/ReactCPUSuspense-test.js
+5
@@ -143,6 +143,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
143 </>,
144 );
145 });
146 + // Inner contents finish in separate commit from outer
147 assertLog(['Inner']);
148 expect(root).toMatchRenderedOutput(
149 <>
@@ -178,6 +179,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
179 await act(async () => {
180 root.render(<App />);
181 });
182 + // Inner contents finish in separate commit from outer
183 assertLog(['Outer', 'Loading...', 'Inner [0]']);
184 expect(root).toMatchRenderedOutput(
185 <>
@@ -190,6 +192,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
192 await act(async () => {
193 setCount(1);
194 });
195 + // Entire update finishes in a single commit
196 assertLog(['Outer', 'Inner [1]']);
197 expect(root).toMatchRenderedOutput(
198 <>
@@ -227,6 +230,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
230 </>,
231 );
232 });
233 + // Inner contents suspended, so we continue showing a fallback.
234 assertLog(['Suspend! [Inner]']);
235 expect(root).toMatchRenderedOutput(
236 <>
@@ -276,6 +280,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
280 await act(async () => {
281 root.render(<App />);
282 });
283 + // Each level commits separately
284 assertLog(['A', 'Loading B...', 'B', 'Loading C...', 'C']);
285 expect(root).toMatchRenderedOutput(
286 <>
packages/react-reconciler/src/__tests__/ReactCache-test.js
+31
@@ -219,6 +219,7 @@ describe('ReactCache', () => {
219 await act(async () => {
220 root.render('Bye');
221 });
222 + // no cleanup: cache is still retained at the root
223 assertLog([]);
224 expect(root).toMatchRenderedOutput('Bye');
225 });
@@ -245,6 +246,7 @@ describe('ReactCache', () => {
246 await act(async () => {
247 root.render('Bye');
248 });
249 + // no cleanup: cache is still retained at the root
250 assertLog([]);
251 expect(root).toMatchRenderedOutput('Bye');
252 });
@@ -273,6 +275,8 @@ describe('ReactCache', () => {
275 root.render(<App showMore={false} />);
276 });
277
278 + // Even though there are two new <Cache /> trees, they should share the same
279 + // data cache. So there should be only a single cache miss for A.
280 assertLog(['Cache miss! [A]', 'Loading...', 'Loading...']);
281 expect(root).toMatchRenderedOutput('Loading...Loading...');
282
@@ -285,6 +289,7 @@ describe('ReactCache', () => {
289 await act(async () => {
290 root.render('Bye');
291 });
292 + // no cleanup: cache is still retained at the root
293 assertLog([]);
294 expect(root).toMatchRenderedOutput('Bye');
295 });
@@ -320,6 +325,8 @@ describe('ReactCache', () => {
325 await act(async () => {
326 root.render(<App showMore={true} />);
327 });
328 + // Even though there are two new <Cache /> trees, they should share the same
329 + // data cache. So there should be only a single cache miss for A.
330 assertLog(['Cache miss! [A]', 'Loading...', 'Loading...']);
331 expect(root).toMatchRenderedOutput('Loading...Loading...');
332
@@ -332,6 +339,9 @@ describe('ReactCache', () => {
339 await act(async () => {
340 root.render('Bye');
341 });
342 + // cleanup occurs for the cache shared by the inner cache boundaries (which
343 + // are not shared w the root because they were added in an update)
344 + // note that no cache is created for the root since the cache is never accessed
345 assertLog(['Cache cleanup: A [v1]']);
346 expect(root).toMatchRenderedOutput('Bye');
347 });
@@ -356,6 +366,8 @@ describe('ReactCache', () => {
366 await act(async () => {
367 root.render(<App />);
368 });
369 + // Even though there is a nested <Cache /> boundary, it should share the same
370 + // data cache as the root. So there should be only a single cache miss for A.
371 assertLog(['Cache miss! [A]', 'Loading...']);
372 expect(root).toMatchRenderedOutput('Loading...');
373
@@ -368,6 +380,7 @@ describe('ReactCache', () => {
380 await act(async () => {
381 root.render('Bye');
382 });
383 + // no cleanup: cache is still retained at the root
384 assertLog([]);
385 expect(root).toMatchRenderedOutput('Bye');
386 },
@@ -412,6 +425,7 @@ describe('ReactCache', () => {
425 await act(async () => {
426 root.render('Bye');
427 });
428 + // no cleanup: cache is still retained at the root
429 assertLog([]);
430 expect(root).toMatchRenderedOutput('Bye');
431 });
@@ -468,6 +482,8 @@ describe('ReactCache', () => {
482 await act(async () => {
483 root.render('Bye!');
484 });
485 + // Cleanup occurs for the *second* cache instance: the first is still
486 + // referenced by the root
487 assertLog(['Cache cleanup: A [v2]']);
488 expect(root).toMatchRenderedOutput('Bye!');
489 });
@@ -549,6 +565,7 @@ describe('ReactCache', () => {
565 await act(async () => {
566 root.render('Bye');
567 });
568 + // no cleanup: cache is still retained at the root
569 assertLog([]);
570 expect(root).toMatchRenderedOutput('Bye');
571 });
@@ -728,12 +745,14 @@ describe('ReactCache', () => {
745 await act(async () => {
746 resolveMostRecentTextCache('A');
747 });
748 + // Note that the version has updated, and the previous cache is cleared
749 assertLog(['A [v2]', 'Cache cleanup: A [v1]']);
750 expect(root).toMatchRenderedOutput('A [v2]');
751
752 await act(async () => {
753 root.render('Bye');
754 });
755 + // the original root cache already cleaned up when the refresh completed
756 assertLog([]);
757 expect(root).toMatchRenderedOutput('Bye');
758 });
@@ -781,12 +800,14 @@ describe('ReactCache', () => {
800 await act(async () => {
801 resolveMostRecentTextCache('A');
802 });
803 + // Note that the version has updated, and the previous cache is cleared
804 assertLog(['A [v2]']);
805 expect(root).toMatchRenderedOutput('A [v2]');
806
807 await act(async () => {
808 root.render('Bye');
809 });
810 + // the original root cache already cleaned up when the refresh completed
811 assertLog([]);
812 expect(root).toMatchRenderedOutput('Bye');
813 });
@@ -841,12 +862,15 @@ describe('ReactCache', () => {
862 }),
863 );
864 });
865 + // The root should re-render without a cache miss.
866 + // The cache is not cleared up yet, since it's still reference by the root
867 assertLog(['A [v2]']);
868 expect(root).toMatchRenderedOutput('A [v2]');
869
870 await act(async () => {
871 root.render('Bye');
872 });
873 + // the refreshed cache boundary is unmounted and cleans up
874 assertLog(['Cache cleanup: A [v2]']);
875 expect(root).toMatchRenderedOutput('Bye');
876 });
@@ -920,6 +944,8 @@ describe('ReactCache', () => {
944 await act(async () => {
945 root.render('Bye!');
946 });
947 + // Unmounting children releases the refreshed cache instance only; the root
948 + // still retains the original cache instance used for the first render
949 assertLog(['Cache cleanup: A [v3]']);
950 expect(root).toMatchRenderedOutput('Bye!');
951 });
@@ -967,6 +993,8 @@ describe('ReactCache', () => {
993 root.render(<App showMore={true} />);
994 });
995
996 + // Even though there are two new <Cache /> trees, they should share the same
997 + // data cache. So there should be only a single cache miss for A.
998 assertLog(['Cache miss! [A]', 'Loading...', 'Loading...']);
999 expect(root).toMatchRenderedOutput('Loading...Loading...');
1000
@@ -1064,6 +1092,9 @@ describe('ReactCache', () => {
1092 await act(async () => {
1093 root.render('Bye!');
1094 });
1095 + // Unmounting children releases both cache boundaries, but the original
1096 + // cache instance (used by second boundary) is still referenced by the root.
1097 + // only the second cache instance is freed.
1098 assertLog(['Cache cleanup: A [v2]']);
1099 expect(root).toMatchRenderedOutput('Bye!');
1100 },
packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js
+5
@@ -339,6 +339,11 @@ describe('ReactLazyContextPropagation', () => {
339 setOtherValue(1);
340 setOtherValue(0);
341 });
342 + // NOTE: If this didn't yield anything, that indicates that we never visited
343 + // the consumer during the render phase, which probably means the eager
344 + // bailout mechanism kicked in. Because we're testing the _lazy_ bailout
345 + // mechanism, update this test to foil the _eager_ bailout, somehow. Perhaps
346 + // by switching to useReducer.
347 assertLog(['Consumer']);
348 expect(root).toMatchRenderedOutput('0');
349 });
packages/react-reconciler/src/__tests__/ReactDeferredValue-test.js
+9
@@ -78,6 +78,7 @@ describe('ReactDeferredValue', () => {
78 root.render(<App value={2} />);
79
80 await waitForPaint(['Original: 2']);
81 + // The deferred value updates in a separate render
82 await waitForPaint(['Deferred: 2']);
83 });
84 expect(root).toMatchRenderedOutput(
@@ -92,6 +93,7 @@ describe('ReactDeferredValue', () => {
93 startTransition(() => {
94 root.render(<App value={3} />);
95 });
96 + // The deferred value updates in the same render as the original
97 await waitForPaint(['Original: 3', 'Deferred: 3']);
98 });
99 expect(root).toMatchRenderedOutput(
@@ -137,6 +139,7 @@ describe('ReactDeferredValue', () => {
139 root.render(<App value={2} />);
140
141 await waitForPaint(['Original: 2']);
142 + // The deferred value updates in a separate render
143 await waitForPaint(['Deferred: 2']);
144 });
145 expect(root).toMatchRenderedOutput(
@@ -151,6 +154,7 @@ describe('ReactDeferredValue', () => {
154 startTransition(() => {
155 root.render(<App value={3} />);
156 });
157 + // The deferred value updates in the same render as the original
158 await waitForPaint(['Original: 3', 'Deferred: 3']);
159 });
160 expect(root).toMatchRenderedOutput(
@@ -201,6 +205,7 @@ describe('ReactDeferredValue', () => {
205 root.render(<App value={2} />);
206
207 await waitForPaint(['Original: 2']);
208 + // The deferred value updates in a separate render
209 await waitForPaint(['Deferred: 2']);
210 });
211 expect(root).toMatchRenderedOutput(
@@ -215,6 +220,7 @@ describe('ReactDeferredValue', () => {
220 startTransition(() => {
221 root.render(<App value={3} />);
222 });
223 + // The deferred value updates in the same render as the original
224 await waitForPaint(['Original: 3', 'Deferred: 3']);
225 });
226 expect(root).toMatchRenderedOutput(
@@ -270,6 +276,9 @@ describe('ReactDeferredValue', () => {
276 startTransition(() => {
277 root.render(<App value={2} />);
278 });
279 + // In the regression, the memoized value was not updated during non-urgent
280 + // updates, so this would flip the deferred value back to the initial
281 + // value (1) instead of reusing the current one (2).
282 await waitForPaint(['Original: 2', 'Deferred: 2']);
283 expect(root).toMatchRenderedOutput(
284 <div>
packages/react-reconciler/src/__tests__/ReactExpiration-test.js
+14
@@ -171,14 +171,17 @@ describe('ReactExpiration', () => {
171 });
172 // Advance the timer.
173 Scheduler.unstable_advanceTime(2000);
174 + // Partially flush the first update, then interrupt it.
175 await waitFor(['A [render]']);
176 interrupt();
177
178 + // Don't advance time by enough to expire the first update.
179 assertLog([]);
180 expect(ReactNoop).toMatchRenderedOutput(null);
181
182 // Schedule another update.
183 ReactNoop.render(<TextClass text="B" />);
184 + // Both updates are batched
185 await waitForAll(['B [render]', 'B [commit]']);
186 expect(ReactNoop).toMatchRenderedOutput(<span prop="B" />);
187
@@ -190,6 +193,8 @@ describe('ReactExpiration', () => {
193 expect(ReactNoop).toMatchRenderedOutput(<span prop="B" />);
194 // Schedule another update.
195 ReactNoop.render(<TextClass text="B" />);
196 + // The updates should flush in the same batch, since as far as the scheduler
197 + // knows, they may have occurred inside the same event.
198 await waitForAll(['B [render]', 'B [commit]']);
199 });
200
@@ -223,14 +228,17 @@ describe('ReactExpiration', () => {
228 });
229 // Advance the timer.
230 Scheduler.unstable_advanceTime(2000);
231 + // Partially flush the first update, then interrupt it.
232 await waitFor(['A [render]']);
233 interrupt();
234
235 + // Don't advance time by enough to expire the first update.
236 assertLog([]);
237 expect(ReactNoop).toMatchRenderedOutput(null);
238
239 // Schedule another update.
240 ReactNoop.render(<TextClass text="B" />);
241 + // Both updates are batched
242 await waitForAll(['B [render]', 'B [commit]']);
243 expect(ReactNoop).toMatchRenderedOutput(<span prop="B" />);
244
@@ -247,6 +255,8 @@ describe('ReactExpiration', () => {
255
256 // Schedule another update.
257 ReactNoop.render(<TextClass text="B" />);
258 + // The updates should flush in the same batch, since as far as the scheduler
259 + // knows, they may have occurred inside the same event.
260 await waitForAll(['B [render]', 'B [commit]']);
261 },
262 );
@@ -471,7 +481,9 @@ describe('ReactExpiration', () => {
481 // In other words, we can flush just the first child without flushing
482 // the rest.
483 Scheduler.unstable_flushNumberOfYields(1);
484 + // Yield right after first child.
485 assertLog(['Sync pri: 1']);
486 + // Now do the rest.
487 await waitForAll(['Normal pri: 1']);
488 });
489 expect(root).toMatchRenderedOutput('Sync pri: 1, Normal pri: 1');
@@ -533,6 +545,7 @@ describe('ReactExpiration', () => {
545 await waitFor(['Sync pri: 0']);
546 updateSyncPri();
547 });
548 + // Same thing should happen as last time
549 assertLog([
550 // Interrupt idle update to render sync update
551 'Sync pri: 1',
@@ -733,6 +746,7 @@ describe('ReactExpiration', () => {
746 Scheduler.unstable_flushNumberOfYields(1);
747 assertLog(['A1', 'B1', 'C1']);
748 });
749 + // The effect flushes after paint.
750 assertLog(['Effect: 1']);
751 });
752 });
packages/react-reconciler/src/__tests__/ReactFlushSync-test.js
+8
@@ -52,6 +52,7 @@ describe('ReactFlushSync', () => {
52 React.startTransition(() => {
53 root.render(<App />);
54 });
55 + // This will yield right before the passive effect fires
56 await waitForPaint(['0, 0']);
57
58 // The passive effect will schedule a sync update and a normal update.
@@ -67,6 +68,7 @@ describe('ReactFlushSync', () => {
68 if (gate(flags => flags.enableUnifiedSyncLane)) {
69 await waitForPaint([]);
70 } else {
71 + // Now flush it.
72 await waitForPaint(['1, 1']);
73 }
74 });
@@ -112,9 +114,11 @@ describe('ReactFlushSync', () => {
114 });
115 });
116 });
117 + // Only the sync update should have flushed
118 assertLog(['1, 0']);
119 expect(root).toMatchRenderedOutput('1, 0');
120 });
121 + // Now the async update has flushed, too.
122 assertLog(['1, 1']);
123 expect(root).toMatchRenderedOutput('1, 1');
124 });
@@ -162,6 +166,7 @@ describe('ReactFlushSync', () => {
166 ]);
167 expect(root).toMatchRenderedOutput('Child');
168 });
169 + // Effect flushes after paint.
170 assertLog(['Effect']);
171 });
172
@@ -217,6 +222,7 @@ describe('ReactFlushSync', () => {
222 ]);
223 expect(root).toMatchRenderedOutput('Child');
224 });
225 + // Effect flushes after paint.
226 assertLog(['Effect']);
227 });
228
@@ -236,8 +242,10 @@ describe('ReactFlushSync', () => {
242
243 // Passive effects are pending. Calling flushSync should not affect them.
244 ReactNoop.flushSync();
245 + // Effects still haven't fired.
246 assertLog([]);
247 });
248 + // Now the effects have fired.
249 assertLog(['Effect']);
250 });
251 });
packages/react-reconciler/src/__tests__/ReactFragment-test.js
+2
@@ -944,6 +944,7 @@ describe('ReactFragment', () => {
944 );
945
946 ReactNoop.render(<Foo condition={false} />);
947 + // The key warning gets deduped because it's in the same component.
948 await waitForAll([]);
949
950 expect(ops).toEqual(['Update Stateful']);
@@ -955,6 +956,7 @@ describe('ReactFragment', () => {
956 );
957
958 ReactNoop.render(<Foo condition={true} />);
959 + // The key warning gets deduped because it's in the same component.
960 await waitForAll([]);
961
962 expect(ops).toEqual(['Update Stateful', 'Update Stateful']);
packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
+48
@@ -299,6 +299,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
299
300 // Resolve the data
301 await resolveText('A');
302 + // Renders successfully
303 await waitForAll(['Foo', 'Bar', 'A', 'B']);
304 expect(ReactNoop).toMatchRenderedOutput(
305 <>
@@ -375,6 +376,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
376 </Suspense>,
377 );
378 });
379 + // B suspends. Continue rendering the remaining siblings.
380 await waitForAll(['A', 'Suspend! [B]', 'C', 'D', 'Loading...']);
381 // Did not commit yet.
382 expect(ReactNoop).toMatchRenderedOutput(null);
@@ -382,6 +384,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
384 // Wait for data to resolve
385 await resolveText('B');
386 await waitForAll(['A', 'B', 'C', 'D']);
387 + // Renders successfully
388 expect(ReactNoop).toMatchRenderedOutput(
389 <>
390 <span prop="A" />
@@ -730,6 +733,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
733 // the update.
734 ReactNoop.expire(10000);
735 await advanceTimers(10000);
736 + // No additional rendering work is required, since we already prepared
737 + // the placeholder.
738 assertLog([]);
739 // Should have committed the placeholder.
740 expect(ReactNoop).toMatchRenderedOutput(
@@ -974,6 +979,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
979 // but not by enough to flush the promise or reach the true expiration time.
980 ReactNoop.expire(2000);
981 await advanceTimers(2000);
982 + // Even flushing won't yield a fallback in a transition.
983 expect(ReactNoop).toMatchRenderedOutput(null);
984
985 await waitForAll([]);
@@ -1014,6 +1020,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1020
1021 await resolveText('Async');
1022
1023 + // Because we're already showing a fallback, interrupt the current render
1024 + // and restart immediately.
1025 await waitForAll(['Async', 'Sibling']);
1026 expect(root).toMatchRenderedOutput(
1027 <>
@@ -1081,6 +1089,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1089
1090 // Resolve the promise
1091 await resolveText('Async');
1092 + // We can now resume rendering
1093 await waitForAll(['Async']);
1094 expect(ReactNoop).toMatchRenderedOutput(<span prop="Async" />);
1095 });
@@ -1106,6 +1115,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1115
1116 // Schedule an update, and suspend for up to 5 seconds.
1117 React.startTransition(() => ReactNoop.render(<App text="A" />));
1118 + // The update should suspend.
1119 await waitForAll(['Suspend! [A]', 'Loading...']);
1120 expect(ReactNoop).toMatchRenderedOutput(<span prop="S" />);
1121
@@ -1117,6 +1127,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1127
1128 // Schedule another low priority update.
1129 React.startTransition(() => ReactNoop.render(<App text="B" />));
1130 + // This update should also suspend.
1131 await waitForAll(['Suspend! [B]', 'Loading...']);
1132 expect(ReactNoop).toMatchRenderedOutput(<span prop="S" />);
1133
@@ -1129,6 +1140,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1140 // Flush the remaining work.
1141 await resolveText('A');
1142 await resolveText('B');
1143 + // Nothing else to render.
1144 await waitForAll([]);
1145 expect(ReactNoop).toMatchRenderedOutput(<span prop="C" />);
1146 });
@@ -1778,6 +1790,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1790 'Commit root',
1791 ]);
1792
1793 + // Flush passive effects.
1794 await waitForAll([
1795 'Effect [A]',
1796 // B's effect should not fire because it suspended
@@ -1823,6 +1836,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1836 'Commit root',
1837 ]);
1838
1839 + // Flush passive effects.
1840 await waitForAll([
1841 // B2's effect should not fire because it suspended
1842 // 'Effect [B2]',
@@ -1863,6 +1877,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1877 });
1878 Scheduler.unstable_advanceTime(100);
1879 await advanceTimers(100);
1880 + // Start rendering
1881 await waitFor(['Foo']);
1882 // For some reason it took a long time to render Foo.
1883 Scheduler.unstable_advanceTime(1250);
@@ -1878,12 +1893,15 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1893 // Flush some of the time
1894 Scheduler.unstable_advanceTime(450);
1895 await advanceTimers(450);
1896 + // Because we've already been waiting for so long we can
1897 + // wait a bit longer. Still nothing...
1898 await waitForAll([]);
1899 expect(ReactNoop).toMatchRenderedOutput(null);
1900
1901 // Eventually we'll show the fallback.
1902 Scheduler.unstable_advanceTime(500);
1903 await advanceTimers(500);
1904 + // No need to rerender.
1905 await waitForAll([]);
1906 // Since this is a transition, we never fallback.
1907 expect(ReactNoop).toMatchRenderedOutput(null);
@@ -1891,6 +1909,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1909 // Flush the promise completely
1910 await resolveText('A');
1911 await waitForAll(['Foo', 'A']);
1912 + // Renders successfully
1913 + // TODO: Why does this render Foo
1914 expect(ReactNoop).toMatchRenderedOutput(<span prop="A" />);
1915 });
1916
@@ -1909,6 +1929,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1929 }
1930
1931 ReactNoop.render(<Foo />);
1932 + // Start rendering
1933 await waitForAll([
1934 'Foo',
1935 // A suspends
@@ -1925,6 +1946,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1946 Scheduler.unstable_advanceTime(5000);
1947 await advanceTimers(5000);
1948
1949 + // Retry with the new content.
1950 await waitForAll([
1951 'A',
1952 // B still suspends
@@ -1943,6 +1965,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1965
1966 // Flush the last promise completely
1967 await resolveText('B');
1968 + // Renders successfully
1969 await waitForAll(['B']);
1970 expect(ReactNoop).toMatchRenderedOutput(
1971 <>
@@ -1967,6 +1990,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1990 }
1991
1992 ReactNoop.render(<Foo />);
1993 + // Start rendering
1994 await waitForAll([
1995 'Foo',
1996 // A suspends
@@ -1980,6 +2004,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2004
2005 await resolveText('A');
2006
2007 + // Retry with the new content.
2008 await waitForAll([
2009 'A',
2010 // B still suspends
@@ -1995,6 +2020,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2020 // Before we commit another Promise resolves.
2021 // We're still showing the first loading state.
2022 expect(ReactNoop).toMatchRenderedOutput(<span prop="Loading..." />);
2023 + // Restart and render the complete content.
2024 await waitForAll(['A', 'B']);
2025 expect(ReactNoop).toMatchRenderedOutput(
2026 <>
@@ -2040,6 +2066,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2066 Scheduler.unstable_advanceTime(500);
2067 jest.advanceTimersByTime(500);
2068
2069 + // We should have already shown the fallback.
2070 + // When we wrote this test, we inferred the start time of high priority
2071 + // updates as way earlier in the past. This test ensures that we don't
2072 + // use this assumption to add a very long JND.
2073 await waitForAll([]);
2074 // Transitions never fallback.
2075 expect(ReactNoop).toMatchRenderedOutput(null);
@@ -2481,6 +2511,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2511
2512 // Schedule an update at idle pri.
2513 ReactNoop.idleUpdates(() => ReactNoop.render(<Foo renderContent={2} />));
2514 + // We won't even work on Idle priority.
2515 await waitForAll([]);
2516
2517 // We're still suspended.
@@ -3040,6 +3071,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3071 await act(async () => {
3072 foo.setState({suspend: true});
3073
3074 + // In the regression that this covers, we would neglect to reset the
3075 + // current debug phase after suspending (in the catch block), so React
3076 + // thinks we're still inside the render phase.
3077 await waitFor(['Suspend!']);
3078
3079 // Then when this setState happens, React would incorrectly fire a warning
@@ -3130,6 +3164,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3164 await waitFor(['Commit']);
3165 expect(ReactNoop).toMatchRenderedOutput(<div hidden={true} />);
3166
3167 + // Partially render through the hidden content.
3168 await waitFor(['Suspend! [A]']);
3169
3170 // Start transition.
@@ -3270,6 +3305,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3305 </>,
3306 );
3307
3308 + // Now flush the remaining work. The Idle update successfully finishes.
3309 await waitForAll(['C']);
3310 expect(root).toMatchRenderedOutput(<span prop="C" />);
3311 });
@@ -3433,6 +3469,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3469 await act(async () => {
3470 setText('D');
3471 });
3472 + // Even though the fragment fiber is not part of the return path, we should
3473 + // be able to finish rendering.
3474 assertLog(['D']);
3475 expect(root).toMatchRenderedOutput(<span prop="D" />);
3476 },
@@ -3513,6 +3551,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3551 setText('E');
3552 });
3553 });
3554 + // Even though the fragment fiber is not part of the return path, we should
3555 + // be able to finish rendering.
3556 assertLog(['Suspend! [D]', 'E']);
3557 expect(root).toMatchRenderedOutput(<span prop="E" />);
3558 },
@@ -3622,6 +3662,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3662 });
3663 });
3664
3665 + // Only the outer part can update. The inner part should still show a
3666 + // fallback because we haven't finished loading B yet. Otherwise, the
3667 + // inner text would be inconsistent with the outer text.
3668 assertLog([
3669 'Outer text: B',
3670 'Outer step: 1',
@@ -3882,11 +3925,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3925 ReactNoop.idleUpdates(() => {
3926 setText('B');
3927 });
3928 + // Suspend the first update. The second update doesn't run because it has
3929 + // Idle priority.
3930 await waitForAll(['Suspend! [B]', 'Loading...']);
3931
3932 // Commit the fallback. Now we'll try working on Idle.
3933 jest.runAllTimers();
3934
3935 + // It also suspends.
3936 await waitForAll(['Suspend! [B]']);
3937 });
3938
@@ -3934,6 +3980,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3980 // Before the retry happens, schedule a new update.
3981 setText('B');
3982
3983 + // The update should be allowed to finish before the retry is attempted.
3984 await waitForPaint(['B']);
3985 expect(root).toMatchRenderedOutput(
3986 <>
@@ -3942,6 +3989,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3989 </>,
3990 );
3991 });
3992 + // Then do the retry.
3993 assertLog(['Async']);
3994 expect(root).toMatchRenderedOutput(
3995 <>