React测试库,如何在Ant Design中打开一个Collapse

React testing library, how to open a Collapse in Ant Design

我想写一个打开antd的单元测试。收起 <Panel />

但无论我尝试使用何种 fireEvent 或 userEvent 鼠标操作组合,我都无法让 React 测试库以与真实用户相同的方式正确地“单击”这个 antD 组件。

示例代码:

import { Collapse } from 'antd'
const { Panel } = Collapse

const Example = () => (
<Collapse>
  <Panel header="test" data-testid="testid">hello_world</Panel>
</Collapse>
)

在我的单元测试中:

我尝试了以下组合来打开带有 header“测试”

的面板
const panel = screen.getByText('test')
userEvent.click(panel)

const result = screen.getByText('hello_world') // FAILED and never finds hello_world
const panel = screen.getByText('test')
userEvent.click(panel)

const result = await screen.findByText('hello_world') // FAILED and never finds hello_world
const panel = screen.getByText('test')
fireEvent.click(panel)

const result = await screen.findByText('hello_world') // FAILED and never finds hello_world
const panel = screen.getByText('test')
fireEvent.mouseDown(panel)

const result = await screen.findByText('hello_world') // FAILED and never finds hello_world
const panel = screen.getByText('test')
await act(async () => {
  fireEvent.mouseDown(panel)
})

const result = await screen.findByText('hello_world') // FAILED and never finds hello_world
const panel = screen.getByText('test')
await act(async () => {
  fireEvent.mouseDown(panel)
})

await waait(500) // using waait library, to force time to pass to see if it was that...

const result = await screen.findByText('hello_world') // FAILED and never finds hello_world
const panel = screen.getByTestId('testid')
fireEvent.click(panel) // FAILED, never finds anything with data-testid="testid"
// I guess antd did not bother passing the test-id to the component.

const result = await screen.findByText('hello_world')

这就是 HTML 的样子:

                    <div
                      class="ant-collapse ant-collapse-icon-position-left css-14dabdk"
                    >
                      <div
                        class="ant-collapse-item"
                      >
                        <div
                          aria-expanded="false"
                          class="ant-collapse-header"
                          role="button"
                          tabindex="0"
                        >
                          test
                        </div>
                      </div>

我也曾尝试在 container 上使用 querySelector.ant-collapse-headerant-collapse-item.ant-collapse 与 userEvent.click 和 fireEvent.mouseDown。但是那些也不管用。

为什么这个东西在测试中这么难打开。

有谁知道如何打开和antD Collapse组件吗?

使用user-event,你可以试试:

await userEvent.click(screen.getByText(/test/i))

或点击按钮,如:

await userEvent.click(screen.getByRole("button"))

然后你可以使用 findByText 比如:

expect(await screen.findByText(/hello_world/i)).toBeInTheDocument();

(Working example)

我创建了一个简单示例来模拟您的问题。

我做了什么让它工作:

  1. 而不是屏幕,我使用 getByTextqueryByTextfindByText 直接来自渲染的 return,例如 const { getByText, queryByText } = render(<Example />);

* 但你可以使用 screen,完全没有问题。

  1. 你的功能测试应该是async,比如:
it("test", async () => { ... })

test("test", async () => { ... })
  1. 要测试渲染 'Hello world' 是否成功,您可以将 getByTextwaitForfindByText 一起使用,如下所示:

代码:

describe("Test PANEL", () => {
  it("should PASS WITH QUERYBY - hello_world RENDERED after CLICKED", async () => {
    const { getByText, queryByText } = render(<Example />);

    const panel = getByText("test");

    fireEvent.click(panel);

    await waitFor(() => {
      const result = queryByText("hello_world");

      expect(result).toBeInTheDocument();
    });
  });

  it("should PASS WITH FINDBY - hello_world RENDERED after CLICKED", async () => {
    const { getByText, findByText } = render(<Example />);

    const panel = getByText("test");

    fireEvent.click(panel);

    const result = await findByText("hello_world");

    expect(result).toBeInTheDocument();
  });
});

如果你想检查 'hello_world' 是否还没有渲染,我建议你使用 queryBy,像这样:

describe("Test PANEL", () => {
  it("should PASS - hello_world NOT redenred before CLICKED", async () => {
    const { getByText, queryByText } = render(<Example />);

    const panel = getByText("test");

    expect(panel).toBeInTheDocument();

    await waitFor(() => {
      const result = queryByText("hello_world");

      expect(result).not.toBeInTheDocument();
    });
  });

那是因为如果 queryBy return 没有找到任何元素,则为 null,不同于 findBygetBy -> 两者都会抛出错误,因为您可以在这个link.

看到