Currently, I'm learning how to unit test with React. However, I'd like to learn it with TypeScript, so the course does not cover most errors that occur with TS.
I have a simple testing function configured with Mock Service Worker (msw):
fit("sends username, email and password to backend after clicking the button", async () => {
let requestBody;
const server = setupServer(
rest.post("/api/1.0/users", (req, res, ctx) => {
requestBody = req.body;
return res(ctx.status(200));
})
);
server.listen();
setupAll(); // Gets the elements on the page (like button)
userEvent.click(button);
await new Promise((resolve) => setTimeout(resolve, 250));
expect(requestBody).toEqual({
username: "LegacyUser",
email: "legacy@user.com",
password: "P455w0rd!",
});
});
In theory, this 'works' (it shows as a Pass in the testing list), but above it errors occur, like:
console.error
Warning: An update to SignUpPage inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
So when I wrap userEvent.click(button)
like act(() => userEvent.click(button))
, it keeps showing this error message.
The click userEvent triggers an onSubmit handler:
const formSubmitHandler = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const { username, email, password } = formEntries;
setIsApiInProgress(true);
axios
.post("/api/1.0/users", {
username,
email,
password,
})
.then((response) => {
if (response.status >= 200 && response.status < 300) {
setIsSignUpSuccessfull(true);
// console.log("OK", response.data);
return response.data;
}
throw new Error(response.status.toString());
})
.catch(({ response }) => {
console.log("CATCH", response);
})
.finally(() => {
setIsApiInProgress(false);
});
};
What am I doing wrong here? Also, is there a way to wait for a resolved promise without using timeouts? It feels kind of hacky this way.