feat(01.1-06): update CLI status command and add integration tests
- Update status command to use tRPC client for server communication - Display health status, uptime, and process count - Handle connection errors gracefully with helpful message - Add 7 integration tests proving full CLI-server tRPC flow - Tests cover health procedure, status procedure, and error handling
This commit is contained in:
@@ -11,6 +11,7 @@ import { CoordinationServer } from '../server/index.js';
|
||||
import { GracefulShutdown } from '../server/shutdown.js';
|
||||
import { ProcessManager, ProcessRegistry } from '../process/index.js';
|
||||
import { LogManager } from '../logging/index.js';
|
||||
import { createDefaultTrpcClient } from './trpc-client.js';
|
||||
|
||||
/** Environment variable for custom port */
|
||||
const CW_PORT_ENV = 'CW_PORT';
|
||||
@@ -77,12 +78,23 @@ export function createCli(serverHandler?: (port?: number) => Promise<void>): Com
|
||||
}
|
||||
});
|
||||
|
||||
// Placeholder commands - will be implemented in later phases
|
||||
// Status command - shows workspace status via tRPC
|
||||
program
|
||||
.command('status')
|
||||
.description('Show workspace status')
|
||||
.action(() => {
|
||||
console.log('cw status: not implemented');
|
||||
.action(async () => {
|
||||
try {
|
||||
const client = createDefaultTrpcClient();
|
||||
const health = await client.health.query();
|
||||
|
||||
console.log('Coordination Server Status');
|
||||
console.log('==========================');
|
||||
console.log(`Status: ${health.status}`);
|
||||
console.log(`Uptime: ${health.uptime}s`);
|
||||
console.log(`Processes: ${health.processCount}`);
|
||||
} catch {
|
||||
console.log('Server not running or unreachable. Start with: cw --server');
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
|
||||
123
tests/integration/cli-server.test.ts
Normal file
123
tests/integration/cli-server.test.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* 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 '../../src/server/index.js';
|
||||
import { ProcessManager, ProcessRegistry } from '../../src/process/index.js';
|
||||
import { LogManager } from '../../src/logging/index.js';
|
||||
import { createEventBus } from '../../src/events/index.js';
|
||||
import { createTrpcClient } from '../../src/cli/trpc-client.js';
|
||||
import type { TrpcClient } from '../../src/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();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user