Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test React Router V6 Outlet using @testing-library/react

I have a component that I am using in React Router v6 for managing private routes, that does some checks on an auth token, and will either render the Outlet component or will redirect to a login page.

I have -

import { Outlet } from 'react-router-dom';

export const CheckAuth = (props) => {
  const valid = ...;
  if (!valid) {
    window.location.replace(loginUrl);
    return null;
  }

  return <Outlet />;
};

and using it like -

<Route element={<CheckAuth token={authToken} />}>
   // ... private routes ...
</Route>

I can mock out window.location.replace with Jest

delete window.location;
window.location = { replace: jest.fn() };
...
render(<CheckAuth token={token} />)
expect(window.location.replace).toHaveBeenCalledWith(loginUrl);

but how can I test the Outlet component using Testing Library?

like image 776
andy mccullough Avatar asked Apr 27 '26 04:04

andy mccullough


1 Answers

If it helps anyone, I ended up just wrapping the components in the test with a react router components, and passed a dummy component as a child to Route and asserted that some fake text in that component was or was not rendered

Outside the test block -

const FakeComponent = () => <div>fake text</div>;

and for a failure scenario, where the outlet should not render -

    render(
      <MemoryRouter initialEntries={['/']}>
        <Routes>
          <Route element={<CheckAuth />}>
            <Route path="/" element={<FakeComponent />} />
          </Route>
        </Routes>
      </MemoryRouter>
    );

    await waitFor(() => expect(screen.queryByText('fake text')).not.toBeInTheDocument());
    await waitFor(() => expect(window.location.replace).toHaveBeenCalledWith(loginUrl));

and for a success scenario, assert that the text is present -

render(
      <MemoryRouter initialEntries={['/']}>
        <Routes>
          <Route element={<CheckAuth token={correctToken}/>}>
            <Route path="/" element={<FakeComponent />} />
          </Route>
        </Routes>
      </MemoryRouter>
    );

    expect(screen.getByText('fake text')).toBeInTheDocument();
like image 174
andy mccullough Avatar answered Apr 28 '26 16:04

andy mccullough