const DependencyChecker = require('./dependency-checker'); const { exec } = require('child_process'); // Mock child_process jest.mock('child_process'); describe('DependencyChecker', () => { let checker; beforeEach(() => { checker = new DependencyChecker(); jest.clearAllMocks(); // Default: commands fail (prevents hanging when unmocked calls occur) exec.mockImplementation((cmd, opts, callback) => { callback(new Error('command not found'), { stdout: '', stderr: 'command not found' }); }); }); describe('checkDocker', () => { test('detects Docker installed and running', async () => { // Mock successful docker --version exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: 'Docker version 24.0.7, build afdd53b', stderr: '' }); }); // Mock successful docker info exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: 'Server Version: 24.0.7', stderr: '' }); }); const result = await checker.checkDocker(); expect(result.installed).toBe(true); expect(result.running).toBe(true); expect(result.version).toBe('24.0.7'); }); test('detects Docker installed but not running', async () => { // Mock successful docker --version exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: 'Docker version 24.0.7, build afdd53b', stderr: '' }); }); // Mock failed docker info exec.mockImplementationOnce((cmd, opts, callback) => { callback(new Error('Cannot connect to Docker daemon'), { stdout: '', stderr: 'Cannot connect' }); }); const result = await checker.checkDocker(); expect(result.installed).toBe(true); expect(result.running).toBe(false); expect(result.version).toBe('24.0.7'); }); test('detects Docker not installed', async () => { // Mock failed docker --version exec.mockImplementationOnce((cmd, opts, callback) => { callback(new Error('command not found'), { stdout: '', stderr: 'command not found' }); }); const result = await checker.checkDocker(); expect(result.installed).toBe(false); expect(result.running).toBe(false); expect(result.version).toBeNull(); }); }); describe('checkCaddy', () => { test('detects Caddy installed', async () => { // Mock successful caddy version exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: 'v2.7.6 h1:w0NymbG2m9PcvKWsrXO6EEkY9Ru4FJK8uQbYcev1p3A=', stderr: '' }); }); // Mock successful which/where caddy exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: '/usr/bin/caddy', stderr: '' }); }); const result = await checker.checkCaddy(); expect(result.installed).toBe(true); expect(result.version).toBe('2.7.6'); expect(result.path).toBe('/usr/bin/caddy'); }); test('detects Caddy not installed', async () => { // Mock failed caddy version exec.mockImplementationOnce((cmd, opts, callback) => { callback(new Error('command not found'), { stdout: '', stderr: 'command not found' }); }); const result = await checker.checkCaddy(); expect(result.installed).toBe(false); expect(result.version).toBeNull(); expect(result.path).toBeNull(); }); }); describe('getDockerInstallInstructions', () => { test('returns Windows instructions', () => { const instructions = checker.getDockerInstallInstructions('windows'); expect(instructions.title).toContain('Windows'); expect(instructions.steps).toBeInstanceOf(Array); expect(instructions.steps.length).toBeGreaterThan(0); expect(instructions.requiresWSL2).toBe(true); expect(instructions.url).toContain('docker.com'); }); test('returns macOS instructions', () => { const instructions = checker.getDockerInstallInstructions('macos'); expect(instructions.title).toContain('Mac'); expect(instructions.steps).toBeInstanceOf(Array); expect(instructions.requiresWSL2).toBe(false); expect(instructions.url).toContain('docker.com'); }); test('returns Linux instructions', () => { const instructions = checker.getDockerInstallInstructions('linux'); expect(instructions.title).toContain('Linux'); expect(instructions.steps).toBeInstanceOf(Array); expect(instructions.packageManagers).toBeDefined(); expect(instructions.packageManagers.ubuntu).toBeDefined(); }); }); describe('getCaddyInstallInstructions', () => { test('returns Windows instructions', () => { const instructions = checker.getCaddyInstallInstructions('windows'); expect(instructions.title).toContain('Windows'); expect(instructions.steps).toBeInstanceOf(Array); expect(instructions.automated).toBe(false); expect(instructions.url).toContain('caddyserver.com'); }); test('returns macOS instructions with automation', () => { const instructions = checker.getCaddyInstallInstructions('macos'); expect(instructions.title).toContain('macOS'); expect(instructions.automated).toBe(true); expect(instructions.command).toBe('brew install caddy'); }); test('returns Linux instructions with package managers', () => { const instructions = checker.getCaddyInstallInstructions('linux'); expect(instructions.title).toContain('Linux'); expect(instructions.automated).toBe(true); expect(instructions.packageManagers).toBeDefined(); expect(instructions.packageManagers.ubuntu).toBeDefined(); expect(instructions.packageManagers.fedora).toBeDefined(); }); }); describe('installDocker', () => { test('returns manual installation instructions', async () => { const result = await checker.installDocker('windows'); expect(result.success).toBe(false); expect(result.automated).toBe(false); expect(result.instructions).toBeDefined(); expect(result.message).toContain('manual'); }); }); describe('installCaddy', () => { test('returns manual instructions for Windows', async () => { const result = await checker.installCaddy('windows'); expect(result.success).toBe(false); expect(result.automated).toBe(false); expect(result.instructions).toBeDefined(); }); test('attempts automated installation on macOS', async () => { // Mock successful brew install exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: 'Caddy installed', stderr: '' }); }); // Mock successful caddy version check exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: 'v2.7.6', stderr: '' }); }); // Mock successful which caddy exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: '/usr/local/bin/caddy', stderr: '' }); }); const result = await checker.installCaddy('macos'); expect(result.automated).toBe(true); // Note: success depends on mocked execution }); }); describe('executeCommand', () => { test('executes command successfully', async () => { exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: 'success', stderr: '' }); }); const result = await checker.executeCommand('test command'); expect(result.success).toBe(true); expect(result.stdout).toBe('success'); }); test('handles command failure', async () => { const error = new Error('command failed'); error.stderr = 'error message'; exec.mockImplementationOnce((cmd, opts, callback) => { callback(error); }); const result = await checker.executeCommand('test command'); expect(result.success).toBe(false); expect(result.stderr).toContain('error'); }); }); describe('detectLinuxDistro', () => { test('detects Ubuntu', async () => { exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: 'ID=ubuntu\nNAME="Ubuntu"', stderr: '' }); }); const distro = await checker.detectLinuxDistro(); expect(distro).toBe('ubuntu'); }); test('detects Fedora', async () => { exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: 'ID=fedora\nNAME="Fedora"', stderr: '' }); }); const distro = await checker.detectLinuxDistro(); expect(distro).toBe('fedora'); }); test('returns unknown for unrecognized distro', async () => { exec.mockImplementationOnce((cmd, opts, callback) => { callback(null, { stdout: 'ID=unknown', stderr: '' }); }); const distro = await checker.detectLinuxDistro(); expect(distro).toBe('unknown'); }); }); });