当执行同一组件的两个渲染时,按钮禁用属性未正确更新

Button disabled attribute is not updated correctly when two renders of the same component are performed

我刚开始使用 react-testing-library,所以我猜测这最终归结为用户错误,但我看到以下行为对我来说没有意义。

在新创建的 CRA 应用程序中使用 jest-dom 3.0.0 和 react-testing-library 5.4.4 进行以下测试 运行:


    import React from "react";
    import { render } from "react-testing-library";
    import "jest-dom/extend-expect";

    import Component from "./Component";

    describe("Verify UI state based on jobs", () => {
      it("mounts with no previous data", () => {
        const { getByTestId } = render(<Component data={[]} />);
        expect(getByTestId("refresh-button")).toBeDisabled();
      });

      it("mounts with previous data", () => {
        const { getByTestId } = render(<Component data={["hi"]} />);
        expect(getByTestId("refresh-button")).not.toBeDisabled();
      });
    });

    /*
    const Component = props => {
      return (
        <div>
          <button data-testid="refresh-button" disabled={props.data.length === 0}>
            Refresh
          </button>
        </div>
      );
    };
    */

事实上,我遇到了以下故障:

根据作业验证 UI 状态 › 使用以前的数据装载

expect(element).not.toBeDisabled()

Received element is disabled:
  <button data-testid="refresh-button" disabled="" />

  13 |   it("mounts with previous data", async () => {
  14 |     const { getByTestId } = render(<Component data={["hi"]} />);
> 15 |     expect(getByTestId("refresh-button")).not.toBeDisabled();
     |                                               ^
  16 |   });
  17 | });
  18 |

  at Object.toBeDisabled (src/Component.test.js:15:47)

但是,如果我禁用第一个测试,第二个测试现在会正常通过。如果我重新排序,第一个测试总是通过而第二个总是失败,即使第一个测试是 'mount with pervious data' 测试。

不确定这是否是测试库、jest-dom 或我的代码中的问题,但如有任何关于如何正确构建这些测试的建议,我们将不胜感激。

文档当前声明当 render is called "the queries from dom-testing-library are automatically returned with their first argument bound to the rendered container".

事实证明这是文档中的一个错误,因为如果没有 container 传递给 render,查询实际上绑定到 document.body(代码 here and here ).

react-testing-library 使用 DOM,除非在测试之间调用 cleanup,否则来自早期测试的 DOM 元素仍将存在,并将包含在以后的查询结果中.

在这种情况下,在第二次测试期间,Component 元素都存在于 document.body 中,并且由于 getByTestId 查询 document.body 它最终找到了这两个元素,并且当它找到时不止一个吧returns the first one it finds.

这意味着第一个测试的 Component 在第二个测试中被 getByTestId 返回,这导致测试失败,因为第一个组件被禁用。


要解决此问题,请确保在每次测试后调用 cleanup 以删除在之前测试期间添加的所有 DOM 元素:

import React from "react";
import { render, cleanup } from "react-testing-library";
import "jest-dom/extend-expect";

afterEach(cleanup);  // clean up the DOM after each test

describe("Verify UI state based on jobs", () => {
  it("mounts with no previous data", () => {
    const { getByTestId } = render(<Component data={[]} />);
    expect(getByTestId("refresh-button")).toBeDisabled();  // SUCCESS
  });

  it("mounts with previous data", () => {
    const { getByTestId } = render(<Component data={["hi"]} />);
    expect(getByTestId("refresh-button")).not.toBeDisabled();  // SUCCESS
  });
});