let React; let startTransition; let ReactNoop; let resolveSuspenseyThing; let getSuspenseyThingStatus; let Suspense; let Activity; let SuspenseList; let useMemo; let Scheduler; let act; let assertLog; let waitForPaint; describe('ReactSuspenseyCommitPhase', () => { beforeEach(() => { jest.resetModules(); React = require('react'); ReactNoop = require('react-noop-renderer'); Scheduler = require('scheduler'); Suspense = React.Suspense; if (gate(flags => flags.enableSuspenseList)) { SuspenseList = React.unstable_SuspenseList; } Activity = React.Activity; useMemo = React.useMemo; startTransition = React.startTransition; resolveSuspenseyThing = ReactNoop.resolveSuspenseyThing; getSuspenseyThingStatus = ReactNoop.getSuspenseyThingStatus; const InternalTestUtils = require('internal-test-utils'); act = InternalTestUtils.act; assertLog = InternalTestUtils.assertLog; waitForPaint = InternalTestUtils.waitForPaint; }); function Text({text}) { Scheduler.log(text); return text; } function SuspenseyImage({src}) { return ( Scheduler.log(`Image requested [${src}]`)} /> ); } // @gate enableSuspenseyImages it('suspend commit during initial mount', async () => { const root = ReactNoop.createRoot(); await act(async () => { startTransition(() => { root.render( }> , ); }); }); assertLog(['Image requested [A]', 'Loading...']); expect(getSuspenseyThingStatus('A')).toBe('pending'); expect(root).toMatchRenderedOutput('Loading...'); // This should synchronously commit resolveSuspenseyThing('A'); expect(root).toMatchRenderedOutput(); }); // @gate enableSuspenseyImages it('suspend commit during update', async () => { const root = ReactNoop.createRoot(); await act(() => resolveSuspenseyThing('A')); await act(async () => { startTransition(() => { root.render( }> , ); }); }); expect(root).toMatchRenderedOutput(); // Update to a new image src. The transition should suspend because // the src hasn't loaded yet, and the image is in an already-visible tree. await act(async () => { startTransition(() => { root.render( }> , ); }); }); assertLog(['Image requested [B]']); expect(getSuspenseyThingStatus('B')).toBe('pending'); // Should remain on previous screen expect(root).toMatchRenderedOutput(); // This should synchronously commit resolveSuspenseyThing('B'); expect(root).toMatchRenderedOutput(); }); // @gate enableSuspenseyImages it('suspend commit during initial mount at the root', async () => { const root = ReactNoop.createRoot(); await act(async () => { startTransition(() => { root.render(); }); }); assertLog(['Image requested [A]']); expect(getSuspenseyThingStatus('A')).toBe('pending'); expect(root).toMatchRenderedOutput(null); resolveSuspenseyThing('A'); expect(getSuspenseyThingStatus('A')).toBe('fulfilled'); expect(root).toMatchRenderedOutput(); }); // @gate enableSuspenseyImages it('suspend commit during update at the root', async () => { const root = ReactNoop.createRoot(); await act(() => resolveSuspenseyThing('A')); expect(getSuspenseyThingStatus('A')).toBe('fulfilled'); expect(root).toMatchRenderedOutput(null); await act(async () => { startTransition(() => { root.render(); }); }); expect(root).toMatchRenderedOutput(); await act(async () => { startTransition(() => { root.render(); }); }); assertLog(['Image requested [B]']); expect(getSuspenseyThingStatus('B')).toBe('pending'); expect(root).toMatchRenderedOutput(); resolveSuspenseyThing('B'); expect(getSuspenseyThingStatus('B')).toBe('fulfilled'); expect(root).toMatchRenderedOutput(); }); // @gate enableSuspenseyImages it('suspend commit during urgent initial mount', async () => { const root = ReactNoop.createRoot(); await act(async () => { root.render( }> , ); }); assertLog(['Image requested [A]', 'Loading...']); expect(getSuspenseyThingStatus('A')).toBe('pending'); expect(root).toMatchRenderedOutput('Loading...'); resolveSuspenseyThing('A'); expect(getSuspenseyThingStatus('A')).toBe('fulfilled'); expect(root).toMatchRenderedOutput(); }); // @gate enableSuspenseyImages it('suspend commit during urgent update', async () => { const root = ReactNoop.createRoot(); await act(() => resolveSuspenseyThing('A')); expect(getSuspenseyThingStatus('A')).toBe('fulfilled'); await act(async () => { root.render( }> , ); }); expect(root).toMatchRenderedOutput(); resolveSuspenseyThing('A'); expect(getSuspenseyThingStatus('A')).toBe('fulfilled'); expect(root).toMatchRenderedOutput(); await act(async () => { root.render( }> , ); }); assertLog(['Image requested [B]', 'Loading...']); expect(getSuspenseyThingStatus('B')).toBe('pending'); expect(root).toMatchRenderedOutput( <>