reactjs - 无法通过可访问的名称找到警报

标签 reactjs react-testing-library react-final-form final-form testing-library

我正在编写一个测试来满足以下业务规则:

If we select Canada from the country dropdown, show error messages on blur for the province and postal code fields if they are blank.

我正在测试的 React Final Form 是:

<Form
  onSubmit={onSubmit}
  validate={values => {
    const errors: ValidationErrors = {};

    if (!values.country) {
      errors.country = "Country must be selected";
    }

    if (values.country === "Canada" && !values.province) {
      errors.province = "Province must be provided";
    }

    if (values.country === "Canada" && !values.postalCode) {
      errors.postalCode = "Postal code must be provided";
    }
    return errors;
  }}
  render={({
    ...
  }) => (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="country">Country</label>
        <br />
        <Field<string> id="country" name="country" component="select">
          <option />
          <option value="Canada">Canada</option>
          <option value="US">US</option>
        </Field>
      </div>

      <Condition when="country" is="Canada">
        <div>
          <label htmlFor="province">Province</label>
          <br />
          <Field id="province" name="province" component="input" />
          <Error name="province" />
        </div>
        <div>
          <label htmlFor="postalCode">Postal Code</label>
          <br />
          <Field id="postalCode" name="postalCode" component="input" />
          <Error name="postalCode" />
        </div>
      </Condition>
      ...
    </form>
  )}

我正在编写的测试如下所示:

describe("Contact form", () => {
test("should show errors if Canada is seledted but province and postal code are blank", async () => {
const { getByLabelText, findByRole } = render(<ContactForm />);

fireEvent.change(getByLabelText("Country"), {
  target: { value: "Canada" }
});

fireEvent.change(getByLabelText("Province"), {
  target: { value: "" }
});

fireEvent.change(getByLabelText("Postal Code"), {
  target: { value: "" }
});

fireEvent.blur(getByLabelText("Postal Code"));

const postalAlert = await findByRole("alert", {
  name: "Postal code must be provided"
});
expect(postalAlert).toBeInTheDocument();

const provinceAlert = await findByRole("alert", {
  name: "Province must be provided"
});
expect(provinceAlert).toBeInTheDocument();

我正在尝试触发错误消息 - 用 role="alert" 渲染出来 - 但我的测试失败了:Unable to find role="alert"

现在,如果我删除试图过滤的 name 属性,则会找到 alert:

const postalAlert = await findByRole("alert"); // SUCCESS

我可以使用 findAllByRole 检索警报并遍历它们,但我真的只想使用它们的可访问名称明确查询每个警报并断言它们在文档中。

我在调试屏幕时看到了该元素,我只想弄清楚如何直接使用它的角色和名称来查询它:

<span
      role="alert"
      style="color: rgb(153, 0, 0);"
    >
      Postal code must be provided
</span>

示例表格:https://codesandbox.io/s/react-ts-unit-test-example-6scjc?file=/src/ContactForm.test.tsx

最佳答案

有一些原因你没能通过考试

好像span没有将文本内容应用为可访问的名称,你可以使用aria-label为其设置可访问的名称,more information here

export const Error = (props: Props) => {
  const {
    meta: { touched, error }
  } = useField(props.name, { subscription: { touched: true, error: true } });
  return touched && error ? (
    // add aria-label to set accessiable name for span
    <span aria-label={error} role="alert" style={{ color: "#900" }}>
      {error}
    </span>
  ) : null;
};

您只调用模糊“邮政编码”,但您的测试也包含省份错误,实现是您在模糊省份输入时显示省份错误,因此您需要将其添加到您的测试中

import * as React from "react";
import { render, fireEvent } from "@testing-library/react";
import { ContactForm } from "./ContactForm";

describe("Contact form", () => {
  test("should show errors if Canada is seledted but province and postal code are blank", async () => {
    const { getByLabelText, findByRole } = render(<ContactForm />);

    fireEvent.change(getByLabelText("Country"), {
      target: { value: "Canada" }
    });

    fireEvent.change(getByLabelText("Province"), {
      target: { value: "" }
    });

    fireEvent.change(getByLabelText("Postal Code"), {
      target: { value: "" }
    });

    // you only blur "Postal Code"
    fireEvent.blur(getByLabelText("Postal Code"));

    const postalAlert = await findByRole("alert", {
      name: "Postal code must be provided"
    });
    expect(postalAlert).toBeInTheDocument();
    
    // This will not shown because you have not called blur Province
    // comment this or add the line below to pass the test
    // fireEvent.blur(getByLabelText("Province"));
    const provinceAlert = await findByRole("alert", {
      name: "Province must be provided"
    });
    expect(provinceAlert).toBeInTheDocument();
  });
});

Edit react-ts-unit-test-example

关于reactjs - 无法通过可访问的名称找到警报,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62763874/

相关文章:

javascript - React-final-form 中是否有 FormSection(reduxForm) 的替代品。如果不是如何以 react-final-form 实现它

reactjs - 有谁知道如何与 react-final-form 一起实现 useDropzone 钩子(Hook)而不是 <Dropzone/> (组件)

javascript - 如何在 react-admin 中创建提交按钮,根据表单数据和验证改变外观和行为

javascript - 按 desc、asc 排序函数

reactjs - 使用 useEffect 刷新表

reactjs - 如何在React中实现进度条?

javascript - 使用 useEffect 发出 Jest Act 警告

reactjs - 如何使用 React 测试库粘贴剪贴板数据?

reactjs - "Did not retain recoil value on render, or committed after timeout elapsed. This is fine, but odd. undefined"是什么意思?我该如何解决?

Reactjs 浏览器选项卡关闭事件