import type { HookEvent } from '../src/types.js'; import startupCheckerHandler from '../hooks/startup-checker/handler.js'; function makeStartupEvent(cfg: Record): HookEvent { return { type: 'gateway', action: 'startup', sessionKey: 'test-session', timestamp: new Date(), messages: [], context: { cfg }, }; } interface TestCase { name: string; test: () => Promise; } const TEST_CASES: TestCase[] = [ { name: 'Reports fail when auth mode is none', test: async () => { const event = makeStartupEvent({ gateway: { auth: { mode: 'none' }, bind: 'loopback', port: 3000 }, agents: { defaults: { sandbox: { mode: 'docker' } } }, hooks: { internal: { enabled: true } }, approvals: { exec: { enabled: true } }, }); await startupCheckerHandler(event); return event.messages.some((m) => m.includes('Auth Mode') && m.includes('none')); }, }, { name: 'Passes when auth is properly configured', test: async () => { const event = makeStartupEvent({ gateway: { auth: { mode: 'token', token: 'test-token', rateLimit: { maxAttempts: 5 }, }, bind: 'loopback', port: 3000, }, agents: { defaults: { sandbox: { mode: 'docker' } } }, hooks: { internal: { enabled: true } }, approvals: { exec: { enabled: true } }, }); await startupCheckerHandler(event); const report = event.messages[0] ?? ''; return report.includes('100/100') || report.includes('✅'); }, }, { name: 'Warns when bind is lan', test: async () => { const event = makeStartupEvent({ gateway: { auth: { mode: 'token', token: 'x' }, bind: 'lan', }, }); await startupCheckerHandler(event); return event.messages.some((m) => m.includes('Network Binding') && m.includes('lan')); }, }, { name: 'Handles empty config gracefully', test: async () => { const event = makeStartupEvent({}); await startupCheckerHandler(event); return event.messages.length > 0; // Should still produce a report }, }, { name: 'Uses deep config paths not flat', test: async () => { // Old flat config paths should NOT produce pass results const event = makeStartupEvent({ authMode: 'token', authToken: 'xxx', bind: 'loopback', sandboxMode: 'docker', }); await startupCheckerHandler(event); // Auth mode should fail because gateway.auth.mode is undefined return event.messages.some((m) => m.includes('not configured')); }, }, { name: 'Skips non-startup events', test: async () => { const event: HookEvent = { type: 'message', action: 'received', sessionKey: 'test', timestamp: new Date(), messages: [], context: { content: 'hello' }, }; await startupCheckerHandler(event); return event.messages.length === 0; }, }, ]; export async function runStartupCheckerTests(): Promise<{ suite: string; passed: number; failed: number; errors: string[]; }> { let passed = 0; let failed = 0; const errors: string[] = []; for (const tc of TEST_CASES) { try { const ok = await tc.test(); if (ok) { passed++; } else { failed++; errors.push(`[${tc.name}] assertion failed`); } } catch (err) { failed++; errors.push(`[${tc.name}] threw: ${err instanceof Error ? err.message : String(err)}`); } } return { suite: 'Startup Checker', passed, failed, errors }; }