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.

129 lines (98 loc) 4.25 kB
import { zip } from 'fflate'; import { describe, expect, it } from 'vitest'; import { unzipFile } from './unzipFile'; describe('unzipFile', () => { it('should extract files from a ZIP archive', async () => { // Create a mock ZIP file with test data const testFiles = { 'test.txt': new TextEncoder().encode('Hello, World!'), 'folder/nested.txt': new TextEncoder().encode('Nested file content'), }; const zipped = await new Promise<Uint8Array>((resolve, reject) => { zip(testFiles, (error, data) => { if (error) reject(error); else resolve(data); }); }); const zipFile = new File([new Uint8Array(zipped)], 'test.zip', { type: 'application/zip' }); const extractedFiles = await unzipFile(zipFile); expect(extractedFiles).toHaveLength(2); expect(extractedFiles[0].name).toBe('test.txt'); expect(extractedFiles[1].name).toBe('nested.txt'); // Verify file contents const content1 = await extractedFiles[0].text(); expect(content1).toBe('Hello, World!'); const content2 = await extractedFiles[1].text(); expect(content2).toBe('Nested file content'); }); it('should skip directories in ZIP archive', async () => { const testFiles = { 'file.txt': new TextEncoder().encode('File content'), 'folder/': new Uint8Array(0), // Directory entry }; const zipped = await new Promise<Uint8Array>((resolve, reject) => { zip(testFiles, (error, data) => { if (error) reject(error); else resolve(data); }); }); const zipFile = new File([new Uint8Array(zipped)], 'test.zip', { type: 'application/zip' }); const extractedFiles = await unzipFile(zipFile); expect(extractedFiles).toHaveLength(1); expect(extractedFiles[0].name).toBe('file.txt'); }); it('should skip hidden files and __MACOSX directories', async () => { const testFiles = { '.hidden': new TextEncoder().encode('Hidden file'), '__MACOSX/._file.txt': new TextEncoder().encode('Mac metadata'), 'visible.txt': new TextEncoder().encode('Visible file'), }; const zipped = await new Promise<Uint8Array>((resolve, reject) => { zip(testFiles, (error, data) => { if (error) reject(error); else resolve(data); }); }); const zipFile = new File([new Uint8Array(zipped)], 'test.zip', { type: 'application/zip' }); const extractedFiles = await unzipFile(zipFile); expect(extractedFiles).toHaveLength(1); expect(extractedFiles[0].name).toBe('visible.txt'); }); it('should set correct MIME types for extracted files', async () => { const testFiles = { 'document.pdf': new TextEncoder().encode('PDF content'), 'image.png': new TextEncoder().encode('PNG content'), 'code.ts': new TextEncoder().encode('TypeScript code'), }; const zipped = await new Promise<Uint8Array>((resolve, reject) => { zip(testFiles, (error, data) => { if (error) reject(error); else resolve(data); }); }); const zipFile = new File([new Uint8Array(zipped)], 'test.zip', { type: 'application/zip' }); const extractedFiles = await unzipFile(zipFile); expect(extractedFiles).toHaveLength(3); expect(extractedFiles.find((f) => f.name === 'document.pdf')?.type).toBe('application/pdf'); expect(extractedFiles.find((f) => f.name === 'image.png')?.type).toBe('image/png'); expect(extractedFiles.find((f) => f.name === 'code.ts')?.type).toBe('text/typescript'); }); it('should handle empty ZIP files', async () => { const testFiles = {}; const zipped = await new Promise<Uint8Array>((resolve, reject) => { zip(testFiles, (error, data) => { if (error) reject(error); else resolve(data); }); }); const zipFile = new File([new Uint8Array(zipped)], 'empty.zip', { type: 'application/zip' }); const extractedFiles = await unzipFile(zipFile); expect(extractedFiles).toHaveLength(0); }); it('should reject on invalid ZIP file', async () => { const invalidFile = new File([new Uint8Array([1, 2, 3, 4])], 'invalid.zip', { type: 'application/zip', }); await expect(unzipFile(invalidFile)).rejects.toThrow(); }); });