I'm desperately trying to test a modal but can't get my head around it!
This is where I'm at:
expect(
create(
<PortalManager>
<Modal isOpen={true} onClose={jest.fn()}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Modal Title</ModalHeader>
<ModalCloseButton />
<ModalBody>Modal body</ModalBody>
<ModalFooter>Modal footer</ModalFooter>
</ModalContent>
</Modal>
</PortalManager>,
).toJSON(),
).toMatchSnapshot();
I forced the modal to be opened. I added the PortalManager
around it to make sure Chakra knows where to place the modal but snapshot is always empty.
Well, an option may be to mock PortalManager
itself and make it act like a React.Component
instead of a React.ReactPortal
, so something like
const divWithChildrenMock = (children, identifier) => <div data-testId={identifier}>{children}</div>;
const divWithoutChildrenMock = (identifier) => <div data-testId={identifier} />;
jest.mock("@chakra-ui/react", () => (
{
...jest.requireActual("@chakra-ui/react"),
PortalManager: jest.fn(({ children }) => divWithChildrenMock(children, "portal")),
Modal: jest.fn(({ children }) => divWithChildrenMock(children, "modal")),
ModalOverlay: jest.fn(({ children }) => divWithChildrenMock(children, "overlay")),
ModalContent: jest.fn(({ children }) => divWithChildrenMock(children, "content")),
ModalHeader: jest.fn(({ children }) => divWithChildrenMock(children, "header")),
ModalFooter: jest.fn(({ children }) => divWithChildrenMock(children, "footer")),
ModalBody: jest.fn(({ children }) => divWithChildrenMock(children, "body")),
ModalCloseButton: jest.fn(() => divWithoutChildrenMock("close")),
}
));
By looking at the following source file
https://github.com/chakra-ui/chakra-ui/blob/main/packages/modal/src/modal.tsx
You can see that even the modal components uses Portal
, so, you should mock these components too, as in the example.
Test id is useful in the tests to check, in the snapshots, if all components are rendered in the right order.