I'm trying to test a component that should open its modal. Modal is a part of this component, but it's rendered with createPortal(). I first check if modal exist in the document and after button click if it appeared but test fails.
Component:
const [openModal, setOpenModal] = useState(false);
function Component() {
return (
<div>
<button onClick={() => setOpenModal(true)}>Open Modal</button>
<Modal open={openModal}/>
</div>
)
}
Modal:
const Modal = ({ open, children }) => {
return createPortal(
<div style={{display: open ? "block" : "none"}} data-testid="modal">
{children}
</div>,
document.getElementById("modals")
);
};
Test:
test("component that opens modal", async () => {
render(<Component />);
const button = screen.getByText("Open Modal");
const modal = screen.queryByTestId("modal");
expect(modal).not.toBeInTheDocument();
fireEvent.click(button);
await waitFor(() => expect(modal).toBeInTheDocument()); // Fails
});
I tried to test it with await waitFor(() => expect(modal).toBeInTheDocument())
and also with standard expect(modal).toBeInTheDocument())
. I also tried to render modal without portal, but still had no effect on the test. Could you please explain how it should be tested?
This kind of behavior is probably generating a new render, try using act
Some useful links: https://github.com/threepointone/react-act-examples/blob/master/sync.md
https://testing-library.com/docs/preact-testing-library/api/#act