@samitouri / QOS-React / commits / 07def0cc5a

Add test for throttling suspended siblings (#28361)

# Overview Adds a test to show the combination of the new throttling behavior and not pre-rendering siblings results in pushing out content that could have rendered much faster. - Without the new throttling, the sibling content would render in 30ms. - Without removing pre-rendering, the sibling content would render in 0ms. - With both, the sibling content takes 600ms. ## Example https://github.com/facebook/react/assets/2440089/abd62dc4-93f9-4b7b-a5aa-b795827c1a3a

Ricky committed Mar 26, 2024 at 00:02 UTC 07def0cc5a377fc36c410b85112fdc51485ecc11
1 file changed +53
packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js
+53
@@ -289,6 +289,59 @@ describe('ReactSuspense', () => {
289 expect(container.textContent).toEqual('AB');
290 });
291
292 + it('pushes out siblings that render faster than throttle', async () => {
293 + function Foo() {
294 + Scheduler.log('Foo');
295 + return (
296 + <Suspense fallback={<Text text="Loading..." />}>
297 + <AsyncText text="A" ms={290} />
298 + <Suspense fallback={<Text text="Loading more..." />}>
299 + <AsyncText text="B" ms={30} />
300 + </Suspense>
301 + </Suspense>
302 + );
303 + }
304 +
305 + setTimeout(async () => {
306 + // TODO: this is dumb, but AsyncText isn't timer based after the act changes.
307 + // Pretend that this is the start of the sibling suspending.
308 + // In a real test, the timer would start when we render B.
309 + setTimeout(async () => {
310 + resolveText('B');
311 + }, 30);
312 +
313 + resolveText('A');
314 + }, 290);
315 +
316 + // Render an empty shell
317 + const root = ReactTestRenderer.create(<Foo />, {
318 + isConcurrent: true,
319 + });
320 +
321 + await waitForAll(['Foo', 'Suspend! [A]', 'Loading...']);
322 + expect(root).toMatchRenderedOutput('Loading...');
323 +
324 + // Now resolve A
325 + jest.advanceTimersByTime(290);
326 + await waitFor(['A']);
327 + expect(root).toMatchRenderedOutput('Loading...');
328 +
329 + // B starts loading. Parent boundary is in throttle.
330 + // Still shows parent loading under throttle
331 + jest.advanceTimersByTime(10);
332 + await waitForAll(['Suspend! [B]', 'Loading more...']);
333 + expect(root).toMatchRenderedOutput('Loading...');
334 +
335 + // !! B could have finished before the throttle, but we show a fallback.
336 + // !! Pushing out the 30ms fetch for B to 300ms.
337 + jest.advanceTimersByTime(300);
338 + await waitFor(['B']);
339 + expect(root).toMatchRenderedOutput('ALoading more...');
340 +
341 + await act(() => {});
342 + expect(root).toMatchRenderedOutput('AB');
343 + });
344 +
345 it('does not throttle fallback committing for too long', async () => {
346 function Foo() {
347 Scheduler.log('Foo');