react-testing-library testing Ant Design modal
Asked Answered
D

2

10

I have a React component with Ant Design Modal inside it and I am trying to test that modal gets opened when a button it clicked:

The component:

const ModalComponent = () => {
  const [visible, setVisible] = useState(false);
  return (
    <>
      <Button type="primary" onClick={() => setVisible(true)}>
        Open Modal
      </Button>
      <Modal
        title="Modal title"
        centered
        visible={visible}
        onOk={() => setVisible(false)}
        onCancel={() => setVisible(false)}
      >
        <p>some contents...</p>
        <p>some contents...</p>
        <p>some contents...</p>
      </Modal>
    </>
  );
};

Test file:

test('modal opening', async () => {
  const { queryByText } = render(<ModalComponent />);

  fireEvent.click(queryByText('Open Modal'));

  await waitFor(() => expect(queryByText('Modal title')).toBeInTheDocument());
});

The problem is that the modal DOM is never rendered in the test when I try to debug, so the test fails. It could be happening because the modal content is created outside of the component DOM tree right inside the body tag?

Deshawndesi answered 18/8, 2021 at 9:11 Comment(2)
Can't reproduce it. It works fine.Homologous
Also can't reproduceExcommunicate
K
13

There is no test failure that you have given from our side.

A little information from my side on Antd modal component.

Antd Modal during testing renders outside the container. This is because Antd uses the rc-dialog component and that component uses react portal to show modal which is always render outside the root div. In the same way, during testing modal will not render in the container but outside of it.

The test that you have given will pass(modal is present) because the queryByText will search the element in document.body not inside the container.

test('modal opening', async () => {
  const { baseElement, queryByText } = render(<ModalComponent />);

  fireEvent.click(queryByText('Open Modal'));

  expect(baseElement).toMatchSnapshot(); // added snapshot

  await waitFor(() => expect(queryByText('Modal title')).toBeInTheDocument());
});

baseElement will show all the elements that are present in the document.body.

Kimbra answered 19/8, 2021 at 7:1 Comment(0)
F
0

I had this exact same use case, with a very similar component.

For some reason, if I triggered the event inside act, then the state of the component wouldn't be updated and the modal would never come up (even if a console.log in the event handler does show up in the console).

The solution was to do userEvent.click outside the act

Feingold answered 13/2, 2023 at 12:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.