javascript - 为什么使用 React Hook 表单时表单测试失败?
问题描述
我正在使用 react-hook-form 来构建一个表单。表格效果很好,但测试没有通过。
当我不使用react-hook-form
并且 jsut 通过 onSubmit时测试通过<form onSubmit={onSubmit}>
。当我使用 handleSubmit 传递 onSubmit 时<form onSubmit={handleSubmit(onSubmit)}>
,它没有通过。
这是我的表格
App.js
import { useForm } from "react-hook-form";
export default function App({ onSubmit = (data) => console.log(data) }) {
const { handleSubmit, register } = useForm();
return (
// <form onSubmit={onSubmit}> <--- This works
// <form onSubmit={handleSubmit(onSubmit)}> <--- This doesn't work
<form onSubmit={handleSubmit(onSubmit)}>
<input
placeholder="Email"
defaultValue=""
key="email"
{...register("email")}
/>
<input
placeholder="Password"
defaultValue=""
key="password"
{...register("password")}
/>
<input type="submit" value="submit" />
</form>
);
}
这是我为它写的测试
App.test.js
import { render, screen } from "@testing-library/react";
import App from "./App";
import userEvent from "@testing-library/user-event";
test("email and password field are clear for submit", async () => {
const handleSubmit = jest.fn();
render(<App onSubmit={handleSubmit} />);
userEvent.type(screen.getByPlaceholderText(/email/i), "test@example.com");
userEvent.type(screen.getByPlaceholderText(/password/i), "password");
userEvent.click(screen.getByText(/submit/i));
expect(handleSubmit).toHaveBeenCalledTimes(1);
});
工作代码也可在https://codesandbox.io/s/react-hook-form-testing-olo4i获得
解决方案
handleSubmit
在签名下方有,如您所见,它的返回值是一个承诺。它是异步的。
这意味着像这样调用它handleSubmit(onSubmit)(e)
会返回一个承诺。
type UseFormHandleSubmit<TFieldValues extends FieldValues> = <TSubmitFieldValues extends FieldValues = TFieldValues>(onValid: SubmitHandler<TSubmitFieldValues>, onInvalid?: SubmitErrorHandler<TFieldValues>) => (e?: React.BaseSyntheticEvent) => Promise<void>;
您需要使用RTL 的waitFor:
import { render, screen, waitFor } from "@testing-library/react";
import App from "./App";
import userEvent from "@testing-library/user-event";
test("email and password field are clear for submit", async () => {
const handleSubmit = jest.fn();
render(<App onSubmit={handleSubmit} />);
userEvent.type(screen.getByPlaceholderText(/email/i), "test@example.com");
userEvent.type(screen.getByPlaceholderText(/password/i), "password");
userEvent.click(screen.getByText(/submit/i));
await waitFor(() => {
expect(handleSubmit).toHaveBeenCalledTimes(1);
})
});
如果您不等待异步代码完成,它可能会在断言结束后执行。
参考源代码
推荐阅读
- r - 确定数字是否高度复合
- sql - 可以在 PostgreSQL IN 子句中包含集合吗?
- sql-server - 如何根据 SQL 中某些单词的出现来显示句子或行?
- node.js - NodeJS 承诺 Firebase
- docker - 在 Ubuntu 18 上重新启动后找不到 Docker
- javascript - module.exports 中的 getter 和 es6 样式导入(反应导航器)
- python - 具有所需帧率的 imshow() 与 opencv
- java - Spring Boot 在运行时获取主类的名称
- php - Symfony - 无法运行创建的控制台命令
- c# - 从字符串中获取数字和字符串