11

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?

2
  • Can't reproduce it. It works fine. Commented Aug 19, 2021 at 2:39
  • Also can't reproduce Commented Aug 19, 2021 at 6:24

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.