Open felipemullen opened 1 year ago
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
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()
})
})
@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?
I am only one who getting " Uncaught [Error: invariant expected app router to be mounted]" error ?
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.
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.]
This issue appears to be more about issues with the test environment not supporting RSC than Next itself. You can check https://github.com/testing-library/react-testing-library/issues/1209 for information and news on testing RSCs with React Testing Library.
Hi, jest's render() function doesn't accept a promise as a parameter so you need to resolve the component by calling it as a function before passing it to the function. For example: describe('A test suite for an async component',()=>{ test('Component well render ok', async()=>{ const component = await YourComponent({customProp:true}); const {debug} = render(component); debug();
} })
So is the work around just to mock out the problematic children components? Or is there something more elegant?
Verify canary release
Provide environment information
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
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:Expected Behavior
Jest should be able to run without error when rendering an
async
component when running a simple test such asWhich browser are you using? (if relevant)
None
How are you deploying your application? (if relevant)
None