import type { Handshake, WsServerCallbacks, WsServerFactory, WsServerLike, WsServerStartOptions, WsServerStartResult, WsSocketLike, } from "../../src/types/types.js"; /** * In-memory deterministic `WsServerLike` implementation. The * production wiring binds the real `ws.WebSocketServer`, but unit * tests + the `tests/integration.test.ts` 3-client scenario drive * lifecycle events through this real-implementation fake. Per the * CLAUDE.md "no mocks" rule, the daemon never sees `vi.mock` — only * an alternative concrete implementation. */ export class FakeWsServer implements WsServerLike { public started = false; public stopped = false; public lastStartOptions: WsServerStartOptions | undefined; public callbacks: WsServerCallbacks | undefined; public boundAddress = "127.0.0.1"; public boundPort = 0; public startError: Error | undefined; private readonly sockets = new Map(); public async start( options: WsServerStartOptions ): Promise { if (this.startError) throw this.startError; this.lastStartOptions = options; this.callbacks = options.callbacks; this.started = true; return { address: this.boundAddress, port: this.boundPort }; } public async stop(): Promise { this.stopped = true; for (const id of [...this.sockets.keys()]) this.disconnect(id, 1001, "stop"); } public async closeAll(code = 1001, reason = "shutdown"): Promise { for (const id of [...this.sockets.keys()]) this.disconnect(id, code, reason); } /** Test affordance: simulate a new client connecting. */ public connect(id: string, handshake?: Partial): FakeWsSocket { const socket = new FakeWsSocket(id, () => this.disconnect(id, 1000, "client-close") ); this.sockets.set(id, socket); const h: Handshake = { headers: handshake?.headers ?? {}, remoteAddress: handshake?.remoteAddress, url: handshake?.url ?? "/", query: handshake?.query ?? {}, }; this.callbacks?.onConnection(socket, h); return socket; } public disconnect(id: string, code = 1000, reason = "close"): void { const socket = this.sockets.get(id); if (!socket) return; this.sockets.delete(id); socket.closed = true; this.callbacks?.onClose(id, code, reason); } public message(id: string, payload: string): void { this.callbacks?.onMessage(id, payload); } public errorOn(id: string, err: Error): void { this.callbacks?.onError(id, err); } public getSocket(id: string): FakeWsSocket | undefined { return this.sockets.get(id); } public socketCount(): number { return this.sockets.size; } } export class FakeWsSocket implements WsSocketLike { public readonly id: string; public readonly sent: string[] = []; public closed = false; public readonly remoteAddress = "127.0.0.1"; private readonly onClose: () => void; public constructor(id: string, onClose: () => void) { this.id = id; this.onClose = onClose; } public send(payload: string): void { if (!this.closed) this.sent.push(payload); } public close(): void { if (this.closed) return; this.closed = true; this.onClose(); } } /** Factory producing a fresh `FakeWsServer` per construction. */ export function makeFakeWsServerFactory(): { readonly instances: FakeWsServer[]; readonly factory: WsServerFactory; } { const instances: FakeWsServer[] = []; return { instances, factory: () => { const inst = new FakeWsServer(); instances.push(inst); return inst; }, }; }