fix(tests): resolve frontend unit test issues due to new errors system
This commit is contained in:
parent
aac32ea64a
commit
fbaf30b29e
|
|
@ -18,7 +18,8 @@ describe('ErrorHelper', () => {
|
||||||
status: 404
|
status: 404
|
||||||
},
|
},
|
||||||
status: 404
|
status: 404
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.getErrorInfo(structuredError);
|
const result = ErrorHelper.getErrorInfo(structuredError);
|
||||||
|
|
@ -37,7 +38,8 @@ describe('ErrorHelper', () => {
|
||||||
message: 'Legacy error message'
|
message: 'Legacy error message'
|
||||||
},
|
},
|
||||||
status: 500
|
status: 500
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.getErrorInfo(legacyError);
|
const result = ErrorHelper.getErrorInfo(legacyError);
|
||||||
|
|
@ -53,7 +55,8 @@ describe('ErrorHelper', () => {
|
||||||
message: 'Network Error',
|
message: 'Network Error',
|
||||||
response: {
|
response: {
|
||||||
status: 500
|
status: 500
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.getErrorInfo(axiosError);
|
const result = ErrorHelper.getErrorInfo(axiosError);
|
||||||
|
|
@ -98,7 +101,8 @@ describe('ErrorHelper', () => {
|
||||||
data: {},
|
data: {},
|
||||||
status: 400
|
status: 400
|
||||||
},
|
},
|
||||||
message: 'Bad Request'
|
message: 'Bad Request',
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.getErrorInfo(emptyError);
|
const result = ErrorHelper.getErrorInfo(emptyError);
|
||||||
|
|
@ -119,7 +123,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_NOT_FOUND',
|
code: 'USER_NOT_FOUND',
|
||||||
status: 404
|
status: 404
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.isErrorCode(error, ErrorCodes.USER_NOT_FOUND)).toBe(true);
|
expect(ErrorHelper.isErrorCode(error, ErrorCodes.USER_NOT_FOUND)).toBe(true);
|
||||||
|
|
@ -133,7 +138,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_NOT_FOUND',
|
code: 'USER_NOT_FOUND',
|
||||||
status: 404
|
status: 404
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.isErrorCode(error, ErrorCodes.USER_DUPLICATE_USERNAME)).toBe(false);
|
expect(ErrorHelper.isErrorCode(error, ErrorCodes.USER_DUPLICATE_USERNAME)).toBe(false);
|
||||||
|
|
@ -145,7 +151,8 @@ describe('ErrorHelper', () => {
|
||||||
data: {
|
data: {
|
||||||
message: 'Legacy error'
|
message: 'Legacy error'
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.isErrorCode(error, ErrorCodes.USER_NOT_FOUND)).toBe(false);
|
expect(ErrorHelper.isErrorCode(error, ErrorCodes.USER_NOT_FOUND)).toBe(false);
|
||||||
|
|
@ -172,7 +179,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_NOT_FOUND',
|
code: 'USER_NOT_FOUND',
|
||||||
status: 404
|
status: 404
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.getUserMessage(error)).toBe('Custom error message');
|
expect(ErrorHelper.getUserMessage(error)).toBe('Custom error message');
|
||||||
|
|
@ -185,7 +193,7 @@ describe('ErrorHelper', () => {
|
||||||
|
|
||||||
test('should return default fallback when no message', () => {
|
test('should return default fallback when no message', () => {
|
||||||
const error = null;
|
const error = null;
|
||||||
expect(ErrorHelper.getUserMessage(error)).toBe('An error occurred');
|
expect(ErrorHelper.getUserMessage(error)).toBe('An unknown error occurred');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -198,7 +206,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_DUPLICATE_USERNAME',
|
code: 'USER_DUPLICATE_USERNAME',
|
||||||
status: 409
|
status: 409
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.getSuggestedAction(error)).toBe('Please choose a different username');
|
expect(ErrorHelper.getSuggestedAction(error)).toBe('Please choose a different username');
|
||||||
|
|
@ -212,7 +221,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_INVALID_CREDENTIALS',
|
code: 'USER_INVALID_CREDENTIALS',
|
||||||
status: 401
|
status: 401
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.getSuggestedAction(error)).toBe('Please check your username and password');
|
expect(ErrorHelper.getSuggestedAction(error)).toBe('Please check your username and password');
|
||||||
|
|
@ -226,7 +236,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'UNKNOWN_ERROR_CODE',
|
code: 'UNKNOWN_ERROR_CODE',
|
||||||
status: 500
|
status: 500
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.getSuggestedAction(error)).toBe(null);
|
expect(ErrorHelper.getSuggestedAction(error)).toBe(null);
|
||||||
|
|
@ -247,7 +258,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'SOURCE_CONNECTION_FAILED',
|
code: 'SOURCE_CONNECTION_FAILED',
|
||||||
status: 503
|
status: 503
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.shouldShowRetry(error)).toBe(true);
|
expect(ErrorHelper.shouldShowRetry(error)).toBe(true);
|
||||||
|
|
@ -260,7 +272,8 @@ describe('ErrorHelper', () => {
|
||||||
message: 'Internal server error'
|
message: 'Internal server error'
|
||||||
},
|
},
|
||||||
status: 500
|
status: 500
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.shouldShowRetry(error)).toBe(true);
|
expect(ErrorHelper.shouldShowRetry(error)).toBe(true);
|
||||||
|
|
@ -274,7 +287,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_INVALID_CREDENTIALS',
|
code: 'USER_INVALID_CREDENTIALS',
|
||||||
status: 400
|
status: 400
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.shouldShowRetry(error)).toBe(false);
|
expect(ErrorHelper.shouldShowRetry(error)).toBe(false);
|
||||||
|
|
@ -293,7 +307,8 @@ describe('ErrorHelper', () => {
|
||||||
const error = {
|
const error = {
|
||||||
response: {
|
response: {
|
||||||
data: { error: 'Test', code, status: 401 }
|
data: { error: 'Test', code, status: 401 }
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
expect(ErrorHelper.getErrorCategory(error)).toBe('auth');
|
expect(ErrorHelper.getErrorCategory(error)).toBe('auth');
|
||||||
});
|
});
|
||||||
|
|
@ -310,7 +325,8 @@ describe('ErrorHelper', () => {
|
||||||
const error = {
|
const error = {
|
||||||
response: {
|
response: {
|
||||||
data: { error: 'Test', code, status: 400 }
|
data: { error: 'Test', code, status: 400 }
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
expect(ErrorHelper.getErrorCategory(error)).toBe('validation');
|
expect(ErrorHelper.getErrorCategory(error)).toBe('validation');
|
||||||
});
|
});
|
||||||
|
|
@ -324,7 +340,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'SOURCE_CONNECTION_FAILED',
|
code: 'SOURCE_CONNECTION_FAILED',
|
||||||
status: 503
|
status: 503
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(ErrorHelper.getErrorCategory(error)).toBe('network');
|
expect(ErrorHelper.getErrorCategory(error)).toBe('network');
|
||||||
|
|
@ -338,7 +355,7 @@ describe('ErrorHelper', () => {
|
||||||
{ status: 422, expectedCategory: 'validation' },
|
{ status: 422, expectedCategory: 'validation' },
|
||||||
{ status: 500, expectedCategory: 'server' },
|
{ status: 500, expectedCategory: 'server' },
|
||||||
{ status: 502, expectedCategory: 'server' },
|
{ status: 502, expectedCategory: 'server' },
|
||||||
{ status: 503, expectedCategory: 'server' }
|
{ status: 503, expectedCategory: 'network' }
|
||||||
];
|
];
|
||||||
|
|
||||||
statusTests.forEach(({ status, expectedCategory }) => {
|
statusTests.forEach(({ status, expectedCategory }) => {
|
||||||
|
|
@ -346,7 +363,8 @@ describe('ErrorHelper', () => {
|
||||||
response: {
|
response: {
|
||||||
data: { message: 'Test error' },
|
data: { message: 'Test error' },
|
||||||
status
|
status
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
expect(ErrorHelper.getErrorCategory(error)).toBe(expectedCategory);
|
expect(ErrorHelper.getErrorCategory(error)).toBe(expectedCategory);
|
||||||
});
|
});
|
||||||
|
|
@ -373,16 +391,16 @@ describe('ErrorHelper', () => {
|
||||||
let error;
|
let error;
|
||||||
switch (category) {
|
switch (category) {
|
||||||
case 'auth':
|
case 'auth':
|
||||||
error = { response: { data: { code: 'USER_INVALID_CREDENTIALS' }, status: 401 } };
|
error = { response: { data: { code: 'USER_INVALID_CREDENTIALS' }, status: 401 }, isAxiosError: true };
|
||||||
break;
|
break;
|
||||||
case 'validation':
|
case 'validation':
|
||||||
error = { response: { data: { code: 'USER_INVALID_PASSWORD' }, status: 400 } };
|
error = { response: { data: { code: 'USER_INVALID_PASSWORD' }, status: 400 }, isAxiosError: true };
|
||||||
break;
|
break;
|
||||||
case 'network':
|
case 'network':
|
||||||
error = { response: { data: { code: 'SOURCE_CONNECTION_FAILED' }, status: 503 } };
|
error = { response: { data: { code: 'SOURCE_CONNECTION_FAILED' }, status: 503 }, isAxiosError: true };
|
||||||
break;
|
break;
|
||||||
case 'server':
|
case 'server':
|
||||||
error = { response: { data: { message: 'Server error' }, status: 500 } };
|
error = { response: { data: { message: 'Server error' }, status: 500 }, isAxiosError: true };
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error = new Error('Unknown error');
|
error = new Error('Unknown error');
|
||||||
|
|
@ -402,7 +420,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_DUPLICATE_USERNAME',
|
code: 'USER_DUPLICATE_USERNAME',
|
||||||
status: 409
|
status: 409
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.formatErrorForDisplay(error, true);
|
const result = ErrorHelper.formatErrorForDisplay(error, true);
|
||||||
|
|
@ -425,7 +444,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_DUPLICATE_USERNAME',
|
code: 'USER_DUPLICATE_USERNAME',
|
||||||
status: 409
|
status: 409
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.formatErrorForDisplay(error, false);
|
const result = ErrorHelper.formatErrorForDisplay(error, false);
|
||||||
|
|
@ -446,7 +466,8 @@ describe('ErrorHelper', () => {
|
||||||
const error = {
|
const error = {
|
||||||
response: {
|
response: {
|
||||||
data: { error: 'Test', code, status: 400 }
|
data: { error: 'Test', code, status: 400 }
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.formatErrorForDisplay(error, true);
|
const result = ErrorHelper.formatErrorForDisplay(error, true);
|
||||||
|
|
@ -464,7 +485,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_SESSION_EXPIRED',
|
code: 'USER_SESSION_EXPIRED',
|
||||||
status: 401
|
status: 401
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const onLogin = vi.fn();
|
const onLogin = vi.fn();
|
||||||
|
|
@ -482,7 +504,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'SOURCE_CONNECTION_FAILED',
|
code: 'SOURCE_CONNECTION_FAILED',
|
||||||
status: 503
|
status: 503
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRetry = vi.fn();
|
const onRetry = vi.fn();
|
||||||
|
|
@ -503,7 +526,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'SOME_OTHER_ERROR',
|
code: 'SOME_OTHER_ERROR',
|
||||||
status: 400
|
status: 400
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.handleSpecificError(error);
|
const result = ErrorHelper.handleSpecificError(error);
|
||||||
|
|
@ -518,7 +542,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_SESSION_EXPIRED',
|
code: 'USER_SESSION_EXPIRED',
|
||||||
status: 401
|
status: 401
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.handleSpecificError(error);
|
const result = ErrorHelper.handleSpecificError(error);
|
||||||
|
|
@ -560,12 +585,12 @@ describe('ErrorHelper', () => {
|
||||||
describe('Edge cases and robustness', () => {
|
describe('Edge cases and robustness', () => {
|
||||||
test('should handle malformed error objects', () => {
|
test('should handle malformed error objects', () => {
|
||||||
const malformedErrors = [
|
const malformedErrors = [
|
||||||
{ response: null },
|
{ response: null, isAxiosError: true },
|
||||||
{ response: { data: null } },
|
{ response: { data: null }, isAxiosError: true },
|
||||||
{ response: { data: { error: null, code: null } } },
|
{ response: { data: { error: null, code: null } }, isAxiosError: true },
|
||||||
{ response: { status: 'not-a-number' } },
|
{ response: { status: 'not-a-number' }, isAxiosError: true },
|
||||||
{ code: 123 }, // numeric code instead of string
|
{ code: 123, isAxiosError: true }, // numeric code instead of string
|
||||||
{ message: { nested: 'object' } } // object instead of string
|
{ message: { nested: 'object' }, isAxiosError: true } // object instead of string
|
||||||
];
|
];
|
||||||
|
|
||||||
malformedErrors.forEach(error => {
|
malformedErrors.forEach(error => {
|
||||||
|
|
@ -586,7 +611,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 'USER_NOT_FOUND',
|
code: 'USER_NOT_FOUND',
|
||||||
status: 404
|
status: 404
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.getErrorInfo(error);
|
const result = ErrorHelper.getErrorInfo(error);
|
||||||
|
|
@ -602,7 +628,8 @@ describe('ErrorHelper', () => {
|
||||||
code: 12345, // numeric code
|
code: 12345, // numeric code
|
||||||
status: 400
|
status: 400
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Should not crash and should handle it as if no code was provided
|
// Should not crash and should handle it as if no code was provided
|
||||||
|
|
@ -623,7 +650,8 @@ describe('ErrorHelper', () => {
|
||||||
response: {
|
response: {
|
||||||
data: apiError,
|
data: apiError,
|
||||||
status: 404
|
status: 404
|
||||||
}
|
},
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.getErrorInfo(error);
|
const result = ErrorHelper.getErrorInfo(error);
|
||||||
|
|
@ -645,7 +673,8 @@ describe('ErrorHelper', () => {
|
||||||
headers: {}
|
headers: {}
|
||||||
},
|
},
|
||||||
message: 'Request failed',
|
message: 'Request failed',
|
||||||
name: 'AxiosError'
|
name: 'AxiosError',
|
||||||
|
isAxiosError: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = ErrorHelper.getErrorInfo(axiosError);
|
const result = ErrorHelper.getErrorInfo(axiosError);
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,9 @@ export const ErrorHelper = {
|
||||||
*/
|
*/
|
||||||
getUserMessage: (error: unknown, fallback?: string): string => {
|
getUserMessage: (error: unknown, fallback?: string): string => {
|
||||||
const errorInfo = ErrorHelper.getErrorInfo(error)
|
const errorInfo = ErrorHelper.getErrorInfo(error)
|
||||||
|
if (errorInfo.message === 'An unknown error occurred' && fallback) {
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
return errorInfo.message || fallback || 'An error occurred'
|
return errorInfo.message || fallback || 'An error occurred'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -219,7 +222,7 @@ export const ErrorHelper = {
|
||||||
if (['USER_INVALID_CREDENTIALS', 'USER_TOKEN_EXPIRED', 'USER_SESSION_EXPIRED'].includes(errorInfo.code)) {
|
if (['USER_INVALID_CREDENTIALS', 'USER_TOKEN_EXPIRED', 'USER_SESSION_EXPIRED'].includes(errorInfo.code)) {
|
||||||
return 'auth'
|
return 'auth'
|
||||||
}
|
}
|
||||||
if (['USER_INVALID_PASSWORD', 'USER_INVALID_EMAIL', 'USER_INVALID_USERNAME'].includes(errorInfo.code)) {
|
if (['USER_INVALID_PASSWORD', 'USER_INVALID_EMAIL', 'USER_INVALID_USERNAME', 'USER_DUPLICATE_USERNAME', 'USER_DUPLICATE_EMAIL'].includes(errorInfo.code)) {
|
||||||
return 'validation'
|
return 'validation'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -232,6 +235,10 @@ export const ErrorHelper = {
|
||||||
return 'validation'
|
return 'validation'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (errorInfo.status === 503) {
|
||||||
|
return 'network'
|
||||||
|
}
|
||||||
|
|
||||||
if (errorInfo.status && errorInfo.status >= 500) {
|
if (errorInfo.status && errorInfo.status >= 500) {
|
||||||
return 'server'
|
return 'server'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue