如何使用 react-testing-library 测试带有动作重定向的表单
How to test a form with action redirection using react-testing-library
我使用表单和输入添加了一个搜索栏到我的 React 应用程序,我想检查它是否重定向到正确的页面。
我正在使用 react-testing-library 和 react-router-dom.
这是我的组件(简化):
const SearchBar = () => (
<form action={'/search'}>
<input type="search" name="q" placeholder="search"></input>
</form>
)
所以我编写了这个测试来检查当我在输入中键入内容时,我是否被重定向到 /search 页面(这发生在我的浏览器中)。我跟着 https://testing-library.com/docs/example-react-router/ 想出了这个:
it('redirects to search page', async () => {
const history = createMemoryHistory();
const header = render(
<Router history={history}>
<Switch>
<Route exact path="/">
<SearchBar />
</Route>
<Route path="/search">
<div>this is the search page</div>
</Route>
</Switch>
</Router>
);
const searchBar = header.getByPlaceholderText('search');
fireEvent.change(searchBar, { target: { value: 'myQuery' } });
fireEvent.submit(searchBar);
expect(screen.getAllByText('this is the search page')).toBeInTheDocument();
});
不幸的是,它因以下错误而失败:
TestingLibraryElementError: Unable to find an element with the text: this is the search page. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
<body>
<div>
<form
action="/search"
>
<input
name="q"
placeholder="search"
type="search"
/>
</form>
</div>
</body>
91 | fireEvent.change(searchBar, { target: { value: 'myQuery' } });
92 | fireEvent.submit(searchBar);
> 93 | expect(screen.getAllByText('this is the search page')).toBeInTheDocument();
| ^
94 | });
95 | });
96 |
at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)
at node_modules/@testing-library/dom/dist/query-helpers.js:92:38
at getAllByText (node_modules/@testing-library/dom/dist/query-helpers.js:127:15)
at Object.<anonymous> (src/components/Header/Header.test.tsx:93:19)
据我了解,我相信提交表单不会改变我的路由器的位置。
有没有办法在不更改代码的情况下通过测试?或者我应该忘记依赖 form
的 action
而是实现一个自定义的 onSubmit
属性 来处理重定向——我可以更容易地测试它?
谢谢:)
表单操作不使用 React Router DOM 而是 native method.
<form action={'/search'}>
如果你想为此使用 React Router,请考虑使用 React onSubmit
处理程序。那么在与您的实际实施集成后,您的原始测试或多或少应该会起作用。
const SearchBar = () => {
const history = useHistory();
const handleSubmit = (event) => {
// Prevent default native behavior of submit
event.preventDefault();
// Push the new location to React Router DOM
history.push("/search");
};
return (
<form onSubmit={handleSubmit}>
<input type="search" name="q" placeholder="search"></input>
</form>
);
};
如果您不想更改实现以使用路由器,我认为一个好的解决方案是测试 action
属性 是否正确而不是测试本机行为,尤其是因为很难测试 (example) 中的非路由器导航更改,并且表单提交未完全实现到 JSDOM.
it('has form action for the search page', () => {
const history = createMemoryHistory();
const header = render(
<Router history={history}>
<SearchBar />
</Router>
);
const searchBar = header.getByPlaceholderText('search');
expect(searchBar).toHaveAttribute('action', '/search');
});
我使用表单和输入添加了一个搜索栏到我的 React 应用程序,我想检查它是否重定向到正确的页面。 我正在使用 react-testing-library 和 react-router-dom.
这是我的组件(简化):
const SearchBar = () => (
<form action={'/search'}>
<input type="search" name="q" placeholder="search"></input>
</form>
)
所以我编写了这个测试来检查当我在输入中键入内容时,我是否被重定向到 /search 页面(这发生在我的浏览器中)。我跟着 https://testing-library.com/docs/example-react-router/ 想出了这个:
it('redirects to search page', async () => {
const history = createMemoryHistory();
const header = render(
<Router history={history}>
<Switch>
<Route exact path="/">
<SearchBar />
</Route>
<Route path="/search">
<div>this is the search page</div>
</Route>
</Switch>
</Router>
);
const searchBar = header.getByPlaceholderText('search');
fireEvent.change(searchBar, { target: { value: 'myQuery' } });
fireEvent.submit(searchBar);
expect(screen.getAllByText('this is the search page')).toBeInTheDocument();
});
不幸的是,它因以下错误而失败:
TestingLibraryElementError: Unable to find an element with the text: this is the search page. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
<body>
<div>
<form
action="/search"
>
<input
name="q"
placeholder="search"
type="search"
/>
</form>
</div>
</body>
91 | fireEvent.change(searchBar, { target: { value: 'myQuery' } });
92 | fireEvent.submit(searchBar);
> 93 | expect(screen.getAllByText('this is the search page')).toBeInTheDocument();
| ^
94 | });
95 | });
96 |
at Object.getElementError (node_modules/@testing-library/dom/dist/config.js:37:19)
at node_modules/@testing-library/dom/dist/query-helpers.js:92:38
at getAllByText (node_modules/@testing-library/dom/dist/query-helpers.js:127:15)
at Object.<anonymous> (src/components/Header/Header.test.tsx:93:19)
据我了解,我相信提交表单不会改变我的路由器的位置。
有没有办法在不更改代码的情况下通过测试?或者我应该忘记依赖 form
的 action
而是实现一个自定义的 onSubmit
属性 来处理重定向——我可以更容易地测试它?
谢谢:)
表单操作不使用 React Router DOM 而是 native method.
<form action={'/search'}>
如果你想为此使用 React Router,请考虑使用 React onSubmit
处理程序。那么在与您的实际实施集成后,您的原始测试或多或少应该会起作用。
const SearchBar = () => {
const history = useHistory();
const handleSubmit = (event) => {
// Prevent default native behavior of submit
event.preventDefault();
// Push the new location to React Router DOM
history.push("/search");
};
return (
<form onSubmit={handleSubmit}>
<input type="search" name="q" placeholder="search"></input>
</form>
);
};
如果您不想更改实现以使用路由器,我认为一个好的解决方案是测试 action
属性 是否正确而不是测试本机行为,尤其是因为很难测试 (example) 中的非路由器导航更改,并且表单提交未完全实现到 JSDOM.
it('has form action for the search page', () => {
const history = createMemoryHistory();
const header = render(
<Router history={history}>
<SearchBar />
</Router>
);
const searchBar = header.getByPlaceholderText('search');
expect(searchBar).toHaveAttribute('action', '/search');
});