I want to test a child component, but it relies on state (hooks) from the parent.
the child receives isModalOpen and setIsModalOpen as properties. Each time isModalOpen changes, the useEffect inside Child will trigger. However, when I try to test the Child component by itself, I'm not able to force a state change triggering the useEffect hook. How can I achieve this without having to render the Parent in the test environment?
In the below example, I'm able to make the test pass by rendering Parent. I want to only render Child, and still make the test pass.
function Child({ isModalOpen, setIsModalOpen }) {
useEffect(() => {
console.log("is the modal open?", isModalOpen);
}, [isModalOpen]);
return (
<button data-testId="myBtn" onClick={() => setIsModalOpen(!isModalOpen)}>
Click to {isModalOpen ? "close" : "open"} modal
</button>
);
}
function Parent() {
const [isModalOpen, setIsModalOpen] = useState(false);
return <Child isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen} />;
}
Test:
it("React test", () => {
let isModalOpen = false;
const mockFunction = jest.fn((val) => (isModalOpen = val));
const { queryByTestId } = render(
<Child isModalOpen={isModalOpen} setIsModalOpen={mockFunction} />
);
const btnEl = queryByTestId("myBtn");
btnEl.click();
expect(btnEl.innerHTML).toEqual("Click to close modal");
// -----
// -----
// -----
// ----- The below code works
// const { queryByTestId } = render(<Parent />);
// const btnEl = queryByTestId("myBtn");
// btnEl.click();
// expect(btnEl.innerHTML).toEqual("Click to close modal");
});
Here is a working example of the above code snippet: https://codesandbox.io/s/jest-test-forked-cjm3r?file=/index.test.js