ant design v4 打破了选择和自动完成的react测试库测试

IT技术 javascript reactjs antd react-testing-library
2021-05-02 07:18:29

我最近将我的 React 项目升级到了 ant design v4,所有使用 Select、AutoComplete 或 Tooltip 的测试都被破坏了。基本上在单击组件时,JSDOM 中不存在模态或选择选项。这曾经在 v3 中工作正常。

有人可以告诉我如何使用 react 测试库测试 antd v4 吗?

例子:

我的组件:

import React from "react";
import "./styles.css";
import { Select } from "antd";

const { Option } = Select;

function handleChange(value) {
  console.log(`selected ${value}`);
}

export default function App() {
  return (
    <div className="App" style={{ marginTop: "40px" }}>
      <Select
        defaultValue="lucy"
        style={{ width: 120 }}
        onChange={handleChange}
      >
        <Option value="jack">Jack</Option>
        <Option value="lucy">Lucy</Option>
        <Option value="disabled" disabled>
          Disabled
        </Option>
        <Option value="Yiminghe">yiminghe</Option>
      </Select>
    </div>
  );
}

我的测试

import "@testing-library/jest-dom/extend-expect";
import React from "react";
import { render, fireEvent, prettyDOM } from "@testing-library/react";
import App from "./App";

test("App Test", () => {
  const { queryAllByText, getByText, container } = render(<App />);

  expect(queryAllByText("Lucy").length).toBe(1);
  expect(queryAllByText("Jack").length).toBe(0);
  fireEvent.click(getByText("Lucy"));
  console.log(prettyDOM(container));
  // This line fails although I would expect the dropdown to be open and all the options visible
  expect(queryAllByText("Jack").length).toBe(1);
});

这是重现该问题的代码沙盒的链接。(如前所述,该代码曾经在 v3 中工作)。

https://codesandbox.io/s/staging-shape-0xkrl?file=/src/App.test.js:0-494

3个回答

在此失去 2 天后,这里是问题和解决方案:

问题

在 antd v3 中,过去可以通过执行selectHtmlElement.click(). 您可以在 chrome 开发工具控制台中进行测试。在 v4 中这不起作用。

这意味着在底层使用 JSDOM 的 RTL 将具有相同的行为。当你什么fireEvent.click(selectElement); 都不

解决方案

这让我走上了正轨:https : //github.com/ant-design/ant-design/issues/22074

您需要触发的事件不是 aclick()而是 amouseDown()在选择的第一个子项上。

const elt = getByTestId('your-select-test-id').firstElementChild;
fireEvent.mouseDown(elt); // THIS WILL OPEN THE SELECT !

现在,您可能想要从列表中选择一个选项,但有一个动画正在进行,因此以下代码(曾经在 v3 中工作)也将失败。

expect(getByText('Option from Select')).toBeVisible(); // FAILS !

您有 2 个选项,使用toBeInTheDocument()或等待动画结束使用waitFor(...)

选项 1:更快但不完全准确,我更喜欢将它用于简单的用例,因为它使测试更快且同步

expect(getByText('Option from Select')).toBeInTheDocument(); // WORKS !

选项 2:较慢,因为您需要等待动画完成,但对于复杂情况更准确

await waitFor(() => expect(getByText('Option from Select')).toBeVisible()); // WORKS !

现在看起来(“antd”:“4.17.3”,“@testing-library/user-event”:“^13.5.0”)userEvent.click{ skipPointerEventsCheck: true }作品:

const options = [
  { label: "🐱", value: "cat", },
  { label: "🐶", value: "dog", }
];

const onChangeMock = jest.fn();

render(
  <Select
    options={options}
    onChange={onChangeMock}
  />,
);

const select = screen.getByRole("combobox");

userEvent.click(select);

const option = screen.getByText("🐶");

userEvent.click(option, undefined, { skipPointerEventsCheck: true });

expect(onChangeMock).toHaveBeenCalledWith("dog", {
  label: "🐶",
  value: "dog",
});

不幸的是,@klugjo 的回答对我使用 antd-mobile 的Radio组件不起作用

我通过向组件添加额外的onClick属性解决了这个问题

<Radio.RadioItem
    key={key}
    checked={isSelected}
    onChange={onChange}
    onClick={onChange} // needed for rtl
    >
    {label}
</Radio.RadioItem>

不是一个干净的解决方案,因为它修改了用于测试的生产代码。它可能会错过一个失败TouchEvent,但这应该是 antd-mobile 库的问题——而不是这个测试。