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