import { describe, it, expect, vi, afterEach } from 'vitest'; import * as net from 'node:net'; import type { Logger } from 'pino'; import type { Adapter, AdapterContext, Metrics, Position } from '../../src/core/types.js'; import { startServer } from '../../src/core/server.js'; function makeMockContext(): AdapterContext { const logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), child: vi.fn().mockReturnThis(), } as unknown as Logger; const metrics: Metrics = { inc: vi.fn(), observe: vi.fn(), }; return { publish: vi.fn(async (_p: Position) => {}), logger, metrics, }; } describe('startServer', () => { const servers: net.Server[] = []; afterEach(() => { for (const server of servers) { server.close(); } servers.length = 0; }); it('invokes handleSession with a real socket when a client connects', async () => { const handleSession = vi.fn().mockResolvedValue(undefined); const adapter: Adapter = { name: 'test-adapter', ports: [0], // port 0 = OS-assigned ephemeral port handleSession, }; const ctx = makeMockContext(); const server = startServer(0, adapter, ctx); servers.push(server); // Wait for the server to start listening const port = await new Promise((resolve) => { server.on('listening', () => { const addr = server.address(); resolve(typeof addr === 'object' && addr !== null ? addr.port : 0); }); }); // Connect a client const client = new net.Socket(); client.connect(port, '127.0.0.1'); // Wait for handleSession to be called await vi.waitFor(() => expect(handleSession).toHaveBeenCalledOnce(), { timeout: 2000 }); const [socketArg, ctxArg] = handleSession.mock.calls[0] as [net.Socket, AdapterContext]; expect(socketArg).toBeInstanceOf(net.Socket); expect(ctxArg).toBeDefined(); expect(typeof ctxArg.publish).toBe('function'); expect(ctxArg.logger).toBeDefined(); client.destroy(); }); });