I am learning react and testing (still :)). In a react component at some part of the code I have this:
...
const navigate = useNavigate();
...
const onSubmit = async (event) => {
event.preventDefault();
const { payload } = await dispatch(
startLoginWithEmail({ email, password })
);
if (payload.ok) {
navigate("/", {
replace: true,
});
}
}
...
Which is working fine in the application. I am practicing unit test, and in my test I can get everything I expect but when mock and test the navigate function I get it is not called. I need help to understand where I have the problem and hopefully be able to fix it. Here it is the test I have implemented:
test("should call startLoginWithEmail when the Login button is clicked", () => {
const email = "email@example.com";
const password = "12345678";
render(
<Provider store={store}>
<MemoryRouter>
<Login />
</MemoryRouter>
</Provider>
);
mockStartLoginWithEmail.mockResolvedValue({ payload: { ok: true } });
const emailInputText = screen.getByRole("textbox", { name: /email/i });
fireEvent.change(emailInputText, {
target: { name: "email", value: email },
});
const passwordInputText = screen.getByLabelText(/password/i);
fireEvent.change(passwordInputText, {
target: { name: "password", value: password },
});
const form = screen.getByRole("form");
fireEvent.submit(form);
expect(mockStartLoginWithEmail).toHaveBeenCalledWith({ email, password });
expect(mockUseNavigate).toHaveBeenCalledWith("/", {
replace: true,
});
});
But apparently mockUseNavigate is not being called.
I mock navigate function as follows:
const mockUseNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockUseNavigate,
}));
I have done something similar in other application and it worked, so I feel confuse what I could have missing here.
Edit: Also the accepted solution found here is very similar of what I have implemented.
I will appreciate help here to understand my missing and know what to do to have the test passing as expected. In the case it could be needed more context, here you can find the full code:
Edit:
Adding debug code in the testing, seems it should be being called, but the test throws Number of calls: 0
How is this possible?
const mockUseNavigate = jest.fn((...args) => {
console.log("mockUseNavigate called with:", ...args);
});
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => {
console.log("mockUseNavigate");
return mockUseNavigate;
},
}));