I am trying to mock useMutation, It has a certain parameter called onError. I am using it as depicted in the piece of code right below.
Whenever useRedirectOnErrorMutation is used, a header with the token is attached to the request, so if the token is invalid there will be 401 error response which I will catch in the onError function that comes with useMutation and redirect the user to the login page.
export const useRedirectOnErrorMutation = <
TData = unknown,
TError = unknown,
TVariables = void,
TContext = unknown
>(
redirectionPath: string,
key: MutationKey,
mutationFunction: MutationFunction<TData, TVariables>,
options?: UseMutationOptions<TData, TError, TVariables, TContext>
): UseMutationResult<TData, TError, TVariables, TContext> => {
const router = useRouter();
console.log(useMutation);
return useMutation(key, mutationFunction, {
...options,
onError: (error) => {
if (error?.response.status == "401" || error?.response.status == "422") {
localStorage.removeItem("token");
localStorage.removeItem("userId");
router.push(redirectionPath);
}
},
});
};
The above code works perfectly fine, now I have to test this function with 100% coverage.
My current implementation on the testing of the function is as follows.
describe("(when api call gives error", () => {
it("should return the response", () => {
const push = jest.fn();
let onError: (
error: any,
variables: any,
context: any | undefined
) => Promise<void> | void;
// @ts-ignore
Router.useRouter = jest.fn(() => ({
push: push,
}));
const mockData = { email: "test@test.com", password: "test@1234" };
// @ts-ignore
ReactQuery.useMutation = jest.fn(
(
key: MutationKey,
mutationFunction: MutationFunction,
options: MutateOptions<
AxiosResponse<LoginResponse>,
AxiosError,
LoginValidationValues
>
) => {
console.log(options.onError.arguments);
onError = options.onError;
return {
mutate: jest.fn(() => mockData),
isLoading: false,
};
}
);
const { result, rerender } = renderHook(() =>
useRedirectOnErrorMutation("/auth/admin/login", "key", adminLoginAPI)
);
rerender();
act(() => {
onError({}, {}, {});
});
expect(result.current.mutate(mockData)).toEqual(mockData);
expect(push).toHaveBeenCalled();
});
});
});
Now, the issue with testing here is that everytime I run it, it still shows the onError part uncovered and an error message saying that error.response is not defined. I am not sure how to pass the onError parameters in the testing.
That is (error)
onError: (error) => {
if (error?.response.status == "401" || error?.response.status == "422") {
localStorage.removeItem("token");
localStorage.removeItem("userId");
router.push(redirectionPath);
}
Ideally passing an error object in the testing wrapped by act should have worked but it also ended up with an error message onError is not a function.
act(()=>{
onError({response:{status: 401}},{},{})
})
Any help would be appreciated! I am completely stuck here.