/** * CLI-Server Integration Tests * * Tests the full flow: start server, call tRPC from client, verify response. * These are INTEGRATION tests, not unit tests - they test the full stack. */ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { CoordinationServer } from '../../apps/server/server/index.js'; import { ProcessManager, ProcessRegistry } from '../../apps/server/process/index.js'; import { LogManager } from '../../apps/server/logging/index.js'; import { createEventBus } from '../../apps/server/events/index.js'; import { createTrpcClient } from '../../apps/server/cli/trpc-client.js'; import type { TrpcClient } from '../../apps/server/cli/trpc-client.js'; describe('CLI-Server Integration', () => { let server: CoordinationServer; let client: TrpcClient; let testPort: number; beforeAll(async () => { // Use a random port to avoid conflicts testPort = 30000 + Math.floor(Math.random() * 10000); // Create dependencies const registry = new ProcessRegistry(); const processManager = new ProcessManager(registry); const logManager = new LogManager(); const eventBus = createEventBus(); // Create and start server server = new CoordinationServer( { port: testPort, pidFile: `/tmp/cw-test-${testPort}.pid`, }, processManager, logManager, eventBus ); await server.start(); // Create client pointing to test server client = createTrpcClient(testPort); }); afterAll(async () => { await server.stop(); }); describe('health procedure', () => { it('should return health status with correct fields', async () => { const result = await client.health.query(); expect(result).toHaveProperty('status', 'ok'); expect(result).toHaveProperty('uptime'); expect(result).toHaveProperty('processCount'); expect(typeof result.uptime).toBe('number'); expect(typeof result.processCount).toBe('number'); }); it('should return increasing uptime on subsequent calls', async () => { const first = await client.health.query(); // Wait a small amount await new Promise((resolve) => setTimeout(resolve, 50)); const second = await client.health.query(); expect(second.uptime).toBeGreaterThanOrEqual(first.uptime); }); it('should return processCount of 0 initially', async () => { const result = await client.health.query(); expect(result.processCount).toBe(0); }); }); describe('status procedure', () => { it('should return server info with correct structure', async () => { const result = await client.status.query(); expect(result).toHaveProperty('server'); expect(result).toHaveProperty('processes'); expect(Array.isArray(result.processes)).toBe(true); }); it('should return server details with startedAt, uptime, and pid', async () => { const result = await client.status.query(); expect(result.server).toHaveProperty('startedAt'); expect(result.server).toHaveProperty('uptime'); expect(result.server).toHaveProperty('pid'); // startedAt should be an ISO string expect(typeof result.server.startedAt).toBe('string'); expect(() => new Date(result.server.startedAt)).not.toThrow(); // uptime should be a non-negative number expect(typeof result.server.uptime).toBe('number'); expect(result.server.uptime).toBeGreaterThanOrEqual(0); // pid should be a positive integer expect(typeof result.server.pid).toBe('number'); expect(result.server.pid).toBeGreaterThan(0); }); it('should return empty processes array initially', async () => { const result = await client.status.query(); expect(result.processes).toEqual([]); }); }); describe('error handling', () => { it('should throw when server is not running', async () => { // Create client pointing to wrong port const badClient = createTrpcClient(testPort + 1); await expect(badClient.health.query()).rejects.toThrow(); }); }); });