Skip to content

Commit

Permalink
fix: ds-356 axios response interceptors
Browse files Browse the repository at this point in the history
  • Loading branch information
cdcabrera committed Sep 13, 2024
1 parent 6978a70 commit 72e478f
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 23 deletions.
12 changes: 8 additions & 4 deletions src/hooks/__tests__/__snapshots__/useLoginApi.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ exports[`useGetSetAuthApi should attempt a call to get a token: getToken 1`] = `
]
`;

exports[`useGetSetAuthApi should process an interceptor error: interceptorError 1`] = `undefined`;

exports[`useGetSetAuthApi should process an interceptor success: interceptorSuccess 1`] = `
exports[`useGetSetAuthApi should process an interceptor request success: interceptorRequestSuccess 1`] = `
{
"headers": {
"Authorization": "Token Dolor sit",
Expand All @@ -19,7 +17,7 @@ exports[`useGetSetAuthApi should process an interceptor success: interceptorSucc
}
`;

exports[`useGetSetAuthApi should process an interceptor success: interceptorSuccess, token service 1`] = `
exports[`useGetSetAuthApi should process an interceptor request success: interceptorRequestSuccess, token service 1`] = `
{
"headers": {
"Authorization": "",
Expand All @@ -28,6 +26,12 @@ exports[`useGetSetAuthApi should process an interceptor success: interceptorSucc
}
`;

exports[`useGetSetAuthApi should process an interceptor response success: interceptorResponseSuccess 1`] = `undefined`;

exports[`useGetSetAuthApi should process interceptor request errors: interceptorRequestError 1`] = `undefined`;

exports[`useGetSetAuthApi should process interceptor response errors: interceptorResponseError 1`] = `undefined`;

exports[`useLoginApi should attempt an api call to login: apiCall 1`] = `
[
[
Expand Down
42 changes: 32 additions & 10 deletions src/hooks/__tests__/useLoginApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,17 @@ describe('useUserApi', () => {
});

describe('useGetSetAuthApi', () => {
const mockLogoutCallback = jest.fn();
let hookResult;

beforeEach(() => {
const hook = renderHook(() => useGetSetAuthApi());
const mockLogoutApi = () => ({
callbackSuccess: mockLogoutCallback,
callbackError: jest.fn(),
apiCall: jest.fn(),
logout: jest.fn()
});
const hook = renderHook(() => useGetSetAuthApi({ useLogout: mockLogoutApi }));
hookResult = hook?.result?.current;
});

Expand All @@ -198,24 +205,39 @@ describe('useGetSetAuthApi', () => {
expect(spyCookie.mock.calls).toMatchSnapshot('getToken');
});

it('should process an interceptor success', () => {
const { interceptorSuccess } = hookResult;
it('should process an interceptor request success', async () => {
const { interceptorRequestSuccess } = hookResult;

jest.spyOn(cookies, 'get').mockReturnValueOnce('RG9sb3Igc2l0');
const mockConfig = { headers: {}, url: '//mock-url' };
act(() => interceptorSuccess(mockConfig));
expect(mockConfig).toMatchSnapshot('interceptorSuccess');
act(() => interceptorRequestSuccess(mockConfig));
expect(mockConfig).toMatchSnapshot('interceptorRequestSuccess');

jest.spyOn(cookies, 'get').mockReturnValueOnce('');
const mockConfigTokenService = { headers: {}, url: `${process.env.REACT_APP_USER_SERVICE_AUTH_TOKEN}` };
act(() => interceptorSuccess(mockConfigTokenService));
expect(mockConfigTokenService).toMatchSnapshot('interceptorSuccess, token service');
act(() => interceptorRequestSuccess(mockConfigTokenService));
expect(mockConfigTokenService).toMatchSnapshot('interceptorRequestSuccess, token service');
});

it('should process an interceptor response success', async () => {
const { interceptorResponseSuccess } = hookResult;

await expect(interceptorResponseSuccess()).toMatchSnapshot('interceptorResponseSuccess');
});

it('should process an interceptor error', async () => {
const { interceptorError } = hookResult;
it('should process interceptor request errors', async () => {
const { interceptorRequestError } = hookResult;

await expect(interceptorRequestError()).rejects.toMatchSnapshot('interceptorRequestError');
});

it('should process interceptor response errors', async () => {
const { interceptorResponseError } = hookResult;

await expect(interceptorResponseError()).rejects.toMatchSnapshot('interceptorResponseError');

await expect(interceptorError()).rejects.toMatchSnapshot('interceptorError');
await interceptorResponseError({ response: { status: 401 } });
expect(mockLogoutCallback).toHaveBeenCalledTimes(1);
});

it('should return an authorization value on mount', async () => {
Expand Down
33 changes: 25 additions & 8 deletions src/hooks/useLoginApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ const useUserApi = () => {
/**
* Get initial token. Apply and set token for all Axios request interceptors, global authorization
*/
const useGetSetAuthApi = () => {
const useGetSetAuthApi = ({ useLogout = useLogoutApi }: { useLogout?: typeof useLogoutApi } = {}) => {
const { callbackSuccess: revokeToken } = useLogout();
const [isAuthorized, setIsAuthorized] = useState<boolean>(false);

const getToken = useCallback(() => {
Expand All @@ -176,7 +177,7 @@ const useGetSetAuthApi = () => {
return parsedToken;
}, []);

const interceptorSuccess = useCallback(
const interceptorRequestSuccess = useCallback(
config => {
const headerToken = getToken();

Expand All @@ -194,13 +195,27 @@ const useGetSetAuthApi = () => {
[getToken]
);

const interceptorError = useCallback(error => Promise.reject(error), []);
const interceptorRequestError = useCallback(error => Promise.reject(error), []);

const setInterceptors = useCallback(
() => axios.interceptors.request.use(interceptorSuccess, interceptorError),
[interceptorError, interceptorSuccess]
const interceptorResponseSuccess = useCallback(config => config, []);

const interceptorResponseError = useCallback(
error => {
if (error?.response?.status === 401) {
setIsAuthorized(false);
return revokeToken();
}

return Promise.reject(error);
},
[revokeToken]
);

const setInterceptors = useCallback(() => {
axios.interceptors.request.use(interceptorRequestSuccess, interceptorRequestError);
axios.interceptors.response.use(interceptorResponseSuccess, interceptorResponseError);
}, [interceptorResponseError, interceptorResponseSuccess, interceptorRequestError, interceptorRequestSuccess]);

useEffect(() => {
setInterceptors();
getToken();
Expand All @@ -210,8 +225,10 @@ const useGetSetAuthApi = () => {
return {
getToken,
isAuthorized,
interceptorError,
interceptorSuccess,
interceptorResponseError,
interceptorResponseSuccess,
interceptorRequestError,
interceptorRequestSuccess,
setInterceptors
};
};
Expand Down
2 changes: 1 addition & 1 deletion tests/__snapshots__/code.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ exports[`General code checks should only have specific console.[warn|log|info|er
"hooks/useLoginApi.ts:58: console.error(error);",
"hooks/useLoginApi.ts:99: console.error(error);",
"hooks/useLoginApi.ts:137: console.error(error);",
"hooks/useLoginApi.ts:165: console.error('Invalid token, unable to parse format');",
"hooks/useLoginApi.ts:166: console.error('Invalid token, unable to parse format');",
"hooks/useScanApi.ts:67: console.error(error);",
"hooks/useScanApi.ts:140: console.error(error);",
"hooks/useScanApi.ts:186: console.log(missingScansMsg);",
Expand Down

0 comments on commit 72e478f

Please sign in to comment.