forms - React-Bootstrap 无效表单反馈始终可见如何测试?

标签 forms validation jestjs react-bootstrap react-testing-library

我无法使用 React-bootstrap 测试表单的正确验证。
我想看到当输入模式无效时,一旦表单被验证就会显示无效的反馈文本。
带测试的工作代码和盒子:https://codesandbox.io/s/flamboyant-cerf-7t7jq

import React, { useState } from "react";

import { Form, Button, InputGroup } from "react-bootstrap";

export default function App(): JSX.Element {
  const [validated, setValidated] = useState<boolean>(false);

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setValidated(true);
  };

  return (
    <Form
      className="col-12 col-lg-5 trans-form"
      noValidate
      validated={validated}
      onSubmit={handleSubmit}
    >
      <InputGroup className="my-2">
        <InputGroup.Prepend>
          <InputGroup.Text>Receiver Public Key</InputGroup.Text>
        </InputGroup.Prepend>
        <Form.Control
          role="textbox"
          className="text-truncate rounded-right"
          type="text"
          pattern="[A-Za-z0-9]{5}"
          required
        />
        <Form.Control.Feedback
          className="font-weight-bold"
          type="invalid"
          role="alert"
        >
          Length or format are incorrect!
        </Form.Control.Feedback>
      </InputGroup>

      <Button
        role="button"
        className="mt-2 font-weight-bold"
        variant={"primary"}
        type="submit"
        block
      >
        Sign
      </Button>
    </Form>
  );
}
测试
import React from "react";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import "@testing-library/jest-dom";

import App from "../src/App";

describe("form validation", () => {
  test("invalid receiver public key length", async () => {
    render(<App />);
    userEvent.click(screen.getByRole("button"));
    userEvent.type(screen.getByRole("textbox"), "invalid");
    expect(screen.getByRole("textbox")).toHaveValue("invalid");
    expect(
      await screen.findByText("Length or format are incorrect!")
    ).toBeVisible();
  });

  // this test fails, making it seem like the invalid-feedback is always present
  test("valid receiver public key length", async () => {
    render(<App />);
    userEvent.click(screen.getByRole("button"));
    userEvent.type(screen.getByRole("textbox"), "valid");
    expect(screen.getByRole("textbox")).toHaveValue("valid");
    await waitFor(() => {
      expect(
        screen.queryByText("Length or format are incorrect!")
      ).not.toBeVisible(); // ← FAILS
    });
  });
});
结果
第二次测试失败
Test Result
存储库
https://github.com/lbragile/LibraCoin/tree/develop

最佳答案

因此,由于使用 SCSS 进行样式设置和 React 测试库无法解释底层样式,因此您似乎遇到了这个问题。
解决这个问题的一种方法是在反馈组件上引入一个属性(即添加一个 extra level of indirection )来记录验证的结果:

    import React, { useState } from "react";
    
    import { Form, Button, InputGroup } from "react-bootstrap";
    
    export default function App(): JSX.Element {
      const [validated, setValidated] = useState<boolean>(false);
      // Hook to store the result of the validation
      const [validity, setValidity] = useState<boolean>(false);
    
      const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
    
        const form = e.currentTarget;
        // Persist the result of the validation
        setValidity(form.checkValidity());
        setValidated(true);
      };
    
      return (
        <Form
          className="col-12 col-lg-5 trans-form"
          noValidate
          validated={validated}
          onSubmit={handleSubmit}
        >
          <InputGroup className="my-2">
            <InputGroup.Prepend>
              <InputGroup.Text>Receiver Public Key</InputGroup.Text>
            </InputGroup.Prepend>
            <Form.Control
              role="textbox"
              className="text-truncate rounded-right"
              type="text"
              pattern="[A-Za-z0-9]{5}"
              required
            />
            <Form.Control.Feedback
              className="font-weight-bold"
              type="invalid"
              role="alert"
              data-validity={validity}
            >
              Length or format are incorrect!
            </Form.Control.Feedback>
          </InputGroup>
    
          <Button
            role="button"
            className="mt-2 font-weight-bold"
            variant={"primary"}
            type="submit"
            block
          >
            Sign
          </Button>
        </Form>
      );
    }
一旦你有了这个,你就可以测试一个有效的验证结果,如下所示:
    test("valid receiver public key length", async () => {
        const { container } = render(<App />);
        userEvent.type(screen.getByRole("textbox"), "valid");
        userEvent.click(screen.getByRole("button"));
        let validationFeedback;
        await waitFor(() => {
          validationFeedback = container.querySelector('[data-validity="true"]');
        });
        expect(validationFeedback).toBeTruthy();
      });
我 fork 了你的例子并使用上面的代码让它工作 here .

关于forms - React-Bootstrap 无效表单反馈始终可见如何测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68012748/

相关文章:

forms - 如何为 play2 的表单定义 StopOnFirstFail dsl?

javascript - 通过 "name"而不是 "id"定位多个复选框

javascript - 将文本从表单发送到 Canvas 元素中的文本时,删除文本不起作用

ios - swift : Cannot validate password

node.js - 类型错误 : Cannot read properties of undefined (reading 'listen' ) when testing with Jest, super 测试、Express、Typescript

jestjs - 如何为每个测试模拟不同的 useLocation 值?

python - 从 ChoiceField 传递选择不接受

java - 基于 Spring-MVC 注解的 bean 验证是否支持基于集合的属性? ( Spring -MVC)

javascript - 函数不修改传递的参数值

javascript - React Native Web 测试 Jest 错误 : ReferenceError: __DEV__ is not defined