Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to test async components with Jest #47131

Open
1 task done
felipemullen opened this issue Mar 14, 2023 · 7 comments
Open
1 task done

Unable to test async components with Jest #47131

felipemullen opened this issue Mar 14, 2023 · 7 comments
Labels
bug Issue was opened via the bug report template. TypeScript Related to types with Next.js.

Comments

@felipemullen
Copy link

felipemullen commented Mar 14, 2023

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 21.6.0: Wed Aug 10 14:28:23 PDT 2022; root:xnu-8020.141.5~2/RELEASE_ARM64_T6000
Binaries:
  Node: 18.9.0
  npm: 8.19.1
  Yarn: N/A
  pnpm: N/A
Relevant packages:
  next: 13.2.5-canary.3
  eslint-config-next: 13.2.4
  react: 18.2.0
  react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true), Jest (next/jest), TypeScript

Link to the code that reproduces this issue

https://github.com/felipemullen/async-jest-bug

To Reproduce

git clone https://github.com/felipemullen/async-jest-bug
npm i
npm test

Describe the Bug

in NextJs 13+ using the experimental App folder, async server components can be written as described by the documentation and the async RFC

These components cannot be tested with Jest and @testing-library/react. The component does not render, but instead spits an infinite loop to the console with the following error:

Error: Uncaught [Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.]

Expected Behavior

Jest should be able to run without error when rendering an async component when running a simple test such as

it('should render without crashing', async () => {
    // @ts-expect-error Async Component
    const { container } = await waitFor(() => render(<Page />));
    expect(container).toBeTruthy();
});

Which browser are you using? (if relevant)

None

How are you deploying your application? (if relevant)

None

@felipemullen felipemullen added the bug Issue was opened via the bug report template. label Mar 14, 2023
@github-actions github-actions bot added the TypeScript Related to types with Next.js. label Mar 14, 2023
@felipemullen
Copy link
Author

Does anyone have a workaround for this? Currently unable to bring test coverage up to an acceptable level on any page that includes an async component

@PauRUES
Copy link

PauRUES commented Mar 23, 2023

We have tried this and work it:

/**
 * @param {function} Component
 * @param {*} props
 * @returns {Promise<()=>JSX.Element>}
 */
async function resolvedComponent(Component, props) {
  const ComponentResolved = await Component(props)
  return () => ComponentResolved
}

describe('Header test', () => {
  it('should render all the content', async () => {
    const HeaderResolved = await resolvedComponent(Header, {
      language: 'es',
      country: 'ES',
    })
    render(<HeaderResolved />)

    expect(screen.getByText('Login')).toBeInTheDocument()
  })
})

@felipemullen
Copy link
Author

felipemullen commented Mar 28, 2023

@PauRUES thanks, that is helpful. It appears to solve the issue for a single async component as the root of a page. Unfortunately does not appear to solve the problem when mixing with other async child components:

export async function DataComponent() {
    const moreData = api.fetchMoreData();

    return (
        <pre>{JSON.stringify(moreData)}</pre>
    );
}

export default async function Page() {
    const data = await api.fetchData();

    return (
        <Suspense fallback={<CenteredSpinner color="text-primary" />}>
            {/* @ts-expect-error */}
            <DataComponent />
            <pre>{JSON.stringify(data)}</pre>
        </Suspense>
    );
}

is this not supported by next?

@DonikaV
Copy link

DonikaV commented May 25, 2023

I am only one who getting " Uncaught [Error: invariant expected app router to be mounted]" error ?

@gweinert
Copy link

gweinert commented Jun 7, 2023

I am only one who getting " Uncaught [Error: invariant expected app router to be mounted]" error ?

No, I was getting that error too whenever writing tests for components that use the useRouter hook. I figured out that mocking out the useRouter hook makes the error go away. However, I found that even if a child component is using the hook, I still get the error. So I have to mock useRouter in most of my specs.

@timbarclay
Copy link

As @felipemullen said, I think the workaround works where you only have a single async component at the root of the tree, but if that component has a child that is also an async component - which nextjs supports fine - jest gives this error

Error: Uncaught [Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.]

@nickmccurdy
Copy link
Contributor

This issue appears to be more about issues with the test environment not supporting RSC than Next itself. You can check testing-library/react-testing-library#1209 for information and news on testing RSCs with React Testing Library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template. TypeScript Related to types with Next.js.
Projects
None yet
Development

No branches or pull requests

6 participants