【问题标题】:How to test a required input field with React Testing Library and Jest?如何使用 React 测试库和 Jest 测试所需的输入字段?
【发布时间】:2021-06-20 12:45:36
【问题描述】:

我尝试使用 React 测试库和 Jest 通过测试弹出框的存在来测试必需的输入字段,但我失败了。我尝试了几种变体,但没有一个有效。 UI 的步骤如下:

  1. 单击空白字段 Empty select field
  2. 点击字段旁边的(模糊)
  3. 鼠标悬停在田野上
  4. 获取所需消息Required message

实现这一点的测试代码是:

  const input = screen.getByRole('textbox', {name: /name \*/i})
  expect(input).toBeTruthy();
  fireEvent.click(input);
  fireEvent.blur(input);
  await waitFor(() => expect(input).toHaveValue(config.EMPTY_STRING));

  act(() => {
    fireEvent.mouseOver(input);
  });

  await waitFor(() => {
    expect(screen.getByText('Name is required')).toBeTruthy();
  });

不幸的是,它不起作用,我收到此错误:TestingLibraryElementError: Unable to find an element with the text: Name is required。这可能是因为文本被多个元素分解。在这种情况下,您可以为 你的文本匹配器使你的匹配器更灵活。

我以这种方式更改了最后一行:expect(screen.getByText('Name is required')).toBeInTheDocument(); 但得到了同样的错误。

我尝试使用 expect(screen.findByText('Name is required')).toBeInTheDocument();,但得到了同样的错误。

我最后一次尝试是:expect(screen.findByText('Name is required')).toBeTruthy();。在这里,该领域的测试通过了,但整体测试失败了。我得到的错误是:console.error 警告:您似乎有重叠的 act() 调用,这是不支持的。在进行新的调用之前,请务必等待先前的 act() 调用。 错误:未捕获 [TypeError:无法读取 null 的属性“useRealTimers”]

所以我被卡住了。任何帮助将非常感激。非常感谢!

【问题讨论】:

  • fireEvent 调用不需要您将它们包装在 act 中,因为库已经在内部完成了。
  • true 但问题不存在...仍然无法获取工具提示文本..
  • 您找到此查询的答案了吗,如果找到解决方案请更新我们

标签: reactjs jestjs react-testing-library


【解决方案1】:

我认为这是不可能的,因为 HTML5 验证的弹出窗口是由浏览器处理的。

Jest 是一个基于节点的运行器。 create-react-app docs 描述得最好:

Jest 是一个基于节点的运行器。这意味着测试总是在一个 节点环境而不是真正的浏览器。这让我们可以快速启用 迭代速度和防止片状。

虽然 Jest 通过 jsdom 提供了诸如 window 之类的浏览器全局变量, 它们只是真实浏览器行为的近似值。开玩笑是 旨在用于您的逻辑和组件的单元测试 而不是 DOM 怪癖。

我们建议您使用单独的工具进行浏览器端到端测试 如果你需要的话。

如果您想测试弹出窗口,可以使用合适的工具来完成这项工作,例如 Cypress。可以参考this

^ 这是我使用的方法。然后在测试库中我测试“my work”即

实际上触发验证的浏览器实现并不是真正测试您的工作(而是测试浏览器本身),这可能很好,但在我看来是不必要的。

因此,在您的示例中,由于需要输入并且您希望出现弹出窗口,因此可以假设输入的值仍然为空。所以我们为此写了一个断言:

expect(input).toHaveValue("")
// I also add some css to highlight the required input,
// so I assert on that
expect(input).toHaveClass("is-required")

【讨论】:

    【解决方案2】:

    您可以使用 querySelector 和伪类选择器通过 React 测试库测试 HTML5 内置验证:

    :valid
    

    例子:

    import { render, screen } from "@testing-library/react";
    import user from "@testing-library/user-event";
    import Client from "./index";
    
    const passedBrowserValidation = (view, name) => {
      const selector = `[name=${name}]:valid`;
      // eslint-disable-next-line testing-library/no-node-access
      const isValidated = view.container.querySelector(selector);
      return Boolean(isValidated);
    };
    
    const renderViewNew = () => {
      return render(
        <Client />
      );
    };
    
    const getClientName = () => {
      return screen.findByRole('textbox', { name: /Name/i });
    };
    
    describe("Client form", () => {
      it("Should validate ok a right value in name", () => {
        const view = renderViewNew();
        const nameField = getClientName();
        user.type(nameField, "Acme");
        expect(passedBrowserValidation(view, "name")).toBeTruthy();
      });
    });
    

    请注意,测试库作者尝试将discourage 使用querySelector,但在这种情况下,它可能是合理的。这就是 linter 评论的原因:// eslint-disable-next-line testing-library/no-node-access

    【讨论】:

      猜你喜欢
      • 2019-04-22
      • 2021-06-04
      • 2020-03-24
      • 2020-06-14
      • 2020-06-01
      • 2021-09-20
      • 2021-06-14
      • 2021-11-30
      • 2017-05-14
      相关资源
      最近更新 更多