简体   繁体   English

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

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

I want to write a unit test that opens an antd.我想写一个打开antd的单元测试。 Collapse <Panel />折叠<Panel />

But no matter what combination of fireEvent or userEvent mouse actions I try, I cannot get React testing library to properly "click" on this antD component the same way a real user does.但是无论我尝试使用什么组合的 fireEvent 或 userEvent 鼠标操作,我都无法让 React 测试库像真实用户一样正确地“点击”这个 antD 组件。

Example code:示例代码:

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

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

and in my unit test:在我的单元测试中:

I have tried the following combinations to open the Panel with the header "test"我尝试了以下组合来打开带有标题“test”的面板

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')

This is what the HTML looks like:这是 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>

I did also try to use querySelector on container to target .ant-collapse-header , ant-collapse-item or .ant-collapse with userEvent.click and fireEvent.mouseDown.我还尝试在container上使用querySelector来定位.ant-collapse-headerant-collapse-item.ant-collapse以及 userEvent.click 和 fireEvent.mouseDown。 But those didn't work either.但那些也没有用。

Why is this thing so difficult to open in a test 🤯.为什么这个东西在测试中这么难打开🤯。

Does anyone know how to open and antD Collapse component?有谁知道如何打开和 antD Collapse 组件?

Using user-event , you can try:使用user-event ,您可以尝试:

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

Or click the button, like:或单击按钮,例如:

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

Then you can use findByText like:然后你可以使用findByText像:

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

( Working example ) 工作示例

I've created a simple example to simulate your issue.我创建了一个简单的示例来模拟您的问题。

What i did to get it working:我做了什么让它工作:

  1. instead of screen, i use getByText , queryByText and findByText direct from the return of render, like const { getByText, queryByText } = render(<Example />);而不是屏幕,我使用getByTextqueryByTextfindByText直接从渲染的返回,如const { getByText, queryByText } = render(<Example />);

* but you can use screen , not problem at all. * 但你可以使用screen ,一点问题都没有。

  1. Your function test should be async , like:您的功能测试应该是async ,例如:
it("test", async () => { ... })

or或者

test("test", async () => { ... })
  1. To test the success of render 'Hello world', you can use getByText with waitFor or findByText , like below:要测试渲染“Hello world”是否成功,您可以将getByTextwaitForfindByText一起使用,如下所示:

Code:代码:

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();
  });
});

If you want to check if 'hello_world' is not rendered yet, i recommend you use queryBy , like this:如果您想检查 '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();
    });
  });

That´s because queryBy returns null if it doesnt find any Element, different than findBy and getBy -> both throws an error, as you can see in this link .那是因为如果queryBy没有找到任何元素,则返回 null,这与findBygetBy不同 -> 都会引发错误,如您在此链接中所见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM