import { describe, expect, it } from 'bun:test'; import type { CLIProxyBackend } from '../../../src/cliproxy/types'; import { installDashboardCliproxyVersion, type DashboardCliproxyInstallResult, } from '../../../src/web-server/services/cliproxy-dashboard-install-service'; function createDeps( overrides: { sessionRunning?: boolean; remoteRunning?: boolean; startResult?: { started: boolean; alreadyRunning: boolean; port: number; error?: string }; } = {} ) { const calls = { isCliproxyRunning: 0, installCliproxyVersion: 0, ensureCliproxyService: 0, }; const deps = { getProxyStatus: () => ({ running: overrides.sessionRunning ?? false }), isCliproxyRunning: async () => { calls.isCliproxyRunning += 1; return overrides.remoteRunning ?? false; }, installCliproxyVersion: async ( _version: string, _verbose?: boolean, _backend?: CLIProxyBackend ) => { calls.installCliproxyVersion += 1; }, ensureCliproxyService: async () => { calls.ensureCliproxyService += 1; return ( overrides.startResult ?? { started: true, alreadyRunning: false, port: 8317, } ); }, }; return { deps, calls }; } describe('installDashboardCliproxyVersion', () => { it('restarts the proxy after install when it was already running', async () => { const { deps, calls } = createDeps({ sessionRunning: true }); const result = await installDashboardCliproxyVersion('6.7.1', 'plus', deps); expect(result).toEqual({ success: true, restarted: true, port: 8317, message: 'Successfully installed CLIProxy Plus v6.7.1 and restarted it on port 8317', }); expect(calls.isCliproxyRunning).toBe(0); expect(calls.installCliproxyVersion).toBe(1); expect(calls.ensureCliproxyService).toBe(1); }); it('keeps the proxy stopped after install when it was not running beforehand', async () => { const { deps, calls } = createDeps({ sessionRunning: false, remoteRunning: false }); const result = await installDashboardCliproxyVersion('6.7.1', 'plus', deps); expect(result).toEqual({ success: true, restarted: false, message: 'Successfully installed CLIProxy Plus v6.7.1', }); expect(calls.isCliproxyRunning).toBe(1); expect(calls.installCliproxyVersion).toBe(1); expect(calls.ensureCliproxyService).toBe(0); }); it('reports a restart failure after a successful install when the proxy had been running', async () => { const { deps, calls } = createDeps({ sessionRunning: false, remoteRunning: true, startResult: { started: false, alreadyRunning: false, port: 8317, error: 'Port 8317 is blocked by another process', }, }); const result = await installDashboardCliproxyVersion('6.7.1', 'original', deps); expect(result).toEqual({ success: false, restarted: false, error: 'Port 8317 is blocked by another process', message: 'Installed CLIProxy v6.7.1, but failed to restart it', }); expect(calls.isCliproxyRunning).toBe(1); expect(calls.installCliproxyVersion).toBe(1); expect(calls.ensureCliproxyService).toBe(1); }); it('uses a fallback restart error when the start result omits one', async () => { const { deps } = createDeps({ remoteRunning: true, startResult: { started: false, alreadyRunning: false, port: 8317, }, }); const result = await installDashboardCliproxyVersion('6.7.1', 'plus', deps); expect(result).toEqual({ success: false, restarted: false, error: 'Installed CLIProxy Plus v6.7.1, but restart failed', message: 'Installed CLIProxy Plus v6.7.1, but failed to restart it', }); }); });