Repository: facebook/react
File: packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js (JavaScript)

Code before:
    await waitForAll(['Loading...']);
    expect(root).not.toMatchRenderedOutput('FooBar');

    await resolveFakeImport(Foo);

    await waitForAll(['Foo']);
    expect(root).not.toMatchRenderedOutput('FooBar');

    await act(() => resolveFakeImport(Bar));
    assertLog(['Foo', 'Bar']);
    expect(root).toMatchRenderedOutput('FooBar');
  });

  it('does not support arbitrary promises, only module objects', async () => {
    const LazyText = lazy(async () => Text);

    const root = ReactTestRenderer.create(null, {
      unstable_isConcurrent: true,
    });

    let error;
    try {
      await act(() => {
        root.update(
          <Suspense fallback={<Text text="Loading..." />}>
            <LazyText text="Hi" />
          </Suspense>,
        );
      });
    } catch (e) {
      error = e;
    }

    expect(error.message).toMatch('Element type is invalid');
    assertLog(['Loading...']);
    assertConsoleErrorDev([
      'Expected the result of a dynamic import() call',
      'Expected the result of a dynamic import() call',
    ]);
    expect(root).not.toMatchRenderedOutput('Hi');
  });

  it('throws if promise rejects', async () => {
    const networkError = new Error('Bad network');
    const LazyText = lazy(async () => {
      throw networkError;
    });

    const root = ReactTestRenderer.create(null, {
      unstable_isConcurrent: true,
    });

Review comment (bug):
We have a lot of test like this that execute at the top level and so has no owner. Therefore doesn't get any owner stack which means that it doesn't have a component stack which fails our assertions. This is why I usually try to add a single frame if possible. Mainly due to our tests.

https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberComponentStack.js#L143-L156

This test was relying on the top stack to be able to have a single stack frame at all.

We could maybe also add a "Lazy" frame for a lazy component if there's no other owner.

This is all academic though because it only affects our tests that asserts on component stacks and real apps rarely has no owner.

Code after:
    await waitForAll(['Loading...']);
    expect(root).not.toMatchRenderedOutput('FooBar');

    await resolveFakeImport(Foo);

    await waitForAll(['Foo']);
    expect(root).not.toMatchRenderedOutput('FooBar');

    await act(() => resolveFakeImport(Bar));
    assertLog(['Foo', 'Bar']);
    expect(root).toMatchRenderedOutput('FooBar');
  });

  it('does not support arbitrary promises, only module objects', async () => {
    const LazyText = lazy(async () => Text);

    const root = ReactTestRenderer.create(null, {
      unstable_isConcurrent: true,
    });

    function App() {
      return (
        <Suspense fallback={<Text text="Loading..." />}>
          <LazyText text="Hi" />
        </Suspense>
      );
    }

    let error;
    try {
      await act(() => {
        root.update(<App />);
      });
    } catch (e) {
      error = e;
    }

    expect(error.message).toMatch('Element type is invalid');
    assertLog(['Loading...']);
    assertConsoleErrorDev([
      'Expected the result of a dynamic import() call',
      'Expected the result of a dynamic import() call',
    ]);
    expect(root).not.toMatchRenderedOutput('Hi');
  });

  it('throws if promise rejects', async () => {
    const networkError = new Error('Bad network');
    const LazyText = lazy(async () => {
      throw networkError;
    });