From db187672fa3e3d40bfa8dc585836cbf16ca9ac11 Mon Sep 17 00:00:00 2001 From: David Kwon Date: Fri, 20 Oct 2023 15:25:51 -0400 Subject: [PATCH] fix: use 'errors.getMessage' to determine error message in AxiosWrapper Signed-off-by: David Kwon --- .../__tests__/axiosWrapper.spec.ts | 69 ++++++++++++++++++- .../services/backend-client/axiosWrapper.ts | 4 +- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/packages/dashboard-frontend/src/services/backend-client/__tests__/axiosWrapper.spec.ts b/packages/dashboard-frontend/src/services/backend-client/__tests__/axiosWrapper.spec.ts index bb122174f..24b4f25fd 100644 --- a/packages/dashboard-frontend/src/services/backend-client/__tests__/axiosWrapper.spec.ts +++ b/packages/dashboard-frontend/src/services/backend-client/__tests__/axiosWrapper.spec.ts @@ -10,7 +10,8 @@ * Red Hat, Inc. - initial API and implementation */ -import mockAxios, { AxiosInstance } from 'axios'; +import common from '@eclipse-che/common'; +import mockAxios, { AxiosInstance, AxiosResponse } from 'axios'; import { AxiosWrapper, @@ -46,7 +47,7 @@ describe('axiosWrapper', () => { expect(axiosGetSpy).toBeCalledTimes(1); }); - it('should retry 0 time without specifi error message', async () => { + it('should retry 0 time without specific error message', async () => { const expectedData = { data: 'some-data' }; axiosGetMock.mockReturnValue(new Promise(resolve => resolve(expectedData))); @@ -71,7 +72,22 @@ describe('axiosWrapper', () => { expect(axiosGetSpy).toBeCalledTimes(2); }); - it('should retry 1 time without specif error message', async () => { + it('should retry 1 time with Bearer Token Authorization is required axios response error message', async () => { + const expectedData = { data: 'some-data' }; + axiosGetMock + .mockRejectedValueOnce(createAxiosResponseError(bearerTokenAuthorizationIsRequiredErrorMsg)) + .mockReturnValue(new Promise(resolve => resolve(expectedData))); + + const result = await new AxiosWrapper( + axiosInstance, + bearerTokenAuthorizationIsRequiredErrorMsg, + ).get('some-url'); + + expect(result).toEqual(expectedData); + expect(axiosGetSpy).toBeCalledTimes(2); + }); + + it('should retry 1 time without specifc error message', async () => { const expectedData = { data: 'some-data' }; axiosGetMock .mockRejectedValueOnce(new Error('some error message')) @@ -99,6 +115,22 @@ describe('axiosWrapper', () => { expect(axiosGetSpy).toBeCalledTimes(3); }); + it('should retry 2 times with Bearer Token Authorization is required axios response error message', async () => { + const expectedData = { data: 'some-data' }; + axiosGetMock + .mockRejectedValueOnce(createAxiosResponseError(bearerTokenAuthorizationIsRequiredErrorMsg)) + .mockRejectedValueOnce(createAxiosResponseError(bearerTokenAuthorizationIsRequiredErrorMsg)) + .mockReturnValue(new Promise(resolve => resolve(expectedData))); + + const result = await new AxiosWrapper( + axiosInstance, + bearerTokenAuthorizationIsRequiredErrorMsg, + ).get('some-url'); + + expect(result).toEqual(expectedData); + expect(axiosGetSpy).toBeCalledTimes(3); + }); + it('should retry 2 times without specific error message', async () => { const expectedData = { data: 'some-data' }; axiosGetMock @@ -130,6 +162,25 @@ describe('axiosWrapper', () => { } }); + it('should fail after 3 times with Bearer Token Authorization is required axios response error message', async () => { + axiosGetMock + .mockRejectedValueOnce(createAxiosResponseError(bearerTokenAuthorizationIsRequiredErrorMsg)) + .mockRejectedValueOnce(createAxiosResponseError(bearerTokenAuthorizationIsRequiredErrorMsg)) + .mockRejectedValueOnce(createAxiosResponseError(bearerTokenAuthorizationIsRequiredErrorMsg)) + .mockRejectedValue(createAxiosResponseError(bearerTokenAuthorizationIsRequiredErrorMsg)); + + try { + await new AxiosWrapper(axiosInstance, bearerTokenAuthorizationIsRequiredErrorMsg).get( + 'some-url', + ); + fail('should fail'); + } catch (e: any) { + expect(common.helpers.errors.includesAxiosResponse(e)).toBeTruthy(); + expect(e.response.data).toEqual(bearerTokenAuthorizationIsRequiredErrorMsg); + expect(axiosGetSpy).toBeCalledTimes(4); + } + }); + it('should fail after 3 times without specific error message', async () => { axiosGetMock .mockRejectedValueOnce(new Error('error 1')) @@ -146,3 +197,15 @@ describe('axiosWrapper', () => { } }); }); + +function createAxiosResponseError(message: string): { response: AxiosResponse } { + return { + response: { + data: message, + status: 401, + statusText: 'Unauthorized', + headers: {}, + config: {}, + }, + }; +} diff --git a/packages/dashboard-frontend/src/services/backend-client/axiosWrapper.ts b/packages/dashboard-frontend/src/services/backend-client/axiosWrapper.ts index 48318327e..bae30ce63 100644 --- a/packages/dashboard-frontend/src/services/backend-client/axiosWrapper.ts +++ b/packages/dashboard-frontend/src/services/backend-client/axiosWrapper.ts @@ -10,6 +10,7 @@ * Red Hat, Inc. - initial API and implementation */ +import common from '@eclipse-che/common'; import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; import { delay } from '@/services/helpers/delay'; @@ -97,7 +98,8 @@ export class AxiosWrapper { } catch (err) { if ( !retry || - (this.errorMessagesToRetry && !(err as Error)?.message?.includes(this.errorMessagesToRetry)) + (this.errorMessagesToRetry && + !common.helpers.errors.getMessage(err).includes(this.errorMessagesToRetry)) ) { throw err; }