Full Repo
https://github.com/brianbancroft/sample-testing-msw-sb-jest-rtl
Using mock service worker (msw) to respond to a network request, I have a React login component. On submit it sends a network request and on success it is supposed to trigger a "handleClose" function which is a prop to the component.
async function handleSubmit(event) {
event.preventDefault();
setLoading(true);
const { username, password } = event.target.elements;
try {
const response = await fetch("/login", {
method: "POST",
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
redirect: "follow",
referrerPolicy: "no-referrer",
body: JSON.stringify({
username: username.value,
password: password.value,
}),
});
await response.json();
if (response.status === 200) {
props.handleClose();
} else {
setInvalidUsernamePassword(true);
setLoading(false);
}
} catch (error) {
alert("Error detected", error);
}
}
When I test, I validate that the function handleClose
is invoked.
const setup = async () => {
const handleClose = jest.fn();
const utils = await render(<Primary handleClose={handleClose} />);
const usernameField = screen.getByLabelText(/Username/);
const passwordField = screen.getByLabelText(/Password/);
const submitButton = screen.getByRole("button", {
name: /Sign In/i,
});
return {
usernameField,
passwordField,
submitButton,
handleClose,
...utils,
};
};
test("The handleClose function prop is triggered", async () => {
const { usernameField, passwordField, submitButton, handleClose } =
await setup();
fireEvent.change(usernameField, { target: { value: faker.lorem.word() } });
fireEvent.change(passwordField, { target: { value: faker.lorem.word() } });
fireEvent.click(submitButton);
expect(handleClose).toHaveBeenCalled();
});
This fails
Expected number of calls: >= 1
Received number of calls: 0
However, when I invoke the prop function before the start of the async function, it passes, which tells me it's not how I am passing the jest.fn() into the component.
I have investigated whether an error gets thrown (it doesn't), and I also know that msw
is working as intended, and that the network request responds with a 200 unless I send a password value of "badpassword" which is used to simulate an incorrect email or password in another test in the same file.
I also converted the function to use promises. No change.