/** * @fileoverview Cross-Platform Compatibility Tests * @author GrabZilla Development Team * @version 2.1.0 * @since 2024-01-01 */ import { describe, it, expect, beforeEach, vi } from 'vitest'; import os from 'os'; import path from 'path'; import fs from 'fs'; /** * CROSS-PLATFORM COMPATIBILITY TESTS * * These tests verify that the application works correctly across: * - macOS (darwin) * - Windows (win32) * - Linux (linux) * * Testing areas: * - Binary path resolution * - File system operations * - Path handling * - Process spawning * - Platform-specific features */ describe('Cross-Platform Compatibility', () => { let currentPlatform; let mockPlatformInfo; beforeEach(() => { currentPlatform = process.platform; mockPlatformInfo = { platform: currentPlatform, arch: process.arch, homedir: os.homedir(), tmpdir: os.tmpdir(), pathSep: path.sep }; }); describe('Platform Detection and Binary Paths', () => { it('should detect current platform correctly', () => { const supportedPlatforms = ['darwin', 'win32', 'linux']; expect(supportedPlatforms).toContain(currentPlatform); }); it('should resolve correct binary paths for each platform', () => { const getBinaryPath = (binaryName, platform = currentPlatform) => { const extension = platform === 'win32' ? '.exe' : ''; return path.join('binaries', `${binaryName}${extension}`); }; // Test for current platform const ytDlpPath = getBinaryPath('yt-dlp'); const ffmpegPath = getBinaryPath('ffmpeg'); if (currentPlatform === 'win32') { expect(ytDlpPath).toBe('binaries\\yt-dlp.exe'); expect(ffmpegPath).toBe('binaries\\ffmpeg.exe'); } else { expect(ytDlpPath).toBe('binaries/yt-dlp'); expect(ffmpegPath).toBe('binaries/ffmpeg'); } // Test for all platforms expect(getBinaryPath('yt-dlp', 'win32')).toMatch(/\.exe$/); expect(getBinaryPath('yt-dlp', 'darwin')).not.toMatch(/\.exe$/); expect(getBinaryPath('yt-dlp', 'linux')).not.toMatch(/\.exe$/); }); it('should handle platform-specific path separators', () => { const createPath = (...segments) => path.join(...segments); const testPath = createPath('downloads', 'videos', 'test.mp4'); if (currentPlatform === 'win32') { expect(testPath).toMatch(/\\/); } else { expect(testPath).toMatch(/\//); } }); it('should resolve home directory correctly on all platforms', () => { const homeDir = os.homedir(); expect(homeDir).toBeTruthy(); expect(path.isAbsolute(homeDir)).toBe(true); // Platform-specific home directory patterns if (currentPlatform === 'win32') { expect(homeDir).toMatch(/^[A-Z]:\\/); } else { expect(homeDir).toMatch(/^\/.*\/[^/]+$/); } }); }); describe('File System Operations', () => { it('should handle file paths with different separators', () => { // Use path.join for cross-platform compatibility const testPaths = [ path.join('downloads', 'video.mp4'), path.join('downloads', 'subfolder', 'video.mp4') ]; testPaths.forEach(testPath => { const normalized = path.normalize(testPath); expect(normalized).toBeTruthy(); const parsed = path.parse(normalized); expect(parsed.name).toBe('video'); expect(parsed.ext).toBe('.mp4'); // The base name should be consistent regardless of path separators expect(parsed.base).toBe('video.mp4'); // Verify the path contains the expected directory expect(normalized).toMatch(/downloads/); }); }); it('should create directories with correct permissions', () => { const testDir = path.join(os.tmpdir(), 'grabzilla-test-' + Date.now()); try { fs.mkdirSync(testDir, { recursive: true }); expect(fs.existsSync(testDir)).toBe(true); const stats = fs.statSync(testDir); expect(stats.isDirectory()).toBe(true); // Check permissions (Unix-like systems) if (currentPlatform !== 'win32') { expect(stats.mode & 0o777).toBeGreaterThan(0); } } finally { // Cleanup if (fs.existsSync(testDir)) { fs.rmSync(testDir, { recursive: true, force: true }); } } }); it('should handle long file paths appropriately', () => { const longFileName = 'a'.repeat(200) + '.mp4'; const longPath = path.join(os.tmpdir(), longFileName); // Windows has path length limitations if (currentPlatform === 'win32') { expect(longPath.length).toBeLessThan(260); // Windows MAX_PATH } // Test path parsing with long names const parsed = path.parse(longPath); expect(parsed.ext).toBe('.mp4'); }); it('should handle special characters in file names', () => { const specialChars = { 'win32': ['<', '>', ':', '"', '|', '?', '*'], 'darwin': [':'], 'linux': [] }; const invalidChars = specialChars[currentPlatform] || []; const testFileName = 'test_video_with_special_chars.mp4'; // Verify our test filename doesn't contain invalid characters invalidChars.forEach(char => { expect(testFileName).not.toContain(char); }); // Test sanitization function const sanitizeFileName = (name) => { let sanitized = name; invalidChars.forEach(char => { sanitized = sanitized.replace(new RegExp(`\\${char}`, 'g'), '_'); }); return sanitized; }; const dirtyName = 'test