如何使用 @testing-library/react 测试 React Router V6 Outlet

and*_*ugh 8 reactjs react-router react-router-dom testing-library

我在 React Router v6 中使用一个组件来管理私有路由,它对身份验证令牌进行一些检查,并且将呈现该Outlet组件或重定向到登录页面。

我有 -

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

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

  return <Outlet />;
};
Run Code Online (Sandbox Code Playgroud)

并像这样使用它 -

<Route element={<CheckAuth token={authToken} />}>
   // ... private routes ...
</Route>
Run Code Online (Sandbox Code Playgroud)

window.location.replace我可以用 Jest 来模拟

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

但如何Outlet使用测试库测试组件?

and*_*ugh 8

如果它对任何人有帮助,我最终只是用反应路由器组件包装测试中的组件,并将一个虚拟组件作为子组件传递给 Route 并断言该组件中的一些虚假文本已渲染或未渲染

测试块外 -

const FakeComponent = () => <div>fake text</div>;
Run Code Online (Sandbox Code Playgroud)

对于故障场景,插座不应呈现 -

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

    expect(screen.queryByText('fake text')).not.toBeInTheDocument();
Run Code Online (Sandbox Code Playgroud)

对于成功的场景,断言文本存在 -

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

    expect(screen.queryByText('fake text')).toBeInTheDocument();
Run Code Online (Sandbox Code Playgroud)