I understand that React Testing Library has an example of testing with react router, but I couldn't get it to work (I think because I am using react router V6).
Basically, I need router testing because I have details component that uses useParams() to get part of the url. I can't render the component without it.
This was my attempt to make it work (yes the page also needs apollo, although it doesn't really need redux).
const AllTheProviders = ({children, initialRoutes}) => {
return (
<ApolloProvider client={client}>
<Provider store={store}>
<MemoryRouter>
{children}
</MemoryRouter>
</Provider>
</ApolloProvider>
);
}
const customRender = (ui, options) => render(ui, {wrapper: AllTheProviders, ...options})
beforeEach(() => {
window.history.pushState({}, 'Test page',"/details/url-param-the-component-needs")
customRender(<App/>);
});
No surprise, but this didn't work. I assume window.history.pushState() doesn't work for react router V6. I tried using useNavigate(), but that doesn't work outside of a component.
If anybody has any ideas on how I could make this work. I would greatly appreciate it.
The MemoryRouter
still takes an array of initialEntries
.
declare function MemoryRouter( props: MemoryRouterProps ): React.ReactElement; interface MemoryRouterProps { basename?: string; children?: React.ReactNode; initialEntries?: InitialEntry[]; initialIndex?: number; }
I would remove the MemoryRouter
from the customRender
and just wrap the component under test locally and pass in the specific initial route entries for the test.
const AllTheProviders = ({ children }) => {
return (
<ApolloProvider client={client}>
<Provider store={store}>
{children}
</Provider>
</ApolloProvider>
);
};
const customRender = (ui, options) =>
render(ui, { wrapper: AllTheProviders, ...options });
...
const { ....queries.... } = customRender(
<MemoryRouter
initialEntries={["Test page", "/details/url-param-the-component-needs"]}
>
<ComponentUnderTest />
</MemoryRouter>
);
An additional thought, the useParams
hook may also need a Route
with a path
prop specifying the match params the component needs, so your test could potentially look like the following:
const { ....queries.... } = customRender(
<MemoryRouter
initialEntries={["Test page", "/details/url-param-the-component-needs"]}
>
<Routes>
<Route path="/details/:theParam" element={<ComponentUnderTest />} />
</Routes>
</MemoryRouter>
);