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

问题描述 投票:0回答:2

我在 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 />;
};

并像-

一样使用它
<Route element={<CheckAuth token={authToken} />}>
   // ... private routes ...
</Route>

我可以用 Jest 来模拟

window.location.replace

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

但是如何使用测试库测试

Outlet
组件?

reactjs react-router react-router-dom testing-library
2个回答
10
投票

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

测试块外 -

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

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

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

    expect(screen.queryByText('fake text')).not.toBeInTheDocument();

对于“成功”场景,断言文本存在 - render( <MemoryRouter initialEntries={['/']}> <Routes> <Route element={<CheckAuth token={correctToken}/>}> <Route path="/" element={<FakeComponent />} /> </Route> </Routes> </MemoryRouter> ); expect(screen.queryByText('fake text')).toBeInTheDocument();



0
投票
App.jsx

App.tsx
中的路由逻辑(这是事实)。
因此,您实际上应该这样做:

- 您需要等待组件实际渲染,然后再检查它是否渲染

例如,如果您有

/home

的私有路由,它可以通过身份验证令牌检查并呈现以下组件:

const HomePage = () => {
  //...some logic 
  
  return <div>Home page</div>

}

你的
App.jsx

看起来像这样:

import { Outlet } from 'react-router-dom';
// other imports

export const App = (props) => {
  //... app logic

 return (
   <Routes>
    <Route path='/' element={<Outlet />}>
       <Route element={<CheckAuth token={authToken} />}>
          // ... all private routes including '/home' ...
       </Route>
    </Route>
   </Routes>
 )
}

index.js

import App from 'App'

const root = createRoot(document.getElementById('root'))
  root.render(
    <BrowserRouter>
      <App />
    </BrowserRouter>
  )

然后,您的测试应该如下所示:

describe("App page", async () => { ... delete window.location; window.location = { replace: jest.fn() }; ... test('should test for private route with invalid authToken', () => { // example private route with no valid auth: '/not-valid' render( <MemoryRouter initialEntries={['/not-valid']}> <App /> </MemoryRouter> ) expect(window.location.replace).toHaveBeenCalledWith(loginUrl) }) test('should test for private route with valid authToken', () => { render( <MemoryRouter initialEntries={['/home']}> <App /> </MemoryRouter> ) expect(await screen.findByText('Home page')).toBeInTheDocument() }) })

这里的关键点是确保等待渲染发生,然后再检查组件是否已成功渲染 
/home

您可以通过等待检查来完成此操作,即

expect(await screen.findBy.......

    

© www.soinside.com 2019 - 2024. All rights reserved.