I'm rendering an element that makes use of a setTimeout to change the inner text from a loading state to a desired message:
function Message({ message }: any) {
const [showMessage, setShowMessage] = useState(false);
useEffect(() => {
const CTATimer = setTimeout(() => {
setShowMessage(true);
}, 1500);
return () => {
clearTimeout(CTATimer);
};
}, []);
if (!showMessage) {
return <p>Loading...</p>;
}
return (
<>
<div>{message.text}</div>
</>
);
}
The corresponding test renders, then advances time by 1500ms, and then should show the message. However, currently the test fails and the terminal shows that the text is still Loading...
. The test is written like so:
const mockMessage = {
text: "this is a message",
answers: [],
id: 1,
};
afterEach(() => {
jest.useRealTimers();
});
it("should show message after setTimeout", () => {
jest.useFakeTimers();
jest.advanceTimersByTime(1500);
customRender(<Message message={mockMessage} />); // my customRender is just the default render but with a ThemeProvider wrapper.
const message = screen.getByText(/this is a message/i);
expect(message).toBeInTheDocument();
});
Why would my test still be rendering the loading state when 1500ms have passed?
act
. rtl claims that that it's not needed: "(All renders and events being fired are wrapped in act, so you don't really need this.)[testing-library.com/docs/preact-testing-library/api/#act]" – Schuller