反应路由器与@testing库/反应的链接的最简单测试



我试图了解如何最好地测试 react-router 在 @testing-library/react 中按预期运行。

我能想到的最简单的测试是验证单击链接是否更改了URL。我知道理想情况下,我应该测试单击链接会呈现一个新组件,但这会为测试添加很多样板。

所以这是我失败的例子:

import { MemoryRouter } from 'react-router-dom';
import { render } from '@testing-library/react';
import { createMemoryHistory } from 'history';
it('routes to a new route', async () => {
const history = createMemoryHistory();
const { getByText } = render(
<MemoryRouter history={history}>
<Link to="/hello">Click me</Link>
</MemoryRouter>
);
fireEvent.click(getByText('Click me'));
await waitFor(() => expect(history.location.pathname).to.equal('/hello')); // Fails
});

我就是这样做的:嘲笑history.push,然后监视它的调用。

import { MemoryRouter } from 'react-router-dom';
import { render } from '@testing-library/react';
import { createMemoryHistory } from 'history';
it('routes to a new route', async () => {
const history = createMemoryHistory();
// mock push function
history.push = jest.fn();
const { getByText } = render(
<MemoryRouter history={history}>
<Link to="/hello">Click me</Link>
</MemoryRouter>
);
// could be userEvent.click
// https://testing-library.com/docs/ecosystem-user-event/#clickelement-eventinit-options
fireEvent.click(getByText('Click me'));
// spy on push calls, assert on url (parameter)
expect(history.push).toHaveBeenCalledWith('/hello');
});

使用 Typescript 和"react-router-dom": "^6.3.0"时,<MemoryRouter />组件不接受 history prop。

<MemoryRouter history={history} >

不起作用我已经通过下面的示例解决了它。

import { render, screen, fireEvent } from '@testing-library/react';
import {  createMemoryHistory } from 'history';
import { Router, Link } from 'react-router-dom';
it('routes to a new route', () => {
const history = createMemoryHistory();
history.push = jest.fn();
render(
<Router location={history.location} navigator={history}>
<Link to="/hello">Click Me</Link>
</Router>,
);
fireEvent.click(screen.getByText(/Click Me/i));
expect(history.push).toHaveBeenCalledWith(
{
hash: '',
pathname: '/hello',
search: '',
},
undefined,
);
});

您不必使用链接来更改URL,只需使用路由即可。

样本:

it('should change the url', () => {
expect.assertions(1);
act(() => {
render(
<BrowserRouter>
<ProtectedRoute path="/mockPage" component={MyPage} />
<Route render={() => <Redirect to="/mockPage" />} />
</BrowserRouter>
);
});
expect(screen.getByTestId('an-element-in-myPage')).toBeInTheDocument();
});

这就是对我有用的(基于Florian Motteau的回答(:react-router-dom: "^5.3.0"

🟡 唯一的区别是从react-router-dom导入RouteLink而不是MemoryRouter

import { fireEvent, render } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { Link, Router } from 'react-router-dom';

it('routes to a new route', () => {
const history = createMemoryHistory();
history.push = jest.fn();
const { getByText } = render(
<Router history={history}>
<Link to="/path-to-navigate">Click me</Link>
</Router>
);
fireEvent.click(getByText('Click me'));
expect(history.push).toHaveBeenCalledWith('/path-to-navigate');
});

最新更新