/** * Tests for file utilities * Run with: pnpm test file-utils */ import { encodeFileToBase64, decodeBase64ToBuffer, isBase64, detectMimeType, validateBase64File, encodeFileWithMetadata, sanitizeFilename, calculateFileHash, FILE_SIZE_LIMITS, SUPPORTED_MIME_TYPES, } from './file-utils'; describe('File Utilities', () => { describe('encodeFileToBase64', () => { it('should encode buffer to base64', () => { const buffer = Buffer.from('test content'); const result = encodeFileToBase64(buffer); expect(result).toBe('dGVzdCBjb250ZW50'); }); it('should encode string to base64', () => { const result = encodeFileToBase64('test content'); expect(result).toBe('dGVzdCBjb250ZW50'); }); it('should return base64 string as-is if already encoded', () => { const base64 = 'dGVzdCBjb250ZW50'; const result = encodeFileToBase64(base64); expect(result).toBe(base64); }); it('should include MIME type in data URL format', () => { const buffer = Buffer.from('test'); const result = encodeFileToBase64(buffer, 'application/json'); expect(result).toContain('data:application/json;base64,'); }); }); describe('decodeBase64ToBuffer', () => { it('should decode base64 to buffer', () => { const base64 = 'dGVzdCBjb250ZW50'; const buffer = decodeBase64ToBuffer(base64); expect(buffer.toString()).toBe('test content'); }); it('should handle data URL format', () => { const dataUrl = 'data:application/json;base64,dGVzdCBjb250ZW50'; const buffer = decodeBase64ToBuffer(dataUrl); expect(buffer.toString()).toBe('test content'); }); }); describe('isBase64', () => { it('should return true for valid base64', () => { expect(isBase64('dGVzdCBjb250ZW50')).toBe(true); expect(isBase64('SGVsbG8gV29ybGQ=')).toBe(true); }); it('should return false for invalid base64', () => { expect(isBase64('not base64!@#')).toBe(false); expect(isBase64('')).toBe(false); }); it('should handle data URL format', () => { expect(isBase64('data:application/json;base64,dGVzdA==')).toBe(true); }); }); describe('detectMimeType', () => { it('should detect PDF from buffer', () => { const pdfBuffer = Buffer.from('%PDF-1.4\n'); const mimeType = detectMimeType(pdfBuffer); expect(mimeType).toBe(SUPPORTED_MIME_TYPES.PDF); }); it('should detect PNG from buffer', () => { const pngBuffer = Buffer.from([0x89, 0x50, 0x4E, 0x47]); const mimeType = detectMimeType(pngBuffer); expect(mimeType).toBe(SUPPORTED_MIME_TYPES.PNG); }); it('should detect MIME type from filename', () => { const mimeType = detectMimeType(Buffer.from('test'), 'document.pdf'); expect(mimeType).toBe(SUPPORTED_MIME_TYPES.PDF); }); }); describe('validateBase64File', () => { it('should validate valid base64 file', () => { const base64 = encodeFileToBase64(Buffer.from('test content')); const result = validateBase64File(base64); expect(result.valid).toBe(true); expect(result.errors).toHaveLength(0); }); it('should reject invalid base64', () => { const result = validateBase64File('invalid base64!@#'); expect(result.valid).toBe(false); expect(result.errors.length).toBeGreaterThan(0); }); it('should enforce size limits', () => { const largeBuffer = Buffer.alloc(FILE_SIZE_LIMITS.MEDIUM + 1); const base64 = encodeFileToBase64(largeBuffer); const result = validateBase64File(base64, { maxSize: FILE_SIZE_LIMITS.MEDIUM, }); expect(result.valid).toBe(false); expect(result.errors.some(e => e.includes('exceeds maximum'))).toBe(true); }); it('should validate MIME types', () => { const pdfBuffer = Buffer.from('%PDF-1.4\n'); const base64 = encodeFileToBase64(pdfBuffer); const result = validateBase64File(base64, { allowedMimeTypes: [SUPPORTED_MIME_TYPES.PDF], }); expect(result.valid).toBe(true); }); it('should reject disallowed MIME types', () => { const pdfBuffer = Buffer.from('%PDF-1.4\n'); const base64 = encodeFileToBase64(pdfBuffer); const result = validateBase64File(base64, { allowedMimeTypes: [SUPPORTED_MIME_TYPES.PNG], }); expect(result.valid).toBe(false); }); }); describe('sanitizeFilename', () => { it('should sanitize unsafe characters', () => { const filename = '../../etc/passwd'; const sanitized = sanitizeFilename(filename); expect(sanitized).not.toContain('/'); expect(sanitized).not.toContain('..'); }); it('should preserve safe characters', () => { const filename = 'document_123.pdf'; const sanitized = sanitizeFilename(filename); expect(sanitized).toBe('document_123.pdf'); }); it('should limit filename length', () => { const longFilename = 'a'.repeat(300) + '.pdf'; const sanitized = sanitizeFilename(longFilename); expect(sanitized.length).toBeLessThanOrEqual(255); }); }); describe('calculateFileHash', () => { it('should calculate SHA256 hash', () => { const data = Buffer.from('test content'); const hash = calculateFileHash(data); expect(hash).toHaveLength(64); // SHA256 produces 64 hex characters expect(typeof hash).toBe('string'); }); it('should calculate SHA512 hash', () => { const data = Buffer.from('test content'); const hash = calculateFileHash(data, 'sha512'); expect(hash).toHaveLength(128); // SHA512 produces 128 hex characters }); }); });