Repository: facebook/react
File: packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js (JavaScript)

Code before:

    function App() {
      return (
        <Suspense fallback="Loading...">
          <ErrorBoundary>
            <Async />
          </ErrorBoundary>
        </Suspense>
      );
    }

    const reportedServerErrors = [];
    await act(() => {
      const {pipe} = renderToPipeableStream(<App />, {
        onError(error) {
          reportedServerErrors.push(error);
        },
      });
      pipe(writable);
    });

    // TODO: The `act` implementation in this file doesn't unwrap microtasks
    // automatically. We can't use the same `act` we use for Fiber tests
    // because that relies on the mock Scheduler. Doesn't affect any public
    // API but we might want to fix this for our own internal tests.
    //
    // For now, wait for each promise in sequence.
    await act(async () => {
      await promiseA;
    });
    await act(async () => {
      await expect(promiseB).rejects.toThrow('Oops!');
    });
    await act(async () => {
      await promiseC;
    });

    expect(getVisibleChildren(container)).toEqual('Loading...');
    expect(reportedServerErrors.length).toBe(1);
    expect(reportedServerErrors[0].message).toBe('Oops!');

    const reportedCaughtErrors = [];
    const reportedClientErrors = [];
    ReactDOMClient.hydrateRoot(container, <App />, {
      onCaughtError(error) {
        reportedCaughtErrors.push(error);
      },
      onRecoverableError(error) {
        reportedClientErrors.push(error);
      },
    });

Review comment (bug):
I'm kind of confused why the lack of this override didn't fail the test before because it should've logged to console.error which fails the test.

Code after:
    });

    // TODO: The `act` implementation in this file doesn't unwrap microtasks
    // automatically. We can't use the same `act` we use for Fiber tests
    // because that relies on the mock Scheduler. Doesn't affect any public
    // API but we might want to fix this for our own internal tests.
    //
    // For now, wait for each promise in sequence.
    await act(async () => {
      await promiseA;
    });
    await act(async () => {
      await expect(promiseB).rejects.toThrow('Oops!');
    });
    await act(async () => {
      await promiseC;
    });

    expect(getVisibleChildren(container)).toEqual('Loading...');
    expect(reportedServerErrors.length).toBe(1);
    expect(reportedServerErrors[0].message).toBe('Oops!');

    const reportedCaughtErrors = [];
    const reportedClientErrors = [];
    ReactDOMClient.hydrateRoot(container, <App />, {
      onCaughtError(error) {
        reportedCaughtErrors.push(error);
      },
      onRecoverableError(error) {
        reportedClientErrors.push(error);
      },
    });
    await waitForAll([]);
    expect(getVisibleChildren(container)).toEqual('Oops!');
    // Because this is rethrown on the client, it is not a recoverable error.
    expect(reportedClientErrors.length).toBe(0);
    // It is caught by the error boundary.
    expect(reportedCaughtErrors.length).toBe(1);
    expect(reportedCaughtErrors[0].message).toBe('Oops!');
  });

  it("use a promise that's already been instrumented and resolved", async () => {
    const thenable = {
      status: 'fulfilled',
      value: 'Hi',
      then() {},
    };

    // This will never suspend because the thenable already resolved
    function App() {
      return use(thenable);