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

Code before:
        return this.props.children;
      }
    }
    const ClientErrorBoundary = clientReference(MyErrorBoundary);

    function App() {
      return (
        <ClientErrorBoundary>
          <ServerComponent />
        </ClientErrorBoundary>
      );
    }

    const transport = ReactNoopFlightServer.render(<App />, {
      onError(x) {
        if (__DEV__) {
          return 'a dev digest';
        }
        if (x instanceof Error) {
          return `digest("${x.message}")`;
        } else if (Array.isArray(x)) {
          return `digest([])`;
        } else if (typeof x === 'object' && x !== null) {
          return `digest({})`;
        }
        return `digest(${String(x)})`;
      },
    });

    await act(() => {
      startTransition(() => {
        ReactNoop.render(
          ReactNoopFlightClient.read(transport, {findSourceMapURL}),
        );
      });
    });

    if (__DEV__) {
      expect({
        errors: errors.map(getErrorForJestMatcher),
        findSourceMapURLCalls: findSourceMapURL.mock.calls,
      }).toEqual({
        errors: [
          {
            message: 'This is an error',
            stack: expect.stringContaining(
              'Error: This is an error\n' +
                '    at eval (eval at testFunction (eval at createFakeFunction (/Users/sebbie/repos/react/packages/react-client/src/ReactFlightClient.js:1948:19), <anonymous>:1:35)\n' +
                '    at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\n' +
                '    at (anonymous) (file:///testing.js:42:3)\n' +
                '    at (anonymous) (file:///testing.js:42:3)\n',

Review comment (bug):
using `expect` in React lifecycles has a couple of problems:
1. if they fail, the error reporting is unreadable since we now have AggregateError and also the frame is pointing all throughout React internals
2. If we'd stop calling this particular lifecycle, tests would pass.

As far as I can tell, this "persist this intermediate value and then assert after render" is widely used so this isn't a new precedence.

Code after:
      error.stack = [
        originalStackLines[0],
        // original
        // '    at ServerComponentError (file://~/react/packages/react-client/src/__tests__/ReactFlight-test.js:1166:19)',
        // nested eval (https://github.com/ChromeDevTools/devtools-frontend/blob/831be28facb4e85de5ee8c1acc4d98dfeda7a73b/test/unittests/front_end/panels/console/ErrorStackParser_test.ts#L198)
        '    at eval (eval at testFunction (inspected-page.html:29:11), <anonymous>:1:10)',
        // parens may be added by Webpack when bundle layers are used. They're also valid in directory names.
        '    at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)',
        // anon function (https://github.com/ChromeDevTools/devtools-frontend/blob/831be28facb4e85de5ee8c1acc4d98dfeda7a73b/test/unittests/front_end/panels/console/ErrorStackParser_test.ts#L115C9-L115C35)
        '    at file:///testing.js:42:3',
        // async anon function (https://github.com/ChromeDevTools/devtools-frontend/blob/831be28facb4e85de5ee8c1acc4d98dfeda7a73b/test/unittests/front_end/panels/console/ErrorStackParser_test.ts#L130C9-L130C41)
        '    at async file:///testing.js:42:3',
        ...originalStackLines.slice(2),
      ].join('\n');
      throw error;
    }

    const findSourceMapURL = jest.fn(() => null);
    const errors = [];
    class MyErrorBoundary extends React.Component {
      state = {error: null};
      static getDerivedStateFromError(error) {
        return {error};
      }
      componentDidCatch(error, componentInfo) {
        errors.push(error);
      }
      render() {
        if (this.state.error) {
          return null;
        }
        return this.props.children;
      }
    }
    const ClientErrorBoundary = clientReference(MyErrorBoundary);

    function App() {
      return (
        <ClientErrorBoundary>
          <ServerComponent />
        </ClientErrorBoundary>
      );
    }

    const transport = ReactNoopFlightServer.render(<App />, {
      onError(x) {
        if (__DEV__) {
          return 'a dev digest';
        }
        if (x instanceof Error) {
          return `digest("${x.message}")`;