192 lines
5.6 KiB
TypeScript
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);
|
|
}
|
|
});
|
|
});
|
|
});
|