UNPKG

@lobehub/chat

Version:

Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.

174 lines (140 loc) • 5.04 kB
import { beforeEach, describe, expect, it, vi } from 'vitest'; import { fileEnv } from '@/config/file'; import { edgeClient } from '@/libs/trpc/client'; import { API_ENDPOINTS } from '@/services/_url'; import { clientS3Storage } from '@/services/file/ClientS3'; import { UPLOAD_NETWORK_ERROR, uploadService } from '../upload'; // Mock dependencies vi.mock('@/libs/trpc/client', () => ({ edgeClient: { upload: { createS3PreSignedUrl: { mutate: vi.fn(), }, }, }, })); vi.mock('@/services/file/ClientS3', () => ({ clientS3Storage: { putObject: vi.fn(), }, })); vi.mock('@/utils/uuid', () => ({ uuid: () => 'mock-uuid', })); describe('UploadService', () => { const mockFile = new File(['test'], 'test.png', { type: 'image/png' }); const mockPreSignUrl = 'https://example.com/presign'; beforeEach(() => { vi.clearAllMocks(); // Mock Date.now vi.spyOn(Date, 'now').mockImplementation(() => 3600000); // 1 hour in milliseconds }); describe('uploadWithProgress', () => { beforeEach(() => { // Mock XMLHttpRequest const xhrMock = { upload: { addEventListener: vi.fn(), }, open: vi.fn(), send: vi.fn(), setRequestHeader: vi.fn(), addEventListener: vi.fn(), status: 200, }; global.XMLHttpRequest = vi.fn(() => xhrMock) as any; // Mock createS3PreSignedUrl (edgeClient.upload.createS3PreSignedUrl.mutate as any).mockResolvedValue(mockPreSignUrl); }); it('should upload file successfully with progress', async () => { const onProgress = vi.fn(); const xhr = new XMLHttpRequest(); // Simulate successful upload vi.spyOn(xhr, 'addEventListener').mockImplementation((event, handler) => { if (event === 'load') { // @ts-ignore handler({ target: { status: 200 } }); } }); const result = await uploadService.uploadToServerS3(mockFile, { onProgress }); expect(result).toEqual({ date: '1', dirname: `${fileEnv.NEXT_PUBLIC_S3_FILE_PATH}/1`, filename: 'mock-uuid.png', path: `${fileEnv.NEXT_PUBLIC_S3_FILE_PATH}/1/mock-uuid.png`, }); }); it('should handle network error', async () => { const xhr = new XMLHttpRequest(); // Simulate network error vi.spyOn(xhr, 'addEventListener').mockImplementation((event, handler) => { if (event === 'error') { Object.assign(xhr, { status: 0 }); // @ts-ignore handler({}); } }); await expect(uploadService.uploadToServerS3(mockFile, {})).rejects.toBe(UPLOAD_NETWORK_ERROR); }); it('should handle upload error', async () => { const xhr = new XMLHttpRequest(); // Simulate upload error vi.spyOn(xhr, 'addEventListener').mockImplementation((event, handler) => { if (event === 'load') { Object.assign(xhr, { status: 400, statusText: 'Bad Request' }); // @ts-ignore handler({}); } }); await expect(uploadService.uploadToServerS3(mockFile, {})).rejects.toBe('Bad Request'); }); }); describe('uploadToClientS3', () => { it('should upload file to client S3 successfully', async () => { const hash = 'test-hash'; const expectedResult = { date: '1', dirname: '', filename: mockFile.name, path: `client-s3://${hash}`, }; (clientS3Storage.putObject as any).mockResolvedValue(undefined); const result = await uploadService['uploadToClientS3'](hash, mockFile); expect(clientS3Storage.putObject).toHaveBeenCalledWith(hash, mockFile); expect(result).toEqual(expectedResult); }); }); describe('getImageFileByUrlWithCORS', () => { beforeEach(() => { global.fetch = vi.fn(); }); it('should fetch and create file from URL', async () => { const url = 'https://example.com/image.png'; const filename = 'test.png'; const mockArrayBuffer = new ArrayBuffer(8); (global.fetch as any).mockResolvedValue({ arrayBuffer: () => Promise.resolve(mockArrayBuffer), }); const result = await uploadService.getImageFileByUrlWithCORS(url, filename); expect(global.fetch).toHaveBeenCalledWith(API_ENDPOINTS.proxy, { body: url, method: 'POST', }); expect(result).toBeInstanceOf(File); expect(result.name).toBe(filename); expect(result.type).toBe('image/png'); }); it('should handle custom file type', async () => { const url = 'https://example.com/image.jpg'; const filename = 'test.jpg'; const fileType = 'image/jpeg'; const mockArrayBuffer = new ArrayBuffer(8); (global.fetch as any).mockResolvedValue({ arrayBuffer: () => Promise.resolve(mockArrayBuffer), }); const result = await uploadService.getImageFileByUrlWithCORS(url, filename, fileType); expect(result.type).toBe(fileType); }); }); });