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

192 lines
5.6 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 { vi, describe, it, expect, beforeAll, beforeEach } from 'vitest';
import { Toast } from '@coze-arch/bot-semi';
import { axiosInstance, isApiError, ApiError } from '@coze-arch/bot-http';
// Import axios configuration to trigger Toast configuration
import '../src/axios';
vi.mock('@coze-arch/bot-semi', () => ({
Toast: {
config: vi.fn(),
error: vi.fn(),
},
}));
// emulating the isApiError function
vi.mock('@coze-arch/bot-http', () => {
// Save the original axiosInstant.interceptors.response.use method
const originalUse = vi.fn();
return {
axiosInstance: {
interceptors: {
response: {
use: originalUse,
},
},
},
isApiError: vi.fn(),
ApiError: vi
.fn()
.mockImplementation(function (this: any, code: string, msg: string) {
this.code = code;
this.msg = msg;
this.config = {};
this.name = 'ApiError';
}),
};
});
describe('axios configuration', () => {
let onFulfilled: Function;
let onRejected: Function;
beforeAll(async () => {
// Import axios configuration to trigger Toast configuration and blocker registration
await import('../src/axios');
// Verify that Toast.config is called
expect(Toast.config).toHaveBeenCalledWith({ top: 80 });
// Get the registered interceptor function
const useArgs = (axiosInstance.interceptors.response.use as any).mock
.calls[0];
onFulfilled = useArgs[0];
onRejected = useArgs[1];
});
beforeEach(() => {
vi.clearAllMocks();
});
describe('response interceptor', () => {
it('should return response data directly on success', () => {
const mockData = { foo: 'bar' };
const mockResponse = { data: mockData };
const result = onFulfilled(mockResponse);
expect(result).toEqual(mockData);
});
it('should show error toast when API error occurs', () => {
// Create an API error
const apiError = new (ApiError as any)('500', 'API Error');
// isApiError returns true
(isApiError as any).mockReturnValue(true);
try {
onRejected(apiError);
// If no errors are thrown, the test should fail
expect(true).toBe(false);
} catch (error) {
expect(isApiError).toHaveBeenCalledWith(apiError);
expect(Toast.error).toHaveBeenCalledWith({
content: apiError.msg,
showClose: false,
});
expect(error).toBe(apiError);
}
});
it('should not show error toast when __disableErrorToast is true', () => {
// Create an API error and set __disableErrorToast to true
const apiError = new (ApiError as any)('401', 'Unauthorized');
apiError.config.__disableErrorToast = true;
// isApiError returns true
(isApiError as any).mockReturnValue(true);
try {
onRejected(apiError);
// If no errors are thrown, the test should fail
expect(true).toBe(false);
} catch (error) {
expect(isApiError).toHaveBeenCalledWith(apiError);
expect(Toast.error).not.toHaveBeenCalled();
expect(error).toBe(apiError);
}
});
it('should not show error toast when error has no message', () => {
// Create an API error with no message
const apiError = new (ApiError as any)('403', undefined);
// isApiError returns true
(isApiError as any).mockReturnValue(true);
try {
onRejected(apiError);
// If no errors are thrown, the test should fail
expect(true).toBe(false);
} catch (error) {
expect(isApiError).toHaveBeenCalledWith(apiError);
expect(Toast.error).not.toHaveBeenCalled();
expect(error).toBe(apiError);
}
});
it('should not show error toast when isApiError returns false', () => {
// Create a normal error
const regularError = new Error('Regular Error');
(regularError as any).msg = 'Error message';
// isApiError returned false
(isApiError as any).mockReturnValue(false);
try {
onRejected(regularError);
// If no errors are thrown, the test should fail
expect(true).toBe(false);
} catch (error) {
expect(isApiError).toHaveBeenCalledWith(regularError);
expect(Toast.error).not.toHaveBeenCalled();
expect(error).toBe(regularError);
}
});
it('should handle null or undefined error', () => {
// Test null error
try {
onRejected(null);
// If no errors are thrown, the test should fail
expect(true).toBe(false);
} catch (error) {
expect(isApiError).toHaveBeenCalledWith(null);
expect(Toast.error).not.toHaveBeenCalled();
expect(error).toBe(null);
}
vi.clearAllMocks();
// Test undefined error
try {
onRejected(undefined);
// If no errors are thrown, the test should fail
expect(true).toBe(false);
} catch (error) {
expect(isApiError).toHaveBeenCalledWith(undefined);
expect(Toast.error).not.toHaveBeenCalled();
expect(error).toBe(undefined);
}
});
});
});