【问题标题】:React Testing Library反应测试库
【发布时间】:2021-10-11 17:11:39
【问题描述】:

我正在寻找解决方案。如果未提供输入,我有验证用户输入并显示错误的表单。然后,在手动测试期间,当提供输入时,错误消失了,但是我无法在测试中重现正确的行为。

我已经尝试过 .not.toBeInDocument 和 .not.toBeVisible() + 将状态更新包装到 act() 中

组件代码:

const schema = yup.object().shape({
  nickname: yup.string().required("Nickname is required"),
  password: yup.string().required("Password is required"),
});
export default function LoginForm() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({ resolver: yupResolver(schema) });
  const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data);

  return (
    <Form onSubmit={handleSubmit(onSubmit)}>
      <FormControl>
        <Label htmlFor="nickname">Username:</Label>
        <InputText
          placeholder="Nickname"
          id="nickname"
          {...register("nickname")}
        ></InputText>
        {errors.nickname?.message && (
          <ErrorText data-testid="error">{errors.nickname?.message}</ErrorText>
        )}
      </FormControl>
      <FormControl>
        <Label htmlFor="password">Password:</Label>
        <InputText
          placeholder="Password"
          id="password"
          type="password"
          {...register("password", { required: true })}
        ></InputText>
        {errors.password?.message && (
          <ErrorText data-testid="error">{errors.password?.message}</ErrorText>
        )}
      </FormControl>
      <FormControl>
        <SubmitButton type="submit" value="Login"></SubmitButton>
      </FormControl>
    </Form>
  );
}

测试:

  test("Correct input does not give error anymore", async () => {
    render(
      <ThemeProvider theme={theme}>
        <LoginForm />
      </ThemeProvider>
    );
    const button = screen.getByDisplayValue(/Login/i);
    fireEvent.click(button);
    const usernameInput = screen.getByLabelText(/username:/i);
    const passwordInput = screen.getByLabelText(/password:/i);
    act(() => {
      fireEvent.change(usernameInput, { target: { value: "test123" } });
      fireEvent.change(passwordInput, { target: { value: "123456" } });
    });
    const errors = await screen.findAllByTestId("error");
    expect(usernameInput.value).toBe("test123");
    expect(passwordInput.value).toBe("123456");
    expect(errors[1]).not.toBeInTheDocument();

    expect(errors[0]).not.toBeVisible();
  });

FireEvent.click() 创建错误“需要 lorem”。问题是fireEvent更改并没有改变错误信息,控制台打印:

Received: <span class="sc-iBPTik eglsQB" data-testid="error">Nickname is required</span>

所以我试图重现手动测试但没有成功。

【问题讨论】:

  • 试试expect(screen.queryByText('my error text')).toBeNull()。另外,请查看 userEvent 库而不是 fireEvent。填写输入表单要容易得多。

标签: reactjs unit-testing testing


【解决方案1】:

您正在测试的东西 - 根据单元测试 - 不存在。

下一行说明了这一点。

 {
   errors.password?.message && (
      <ErrorText data-testid="error">
        {errors.password?.message}
      </ErrorText>
   )
  }

上面的那行说如果没有错误就不要渲染它。如果有然后渲染这个。 由于没有 &lt;ErrorText /&gt; 的元素被渲染,那么文档中不会有任何具有 data-testid="error" 属性的元素

如果你在下面定义errors的测试文件中添加这个:

console.log(errors)

然后您应该会在终端中看到一个空数组。

我总是发现单元测试验证错误很棘手。

我更喜欢做的是根据是否提供输入值来禁用与表单相关的按钮。

然后您可以通过执行以下操作来检查按钮是否已启用:

    const button = getByText('Submit');
    expect(button).toBeEnabled();

【讨论】:

  • 我创建此问题的主要动机是我收到此控制台日志`expect(element).not.toBeInTheDocument() 预期文档不包含元素,发现需要密码 而不是 `
猜你喜欢
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 2022-07-13
  • 2021-05-09
  • 1970-01-01
  • 2022-06-21
  • 1970-01-01
相关资源
最近更新 更多