I migrated from React Router v5 to v6 following this tutorial. I want to test it with react-testing-library, but my old unit tests (using the pattern in this doc) stopped working.
My app with React Router v6 is like this
const router = createBrowserRouter([
{
path: "/",
element: (
<>
<SiteHeader />
<Outlet />
</>
),
errorElement: <NotFound />,
children: [
{ path: "/", element: <Home /> },
{ path: "/posts", element: <Posts /> },
{ path: "/post/:postId", element: <PostPage /> },
],
},
]);
function App() {
return (
<div className="app">
<RouterProvider router={router} />
</div>
);
}
As you can see, it's using RouterProvider instead of Switch/Route (so I'm confused that this SO question says it's using React Router v6 but it looks so different.).
The code in official doc of testing-library is not using RouterProvider either.
I want to test some routing logic like this pseudo code:
renderWithRouter(<App />, "/posts"); // loads /posts page initially
await user.click(screen.getByText("some post title")); // trigger click
expect(getUrl(location)).toEqual("/post/123"); // checks the URL changed correctly
How can I create a renderWithRouter function like this with RouterProvider? Note that this renderWithRouter worked for me when I used React Router v5, but after migrating to v6, it stopped working.
My current dependency versions:
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "react-router-dom": "^6.4.3",
- "@testing-library/jest-dom": "^5.16.5",
- "@testing-library/react": "^13.4.0",
- "@testing-library/user-event": "^14.4.3",
I tried this
test("click post goes to /post/:postId", async () => {
render(
<MemoryRouter initialEntries={["/posts"]}>
<App />
</MemoryRouter>,
);
// ...
});
but I got error
You cannot render a <Router> inside another <Router>. You should never have more than one in your app.
31 | test("click post goes to /post/:postId", async () => {
> 32 | render(
| ^
34 | <MemoryRouter initialEntries={["/posts"]}>
36 | <App />
Postscomponent in aMemoryRouterand testingPostsbehavior, as an example?MemoryRouter(see the end)Postcomponent, then try rendering onlyPost. Again, it depends on what you are trying to unit test. Sometimes some components need to be rendered within a routing context, so a router is necessary to provide the context.react-testing-libraryisn't the correct tool for the job of integration testing. For this look for something like puppeteer, selenium, cypress, etc.