Repository: facebook/react
Pull request: Remove RTR from ReactSuspense-test

## Summary

Cleaning up internal usage of ReactTestRenderer

## How did you test this change?

`yarn test packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js`

Changed files:
filename: packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js
patch: @@ -1,10 +1,12 @@
 let React;
-let ReactTestRenderer;
+let ReactDOMClient;
+let ReactDOM;
 let ReactFeatureFlags;
 let Scheduler;
 let Suspense;
 let act;
 let textCache;
+let container;
 
 let assertLog;
 let waitForPaint;
@@ -18,9 +20,11 @@ describe('ReactSuspense', () => {
 
     ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
     React = require('react');
-    ReactTestRenderer = require('react-test-renderer');
+    ReactDOM = require('react-dom');
+    ReactDOMClient = require('react-dom/client');
     act = require('internal-test-utils').act;
     Scheduler = require('scheduler');
+    container = document.createElement('div');
 
     Suspense = React.Suspense;
 
@@ -115,18 +119,19 @@ describe('ReactSuspense', () => {
       );
     }
 
+    const root = ReactDOMClient.createRoot(container);
     // Render an empty shell
-    const root = ReactTestRenderer.create(<Foo />, {
-      isConcurrent: true,
+    await act(() => {
+      root.render(<Foo />);
     });
-
-    await waitForAll(['Foo']);
-    expect(root).toMatchRenderedOutput(null);
+    assertLog(['Foo']);
+    const renderedEl = container;
+    expect(renderedEl.innerText).toBeUndefined();
 
     // Navigate the shell to now render the child content.
     // This should suspend.
     React.startTransition(() => {
-      root.update(<Foo renderBar={true} />);
+      root.render(<Foo renderBar={true} />);
     });
 
     await waitForAll([
@@ -136,19 +141,20 @@ describe('ReactSuspense', () => {
       'Suspend! [A]',
       'Loading...',
     ]);
-    expect(root).toMatchRenderedOutput(null);
+    expect(container.textContent).toEqual('');
 
     await waitForAll([]);
-    expect(root).toMatchRenderedOutput(null);
+    expect(container.textContent).toEqual('');
 
-    await resolveText('A');
+    resolveText('A');
     await waitForAll(['Foo', 'Bar', 'A', 'B']);
-    expect(root).toMatchRenderedOutput('AB');
+    expect(container.textContent).toEqual('AB');
   });
 
   it('suspends siblings and later recovers each independently', async () => {
+    const root = ReactDOMClient.createRoot(container);
     // Render two sibling Suspense components
-    const root = ReactTestRenderer.create(
+    root.render(
       <>
         <Suspense fallback={<Text text="Loading A..." />}>
           <AsyncText text="A" ms={5000} />
@@ -157,9 +163,6 @@ describe('ReactSuspense', () => {
           <AsyncText text="B" ms={6000} />
         </Suspense>
       </>,
-      {
-        isConcurrent: true,
-      },
     );
 
     await waitForAll([
@@ -168,19 +171,19 @@ describe('ReactSuspense', () => {
       'Suspend! [B]',
       'Loading B...',
     ]);
-    expect(root).toMatchRenderedOutput('Loading A...Loading B...');
+    expect(container.innerHTML).toEqual('Loading A...Loading B...');
 
     // Resolve first Suspense's promise and switch back to the normal view. The
     // second Suspense should still show the placeholder
     await act(() => resolveText('A'));
     assertLog(['A']);
-    expect(root).toMatchRenderedOutput('ALoading B...');
+    expect(container.textContent).toEqual('ALoading B...');
 
     // Resolve the second Suspense's promise resolves and switche back to the
     // normal view
     await act(() => resolveText('B'));
     assertLog(['B']);
-    expect(root).toMatchRenderedOutput('AB');
+    expect(container.textContent).toEqual('AB');
   });
 
   it('interrupts current render if promise resolves before current render phase', async () => {
@@ -210,22 +213,22 @@ describe('ReactSuspense', () => {
       Scheduler.log('Async');
       return 'Async';
     }
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(
+        <>
+          <Suspense fallback={<Text text="Loading..." />} />
+          <Text text="Initial" />
+        </>,
+      );
+    });
 
-    const root = ReactTestRenderer.create(
-      <>
-        <Suspense fallback={<Text text="Loading..." />} />
-        <Text text="Initial" />
-      </>,
-      {
-        isConcurrent: true,
-      },
-    );
-    await waitForAll(['Initial']);
-    expect(root).toMatchRenderedOutput('Initial');
+    assertLog(['Initial']);
+    expect(container.textContent).toEqual('Initial');
 
     // The update will suspend.
     React.startTransition(() => {
-      root.update(
+      root.render(
         <>
           <Suspense fallback={<Text text="Loading..." />}>
             <Async />
@@ -242,7 +245,7 @@ describe('ReactSuspense', () => {
     // The promise resolves before the current render phase has completed
     resolveThenable();
     assertLog([]);
-    expect(root).toMatchRenderedOutput('Initial');
+    expect(container.textContent).toEqual('Initial');
 
     // Start over from the root, instead of continuing.
     await waitForAll([
@@ -251,7 +254,7 @@ describe('ReactSuspense', () => {
       'After Suspense',
       'Sibling',
     ]);
-    expect(root).toMatchRenderedOutput('AsyncAfter SuspenseSibling');
+    expect(container.textContent).toEqual('AsyncAfter SuspenseSibling');
   });
 
   it('throttles fallback committing globally', async () => {
@@ -267,26 +270,27 @@ describe('ReactSuspense', () => {
       );
     }
 
-    const root = ReactTestRenderer.create(<Foo />, {
-      isConcurrent: true,
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(<Foo />);
     });
 
-    await waitForAll(['Foo', 'Suspend! [A]', 'Loading...']);
-    expect(root).toMatchRenderedOutput('Loading...');
+    assertLog(['Foo', 'Suspend! [A]', 'Loading...']);
+    expect(container.textContent).toEqual('Loading...');
 
     await resolveText('A');
     await waitForAll(['A', 'Suspend! [B]', 'Loading more...']);
 
     // By this point, we have enough info to show "A" and "Loading more..."
     // However, we've just shown the outer fallback. So we'll delay
     // showing the inner fallback hoping that B will resolve soon enough.
-    expect(root).toMatchRenderedOutput('Loading...');
+    expect(container.textContent).toEqual('Loading...');
 
     await act(() => resolveText('B'));
     // By this point, B has resolved.
     // The contents of both should pop in together.
     assertLog(['A', 'B']);
-    expect(root).toMatchRenderedOutput('AB');
+    expect(container.textContent).toEqual('AB');
   });
 
   it('does not throttle fallback committing for too long', async () => {
@@ -302,29 +306,29 @@ describe('ReactSuspense', () => {
       );
     }
 
-    const root = ReactTestRenderer.create(<Foo />, {
-      isConcurrent: true,
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(<Foo />);
     });
-
-    await waitForAll(['Foo', 'Suspend! [A]', 'Loading...']);
-    expect(root).toMatchRenderedOutput('Loading...');
+    assertLog(['Foo', 'Suspend! [A]', 'Loading...']);
+    expect(container.textContent).toEqual('Loading...');
 
     await resolveText('A');
     await waitForAll(['A', 'Suspend! [B]', 'Loading more...']);
 
     // By this point, we have enough info to show "A" and "Loading more..."
     // However, we've just shown the outer fallback. So we'll delay
     // showing the inner fallback hoping that B will resolve soon enough.
-    expect(root).toMatchRenderedOutput('Loading...');
+    expect(container.textContent).toEqual('Loading...');
     // But if we wait a bit longer, eventually we'll give up and show a
     // fallback. The exact value here isn't important. It's a JND ("Just
     // Noticeable Difference").
     jest.advanceTimersByTime(500);
-    expect(root).toMatchRenderedOutput('ALoading more...');
+    expect(container.textContent).toEqual('ALoading more...');
 
     await act(() => resolveText('B'));
     assertLog(['B']);
-    expect(root).toMatchRenderedOutput('AB');
+    expect(container.textContent).toEqual('AB');
   });
 
   // @gate forceConcurrentByDefaultForTesting
@@ -333,10 +337,12 @@ describe('ReactSuspense', () => {
       "delay and we've already skipped over a lower priority update in " +
       'a parent',
     async () => {
+      const root = ReactDOMClient.createRoot(container);
+
       function interrupt() {
         // React has a heuristic to batch all updates that occur within the same
         // event. This is a trick to circumvent that heuristic.
-        ReactTestRenderer.create('whatever');
+        ReactDOM.render('whatever', document.createElement('div'));
       }
 
       function App({shouldSuspend, step}) {
@@ -352,24 +358,20 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(null, {
-        isConcurrent: true,
-      });
-
-      root.update(<App shouldSuspend={false} step={0} />);
+      root.render(<App shouldSuspend={false} step={0} />);
       await waitForAll(['A0', 'B0', 'C0']);
-      expect(root).toMatchRenderedOutput('A0B0C0');
+      expect(container.textContent).toEqual('A0B0C0');
 
       // This update will suspend.
-      root.update(<App shouldSuspend={true} step={1} />);
+      root.render(<App shouldSuspend={true} step={1} />);
 
       // Do a bit of work
       await waitFor(['A1']);
 
       // Schedule another update. This will have lower priority because it's
       // a transition.
       React.startTransition(() => {
-        root.update(<App shouldSuspend={false} step={2} />);
+        root.render(<App shouldSuspend={false} step={2} />);
       });
 
       // Interrupt to trigger a restart.
@@ -384,7 +386,7 @@ describe('ReactSuspense', () => {
       ]);
 
       // Should not have committed loading state
-      expect(root).toMatchRenderedOutput('A0B0C0');
+      expect(container.textContent).toEqual('A0B0C0');
 
       // After suspending, should abort the first update and switch to the
       // second update. So, C1 should not appear in the log.
@@ -393,11 +395,11 @@ describe('ReactSuspense', () => {
       // the render before the end of the current slice of work.
       await waitForAll(['A2', 'B2', 'C2']);
 
-      expect(root).toMatchRenderedOutput('A2B2C2');
+      expect(container.textContent).toEqual('A2B2C2');
     },
   );
 
-  it('mounts a lazy class component in non-concurrent mode', async () => {
+  it('mounts a lazy class component in non-concurrent mode (legacy)', async () => {
     class Class extends React.Component {
       componentDidMount() {
         Scheduler.log('Did mount: ' + this.props.label);
@@ -416,19 +418,20 @@ describe('ReactSuspense', () => {
 
     const LazyClass = React.lazy(() => fakeImport(Class));
 
-    const root = ReactTestRenderer.create(
+    ReactDOM.render(
       <Suspense fallback={<Text text="Loading..." />}>
         <LazyClass label="Hi" />
       </Suspense>,
+      container,
     );
 
     assertLog(['Loading...']);
-    expect(root).toMatchRenderedOutput('Loading...');
+    expect(container.textContent).toEqual('Loading...');
 
     await LazyClass;
 
     await waitForPaint(['Hi', 'Did mount: Hi']);
-    expect(root).toMatchRenderedOutput('Hi');
+    expect(container.textContent).toEqual('Hi');
   });
 
   it('updates memoized child of suspense component when context updates (simple memo)', async () => {
@@ -455,21 +458,22 @@ describe('ReactSuspense', () => {
       );
     }
 
-    const root = ReactTestRenderer.create(<App />, {
-      isConcurrent: true,
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(<App />);
     });
-    await waitForAll(['Suspend! [default]', 'Loading...']);
+    assertLog(['Suspend! [default]', 'Loading...']);
 
     await act(() => resolveText('default'));
     assertLog(['default']);
-    expect(root).toMatchRenderedOutput('default');
+    expect(container.textContent).toEqual('default');
 
     await act(() => setValue('new value'));
     assertLog(['Suspend! [new value]', 'Loading...']);
 
     await act(() => resolveText('new value'));
     assertLog(['new value']);
-    expect(root).toMatchRenderedOutput('new value');
+    expect(container.textContent).toEqual('new value');
   });
 
   it('updates memoized child of suspense component when context updates (manual memo)', async () => {
@@ -501,21 +505,22 @@ describe('ReactSuspense', () => {
       );
     }
 
-    const root = ReactTestRenderer.create(<App />, {
-      isConcurrent: true,
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(<App />);
     });
-    await waitForAll(['Suspend! [default]', 'Loading...']);
+    assertLog(['Suspend! [default]', 'Loading...']);
 
     await act(() => resolveText('default'));
     assertLog(['default']);
-    expect(root).toMatchRenderedOutput('default');
+    expect(container.textContent).toEqual('default');
 
     await act(() => setValue('new value'));
     assertLog(['Suspend! [new value]', 'Loading...']);
 
     await act(() => resolveText('new value'));
     assertLog(['new value']);
-    expect(root).toMatchRenderedOutput('new value');
+    expect(container.textContent).toEqual('new value');
   });
 
   it('updates memoized child of suspense component when context updates (function)', async () => {
@@ -538,28 +543,28 @@ describe('ReactSuspense', () => {
       );
     }
 
-    const root = ReactTestRenderer.create(
-      <App>
-        <Suspense fallback={<Text text="Loading..." />}>
-          <MemoizedChild />
-        </Suspense>
-      </App>,
-      {
-        isConcurrent: true,
-      },
-    );
-    await waitForAll(['Suspend! [default]', 'Loading...']);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(
+        <App>
+          <Suspense fallback={<Text text="Loading..." />}>
+            <MemoizedChild />
+          </Suspense>
+        </App>,
+      );
+    });
+    assertLog(['Suspend! [default]', 'Loading...']);
 
     await act(() => resolveText('default'));
     assertLog(['default']);
-    expect(root).toMatchRenderedOutput('default');
+    expect(container.textContent).toEqual('default');
 
     await act(() => setValue('new value'));
     assertLog(['Suspend! [new value]', 'Loading...']);
 
     await act(() => resolveText('new value'));
     assertLog(['new value']);
-    expect(root).toMatchRenderedOutput('new value');
+    expect(container.textContent).toEqual('new value');
   });
 
   it('updates memoized child of suspense component when context updates (forwardRef)', async () => {
@@ -582,28 +587,28 @@ describe('ReactSuspense', () => {
       );
     }
 
-    const root = ReactTestRenderer.create(
-      <App>
-        <Suspense fallback={<Text text="Loading..." />}>
-          <MemoizedChild />
-        </Suspense>
-      </App>,
-      {
-        isConcurrent: true,
-      },
-    );
-    await waitForAll(['Suspend! [default]', 'Loading...']);
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(
+        <App>
+          <Suspense fallback={<Text text="Loading..." />}>
+            <MemoizedChild />
+          </Suspense>
+        </App>,
+      );
+    });
+    assertLog(['Suspend! [default]', 'Loading...']);
 
     await act(() => resolveText('default'));
     assertLog(['default']);
-    expect(root).toMatchRenderedOutput('default');
+    expect(container.textContent).toEqual('default');
 
     await act(() => setValue('new value'));
     assertLog(['Suspend! [new value]', 'Loading...']);
 
     await act(() => resolveText('new value'));
     assertLog(['new value']);
-    expect(root).toMatchRenderedOutput('new value');
+    expect(container.textContent).toEqual('new value');
   });
 
   it('re-fires layout effects when re-showing Suspense', async () => {
@@ -630,12 +635,13 @@ describe('ReactSuspense', () => {
       );
     }
 
-    const root = ReactTestRenderer.create(<App />, {
-      isConcurrent: true,
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(<App />);
     });
 
-    await waitForAll(['Child 1', 'create layout']);
-    expect(root).toMatchRenderedOutput('Child 1');
+    assertLog(['Child 1', 'create layout']);
+    expect(container.textContent).toEqual('Child 1');
 
     await act(() => {
       _setShow(true);
@@ -649,10 +655,36 @@ describe('ReactSuspense', () => {
 
     await act(() => resolveText('Child 2'));
     assertLog(['Child 1', 'Child 2', 'create layout']);
-    expect(root).toMatchRenderedOutput(['Child 1', 'Child 2'].join(''));
+    expect(container.textContent).toEqual(['Child 1', 'Child 2'].join(''));
   });
 
-  describe('outside concurrent mode', () => {
+  it('does not get stuck with fallback in concurrent mode for a large delay', async () => {
+    function App(props) {
+      return (
+        <Suspense fallback={<Text text="Loading..." />}>
+          <AsyncText text="Child 1" />
+          <AsyncText text="Child 2" />
+        </Suspense>
+      );
+    }
+
+    const root = ReactDOMClient.createRoot(container);
+    await act(() => {
+      root.render(<App />);
+    });
+
+    assertLog(['Suspend! [Child 1]', 'Loading...']);
+    await resolveText('Child 1');
+    await waitForAll(['Child 1', 'Suspend! [Child 2]']);
+
+    jest.advanceTimersByTime(6000);
+
+    await act(() => resolveText('Child 2'));
+    assertLog(['Child 1', 'Child 2']);
+    expect(container.textContent).toEqual(['Child 1', 'Child 2'].join(''));
+  });
+
+  describe('outside concurrent mode (legacy)', () => {
     it('a mounted class component can suspend without losing state', async () => {
       class TextWithLifecycle extends React.Component {
         componentDidMount() {
@@ -698,8 +730,7 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App />);
-
+      ReactDOM.render(<App />, container);
       assertLog([
         'A',
         'Suspend! [B:1]',
@@ -712,24 +743,24 @@ describe('ReactSuspense', () => {
         'Mount [C]',
         'Mount [Loading...]',
       ]);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       await resolveText('B:1');
-      await waitForPaint([
+      assertLog([
         'B:1',
         'Unmount [Loading...]',
         // Should be a mount, not an update
         'Mount [B:1]',
       ]);
-      expect(root).toMatchRenderedOutput('AB:1C');
+      expect(container.textContent).toEqual('AB:1C');
 
       instance.setState({step: 2});
       assertLog(['Suspend! [B:2]', 'Loading...', 'Mount [Loading...]']);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       await resolveText('B:2');
-      await waitForPaint(['B:2', 'Unmount [Loading...]', 'Update [B:2]']);
-      expect(root).toMatchRenderedOutput('AB:2C');
+      assertLog(['B:2', 'Unmount [Loading...]', 'Update [B:2]']);
+      expect(container.textContent).toEqual('AB:2C');
     });
 
     it('bails out on timed-out primary children even if they receive an update', async () => {
@@ -751,25 +782,25 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App text="A" />);
+      ReactDOM.render(<App text="A" />, container);
 
       assertLog(['Stateful: 1', 'Suspend! [A]', 'Loading...']);
 
       await resolveText('A');
-      await waitForPaint(['A']);
-      expect(root).toMatchRenderedOutput('Stateful: 1A');
+      assertLog(['A']);
+      expect(container.textContent).toEqual('Stateful: 1A');
 
-      root.update(<App text="B" />);
+      ReactDOM.render(<App text="B" />, container);
       assertLog(['Stateful: 1', 'Suspend! [B]', 'Loading...']);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       instance.setState({step: 2});
       assertLog(['Stateful: 2', 'Suspend! [B]']);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       await resolveText('B');
-      await waitForPaint(['B']);
-      expect(root).toMatchRenderedOutput('Stateful: 2B');
+      assertLog(['B']);
+      expect(container.textContent).toEqual('Stateful: 2B');
     });
 
     it('when updating a timed-out tree, always retries the suspended component', async () => {
@@ -799,17 +830,17 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App text="A" />);
+      ReactDOM.render(<App text="A" />, container);
 
       assertLog(['Stateful: 1', 'Suspend! [A]', 'Loading...']);
 
       await resolveText('A');
-      await waitForPaint(['A']);
-      expect(root).toMatchRenderedOutput('Stateful: 1A');
+      assertLog(['A']);
+      expect(container.textContent).toEqual('Stateful: 1A');
 
-      root.update(<App text="B" />);
+      ReactDOM.render(<App text="B" />, container);
       assertLog(['Stateful: 1', 'Suspend! [B]', 'Loading...']);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       instance.setState({step: 2});
       assertLog([
@@ -820,14 +851,14 @@ describe('ReactSuspense', () => {
         // pending work, so it was improperly treated as complete.
         'Suspend! [B]',
       ]);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       await resolveText('B');
-      await waitForPaint(['B']);
-      expect(root).toMatchRenderedOutput('Stateful: 2B');
+      assertLog(['B']);
+      expect(container.textContent).toEqual('Stateful: 2B');
     });
 
-    it('suspends in a class that has componentWillUnmount and is then deleted', () => {
+    it('suspends in a class that has componentWillUnmount and is then deleted', async () => {
       class AsyncTextWithUnmount extends React.Component {
         componentWillUnmount() {
           Scheduler.log('will unmount');
@@ -845,12 +876,12 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App text="A" />);
+      ReactDOM.render(<App text="A" />, container);
       assertLog(['Suspend! [A]', 'Loading...']);
-      root.update(<Text text="B" />);
+      ReactDOM.render(<Text text="B" />, container);
       // Should not fire componentWillUnmount
       assertLog(['B']);
-      expect(root).toMatchRenderedOutput('B');
+      expect(container.textContent).toEqual('B');
     });
 
     it('suspends in a component that also contains useEffect', async () => {
@@ -874,10 +905,10 @@ describe('ReactSuspense', () => {
         );
       }
 
-      ReactTestRenderer.create(<App text="A" />);
+      ReactDOM.render(<App text="A" />, container);
       assertLog(['Suspend! [A]', 'Loading...']);
       await resolveText('A');
-      await waitForPaint(['A', 'Did commit: A']);
+      assertLog(['A', 'Did commit: A']);
     });
 
     it('retries when an update is scheduled on a timed out tree', async () => {
@@ -898,35 +929,33 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App />, {
-        isConcurrent: true,
-      });
+      ReactDOM.render(<App />, container);
 
       // Initial render
-      await waitForAll(['Suspend! [Step: 1]', 'Loading...']);
+      assertLog(['Suspend! [Step: 1]', 'Loading...']);
 
       await act(() => resolveText('Step: 1'));
       assertLog(['Step: 1']);
-      expect(root).toMatchRenderedOutput('Step: 1');
+      expect(container.textContent).toEqual('Step: 1');
 
       // Update that suspends
       await act(() => {
         instance.setState({step: 2});
       });
       assertLog(['Suspend! [Step: 2]', 'Loading...']);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       // Update while still suspended
       instance.setState({step: 3});
-      await waitForAll(['Suspend! [Step: 3]']);
-      expect(root).toMatchRenderedOutput('Loading...');
+      assertLog(['Suspend! [Step: 3]']);
+      expect(container.textContent).toEqual('Loading...');
 
       await act(() => {
         resolveText('Step: 2');
         resolveText('Step: 3');
       });
       assertLog(['Step: 3']);
-      expect(root).toMatchRenderedOutput('Step: 3');
+      expect(container.textContent).toEqual('Step: 3');
     });
 
     it('does not remount the fallback while suspended children resolve in legacy mode', async () => {
@@ -950,7 +979,7 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App />);
+      ReactDOM.render(<App />, container);
 
       // Initial render
       assertLog([
@@ -962,48 +991,19 @@ describe('ReactSuspense', () => {
       await waitForAll([]);
 
       await resolveText('Child 1');
-      await waitForPaint([
-        'Child 1',
-        'Suspend! [Child 2]',
-        'Suspend! [Child 3]',
-      ]);
+      assertLog(['Child 1', 'Suspend! [Child 2]', 'Suspend! [Child 3]']);
 
       await resolveText('Child 2');
-      await waitForPaint(['Child 2', 'Suspend! [Child 3]']);
+      assertLog(['Child 2', 'Suspend! [Child 3]']);
 
       await resolveText('Child 3');
-      await waitForPaint(['Child 3']);
-      expect(root).toMatchRenderedOutput(
+      assertLog(['Child 3']);
+      expect(container.textContent).toEqual(
         ['Child 1', 'Child 2', 'Child 3'].join(''),
       );
       expect(mounts).toBe(1);
     });
 
-    it('does not get stuck with fallback in concurrent mode for a large delay', async () => {
-      function App(props) {
-        return (
-          <Suspense fallback={<Text text="Loading..." />}>
-            <AsyncText text="Child 1" />
-            <AsyncText text="Child 2" />
-          </Suspense>
-        );
-      }
-
-      const root = ReactTestRenderer.create(<App />, {
-        isConcurrent: true,
-      });
-
-      await waitForAll(['Suspend! [Child 1]', 'Loading...']);
-      await resolveText('Child 1');
-      await waitForAll(['Child 1', 'Suspend! [Child 2]']);
-
-      jest.advanceTimersByTime(6000);
-
-      await act(() => resolveText('Child 2'));
-      assertLog(['Child 1', 'Child 2']);
-      expect(root).toMatchRenderedOutput(['Child 1', 'Child 2'].join(''));
-    });
-
     it('reuses effects, including deletions, from the suspended tree', async () => {
       const {useState} = React;
 
@@ -1020,35 +1020,35 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App />);
+      ReactDOM.render(<App />, container);
       assertLog(['Suspend! [Tab: 0]', ' + sibling', 'Loading...']);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       await resolveText('Tab: 0');
-      await waitForPaint(['Tab: 0']);
-      expect(root).toMatchRenderedOutput('Tab: 0 + sibling');
+      assertLog(['Tab: 0']);
+      expect(container.textContent).toEqual('Tab: 0 + sibling');
 
       await act(() => setTab(1));
       assertLog(['Suspend! [Tab: 1]', ' + sibling', 'Loading...']);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       await resolveText('Tab: 1');
-      await waitForPaint(['Tab: 1']);
-      expect(root).toMatchRenderedOutput('Tab: 1 + sibling');
+      assertLog(['Tab: 1']);
+      expect(container.textContent).toEqual('Tab: 1 + sibling');
 
       await act(() => setTab(2));
       assertLog(['Suspend! [Tab: 2]', ' + sibling', 'Loading...']);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       await resolveText('Tab: 2');
-      await waitForPaint(['Tab: 2']);
-      expect(root).toMatchRenderedOutput('Tab: 2 + sibling');
+      assertLog(['Tab: 2']);
+      expect(container.textContent).toEqual('Tab: 2 + sibling');
     });
 
     it('does not warn if a mounted component is pinged', async () => {
       const {useState} = React;
 
-      const root = ReactTestRenderer.create(null);
+      ReactDOM.render(null, container);
 
       let setStep;
       function UpdatingText({text, ms}) {
@@ -1058,25 +1058,22 @@ describe('ReactSuspense', () => {
         return <Text text={readText(fullText)} />;
       }
 
-      root.update(
+      ReactDOM.render(
         <Suspense fallback={<Text text="Loading..." />}>
           <UpdatingText text="A" ms={1000} />
         </Suspense>,
+        container,
       );
 
       assertLog(['Suspend! [A:0]', 'Loading...']);
 
       await resolveText('A:0');
-      await waitForPaint(['A:0']);
-      expect(root).toMatchRenderedOutput('A:0');
+      assertLog(['A:0']);
+      expect(container.textContent).toEqual('A:0');
 
       await act(() => setStep(1));
       assertLog(['Suspend! [A:1]', 'Loading...']);
-      expect(root).toMatchRenderedOutput('Loading...');
-
-      await act(() => {
-        root.update(null);
-      });
+      expect(container.textContent).toEqual('Loading...');
     });
 
     it('memoizes promise listeners per thread ID to prevent redundant renders', async () => {
@@ -1090,22 +1087,22 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(null);
+      ReactDOM.render(null, container);
 
-      root.update(<App />);
+      ReactDOM.render(<App />, container);
 
       assertLog(['Suspend! [A]', 'Suspend! [B]', 'Suspend! [C]', 'Loading...']);
 
       await resolveText('A');
-      await waitForPaint([
+      assertLog([
         'A',
         // The promises for B and C have now been thrown twice
         'Suspend! [B]',
         'Suspend! [C]',
       ]);
 
       await resolveText('B');
-      await waitForPaint([
+      assertLog([
         // Even though the promise for B was thrown twice, we should only
         // re-render once.
         'B',
@@ -1114,7 +1111,7 @@ describe('ReactSuspense', () => {
       ]);
 
       await resolveText('C');
-      await waitForPaint([
+      assertLog([
         // Even though the promise for C was thrown three times, we should only
         // re-render once.
         'C',
@@ -1153,11 +1150,9 @@ describe('ReactSuspense', () => {
         }
       }
 
-      const root = ReactTestRenderer.create(null);
+      ReactDOM.render(null, container);
 
-      await act(() => {
-        root.update(<App name="world" />);
-      });
+      ReactDOM.render(<App name="world" />, container);
     });
 
     it('updates memoized child of suspense component when context updates (simple memo)', async () => {
@@ -1184,19 +1179,19 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App />);
+      ReactDOM.render(<App />, container);
       assertLog(['Suspend! [default]', 'Loading...']);
 
       await resolveText('default');
-      await waitForPaint(['default']);
-      expect(root).toMatchRenderedOutput('default');
+      assertLog(['default']);
+      expect(container.textContent).toEqual('default');
 
       await act(() => setValue('new value'));
       assertLog(['Suspend! [new value]', 'Loading...']);
 
       await resolveText('new value');
-      await waitForPaint(['new value']);
-      expect(root).toMatchRenderedOutput('new value');
+      assertLog(['new value']);
+      expect(container.textContent).toEqual('new value');
     });
 
     it('updates memoized child of suspense component when context updates (manual memo)', async () => {
@@ -1228,19 +1223,19 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App />);
+      ReactDOM.render(<App />, container);
       assertLog(['Suspend! [default]', 'Loading...']);
 
       await resolveText('default');
-      await waitForPaint(['default']);
-      expect(root).toMatchRenderedOutput('default');
+      assertLog(['default']);
+      expect(container.textContent).toEqual('default');
 
       await act(() => setValue('new value'));
       assertLog(['Suspend! [new value]', 'Loading...']);
 
       await resolveText('new value');
-      await waitForPaint(['new value']);
-      expect(root).toMatchRenderedOutput('new value');
+      assertLog(['new value']);
+      expect(container.textContent).toEqual('new value');
     });
 
     it('updates memoized child of suspense component when context updates (function)', async () => {
@@ -1265,25 +1260,26 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(
+      ReactDOM.render(
         <App>
           <Suspense fallback={<Text text="Loading..." />}>
             <MemoizedChild />
           </Suspense>
         </App>,
+        container,
       );
       assertLog(['Suspend! [default]', 'Loading...']);
 
       await resolveText('default');
-      await waitForPaint(['default']);
-      expect(root).toMatchRenderedOutput('default');
+      assertLog(['default']);
+      expect(container.textContent).toEqual('default');
 
       await act(() => setValue('new value'));
       assertLog(['Suspend! [new value]', 'Loading...']);
 
       await resolveText('new value');
-      await waitForPaint(['new value']);
-      expect(root).toMatchRenderedOutput('new value');
+      assertLog(['new value']);
+      expect(container.textContent).toEqual('new value');
     });
 
     it('updates memoized child of suspense component when context updates (forwardRef)', async () => {
@@ -1310,19 +1306,19 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App />);
+      ReactDOM.render(<App />, container);
       assertLog(['Suspend! [default]', 'Loading...']);
 
       await resolveText('default');
-      await waitForPaint(['default']);
-      expect(root).toMatchRenderedOutput('default');
+      assertLog(['default']);
+      expect(container.textContent).toEqual('default');
 
       await act(() => setValue('new value'));
       assertLog(['Suspend! [new value]', 'Loading...']);
 
       await resolveText('new value');
-      await waitForPaint(['new value']);
-      expect(root).toMatchRenderedOutput('new value');
+      assertLog(['new value']);
+      expect(container.textContent).toEqual('new value');
     });
 
     it('updates context consumer within child of suspended suspense component when context updates', async () => {
@@ -1364,17 +1360,17 @@ describe('ReactSuspense', () => {
         );
       }
 
-      const root = ReactTestRenderer.create(<App />);
+      ReactDOM.render(<App />, container);
       assertLog(['Received context value [default]', 'default']);
-      expect(root).toMatchRenderedOutput('default');
+      expect(container.textContent).toEqual('default');
 
       await act(() => setValue('new value'));
       assertLog(['Received context value [new value]', 'Loading...']);
-      expect(root).toMatchRenderedOutput('Loading...');
+      expect(container.textContent).toEqual('Loading...');
 
       await act(() => setValue('default'));
       assertLog(['Received context value [default]', 'default']);
-      expect(root).toMatchRenderedOutput('default');
+      expect(container.textContent).toEqual('default');
     });
   });
 });