如何在 React Router DOM v6 上使用 MemoryRouter 测试位置?

Dos*_*kya 6 javascript testing reactjs react-router react-testing-library

将 React Router DOM (v6) 与 React 测试库结合使用,我想知道是否有一种方法可以处理“模拟”历史记录createMemoryHistory或类似的替代方案。

根据测试库的示例,我可以模拟组件的历史记录Router,但在 v6 中该组件不再接受该historyprop。

所以,我的疑问是:如何使用 React Router DOM v6 使用 RTL(React 测试库)测试历史记录和位置?我应该继续使用MemoryRouter吗?

小智 14

使用 React Router DOM v6.4.0 的推荐测试方法依赖于createMemoryRouter哪个将返回RemixRouter. 可以使用Router 的对象来history代替使用,因为该 Router使用其自己的内存历史记录。该对象包含我们可以检查导航是否正确的位置。createMemoryHistorystatecreateMemoryRouterstate

使用RouterProviderReact Router DOM,我们可以将创建的路由器传递createMemoryRouter给提供者并传递给我们的测试。

import { render, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import {
  createMemoryRouter,
  RouterProvider,
  useNavigate,
} from 'react-router-dom'
import { screen } from '@testing-library/react'

// The element we want to render. Uses the hook useNavigate to send us somewhere.
const ElementToRender: React.FC = () => {
  const navigate = useNavigate()

  return <button onClick={() => navigate('/')}>Navigate to Home</button>
}

const setupMyTest = () => {
  const router = createMemoryRouter(
    [
      {
        path: '/',
        element: <>Navigated from Start</>,
      },
      {
        path: '/starting/path',
        // Render the component causing the navigate to '/'
        element: <ElementToRender />,
      },
    ],
    {
      // Set for where you want to start in the routes. Remember, KISS (Keep it simple, stupid) the routes.
      initialEntries: ['/starting/path'],
      // We don't need to explicitly set this, but it's nice to have.
      initialIndex: 0,
    }
  )

  render(<RouterProvider router={router} />)

  // Objectify the router so we can explicitly pull when calling setupMyTest
  return { router }
}

it('tests react router dom v6.4.0 navigates properly', async () => {
  const { router } = setupMyTest()

  // Given we do start where we want to start
  expect(router.state.location.pathname).toEqual('/starting/path')

  // Navigate away from /starting/path
  userEvent.click(screen.getByRole('button', { name: 'Navigate to Home' }))

  // Don't forget to await the update since not all actions are immediate
  await waitFor(() => {
    expect(router.state.location.pathname).toEqual('/')
  })
})

Run Code Online (Sandbox Code Playgroud)


Jur*_*r P -4

使用react router dom v6,路由器使用 navigator prop 来接受历史记录。

const history = createMemoryHistory(); 
...
<MockedProvider mocks={[]}>
  <Router navigator={history} location={"/"}>
    <Home />
  </Router>
</MockedProvider> 
... 
await waitFor(() => {
  expect(history.location.pathname).toBe("/");
});
Run Code Online (Sandbox Code Playgroud)

  • RRD V6 的 MemoryRouter 不接受导航器或位置属性 (2认同)