I had troubles to implemented the accepted answer.
The following solution will not check directly for a path being opened, but for the component that should be rendered at that path.
describe('SideBar', () => {
it('navigation to location 1', () => {
// setup
render(
<MemoryRouter initialIndex={0} initialEntries={['/testbase']}>
<Routes>
<Route path="/testbase" element={<Sidebar/>}/>
<Route path="/location1" element={<div>location 1</div>} />
</Routes>
</MemoryRouter>
);
// run
fireEvent.click(screen.getByText('location 1'));
// check
expect(screen.getByText('location 1')).toBeTruthy();
});
});
Notes:
initialEntries
provides a history that can be accessed.
initialIndex
tells the router which route of initialEntries
should be opened first (in this case /testbase.
OT Notes:
- It's probably a good idea to wrap fireEvent in act and use await. (to prevent test failing once the component becomes more sophisticated)
- It might be a good idea to wrap render in act and use await (to prevent test failing once the component becomes more sophisticated)
Encapsulate MemoryRouter
If you'd like to encapsulate MemoryRouter to make the tests more concise, here's an idea (in Typescript):
import React from 'react'
import { MemoryRouter, Route, Routes } from 'react-router-dom';
export type Route = {
path: string;
element: React.ReactElement;
}
export type TestRouterProps = {
initialRoute?: string;
routes: Route[];
};
/**
*
* How to use:
* <TestRouter initialRoute="/testbase"
* routes={[
* { path: '/testbase', element: <MyComponent/> },
* { path: '/', element: <div>aaa</div> },
* ]}
* />
*
**/
export const TestRouter: React.FC<TestRouterProps> = (props: TestRouterProps) => {
const routerProps = props.initialRoute ? {
initialIndex: 0,
initialEntries: [props.initialRoute],
} : {};
return (
<MemoryRouter {...routerProps}>
<Routes>
{props.routes.map((route) => <Route path={route.path} element={route.element} />)}
</Routes>
</MemoryRouter>);
}
/
is the value by default, and it does not navigate yet. – Phenol