161 lines
3.9 KiB
TypeScript
161 lines
3.9 KiB
TypeScript
/*
|
|
* Copyright 2025 coze-dev Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import { type AxiosError, AxiosHeaders } from 'axios';
|
|
import { logger } from '@coze-arch/logger';
|
|
|
|
import {
|
|
reportHttpError,
|
|
ReportEventNames,
|
|
ApiError,
|
|
isApiError,
|
|
} from '../src/api-error';
|
|
|
|
vi.mock('@coze-arch/logger', () => ({
|
|
logger: {
|
|
info: vi.fn(),
|
|
persist: {
|
|
error: vi.fn(),
|
|
},
|
|
},
|
|
}));
|
|
describe('reportHttpError', () => {
|
|
const error: AxiosError = {
|
|
response: {
|
|
data: {
|
|
code: '500',
|
|
msg: 'Internal Server Error',
|
|
},
|
|
status: 500,
|
|
statusText: '',
|
|
config: {
|
|
headers: new AxiosHeaders(),
|
|
},
|
|
headers: {
|
|
'x-tt-logid': '1234567890',
|
|
},
|
|
},
|
|
config: {
|
|
method: 'GET',
|
|
headers: new AxiosHeaders(),
|
|
url: '/users',
|
|
},
|
|
message: 'Request failed with status code 500',
|
|
name: 'AxiosError',
|
|
isAxiosError: true,
|
|
toJSON: () => ({}),
|
|
};
|
|
it('if no response data, should report http error', () => {
|
|
const eventName = ReportEventNames.ApiError;
|
|
const noResponseError: AxiosError = {
|
|
response: {
|
|
data: {
|
|
code: '',
|
|
},
|
|
status: 500,
|
|
statusText: '',
|
|
config: {
|
|
headers: new AxiosHeaders(),
|
|
},
|
|
headers: {
|
|
'x-tt-logid': '1234567890',
|
|
},
|
|
},
|
|
config: {
|
|
method: 'GET',
|
|
headers: new AxiosHeaders(),
|
|
url: '/users',
|
|
},
|
|
message: 'Request failed with status code 500',
|
|
name: 'AxiosError',
|
|
isAxiosError: true,
|
|
toJSON: () => ({}),
|
|
};
|
|
|
|
reportHttpError(eventName, noResponseError);
|
|
|
|
expect(logger.persist.error).toBeCalledWith({
|
|
eventName,
|
|
error: noResponseError,
|
|
meta: {
|
|
message: error.message,
|
|
name: error.name,
|
|
httpStatusCode: '500',
|
|
httpMethod: 'GET',
|
|
urlPath: '/users',
|
|
logId: '1234567890',
|
|
customErrorCode: '',
|
|
customErrorMsg: '',
|
|
},
|
|
});
|
|
});
|
|
|
|
it('should report http error', () => {
|
|
const eventName = ReportEventNames.ApiError;
|
|
|
|
reportHttpError(eventName, error);
|
|
|
|
expect(logger.persist.error).toHaveBeenCalledWith({
|
|
eventName,
|
|
error,
|
|
meta: {
|
|
message: error.message,
|
|
name: error.name,
|
|
httpStatusCode: '500',
|
|
httpMethod: 'GET',
|
|
urlPath: '/users',
|
|
logId: '1234567890',
|
|
customErrorCode: '500',
|
|
customErrorMsg: 'Internal Server Error',
|
|
},
|
|
});
|
|
});
|
|
|
|
it('should handle error when reporting http catch', () => {
|
|
const eventName = ReportEventNames.ApiError;
|
|
|
|
(logger.persist.error as any).mockImplementation(() => {
|
|
throw new Error('Failed to persist error');
|
|
});
|
|
|
|
expect(() => {
|
|
reportHttpError(eventName, error);
|
|
}).toThrowError('Failed to persist error');
|
|
});
|
|
});
|
|
|
|
describe('isApiError', () => {
|
|
it('should return true if error is an instance of ApiError', () => {
|
|
const error = new ApiError('500', 'Internal Server Error', {
|
|
data: {},
|
|
status: 500,
|
|
statusText: 'Internal Server Error',
|
|
headers: new AxiosHeaders(),
|
|
config: {
|
|
headers: new AxiosHeaders(),
|
|
},
|
|
});
|
|
const result = isApiError(error);
|
|
expect(result).toBe(true);
|
|
});
|
|
|
|
it('should return false if error is not an instance of ApiError', () => {
|
|
const error = new Error('OtherError');
|
|
const result = isApiError(error);
|
|
expect(result).toBe(false);
|
|
});
|
|
});
|