coze-studio/frontend/packages/arch/bot-http/__tests__/api-error.test.ts

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);
});
});