import { IPty, PtyEvent, IDisposable } from '../../src/types' /** * Mock IPty for testing. * * Implements the full IPty interface with manual trigger methods * (emitData, emitExit) and recording of calls (writes, resizes, killed). * * All properties are mutable for testing convenience. */ export interface MockIPty extends IPty { /** Recorded write() calls. */ writes: string[] /** Recorded resize() calls. */ resizes: Array<{ cols: number; rows: number }> /** Whether kill() was called. */ killed: boolean /** Manually trigger onData listeners. */ emitData(data: string): void /** Manually trigger onExit listeners. */ emitExit(exitCode: number, signal?: number): void } /** * Create a mock PTY for testing. * * pid, cols, rows are fixed but can be overridden via options for specific tests. */ export function createMockPty(options?: { pid?: number cols?: number rows?: number }): MockIPty { const pid = options?.pid ?? 12345 let cols = options?.cols ?? 80 let rows = options?.rows ?? 24 const writes: string[] = [] const resizes: Array<{ cols: number; rows: number }> = [] let killed = false // Event listeners: store arrays of listeners for each event type const dataListeners: Array<(data: string) => void> = [] const exitListeners: Array<(event: { exitCode: number; signal?: number }) => void> = [] const onData: PtyEvent = (listener: (e: string) => void): IDisposable => { dataListeners.push(listener) return { dispose() { const index = dataListeners.indexOf(listener) if (index !== -1) { dataListeners.splice(index, 1) } }, } } const onExit: PtyEvent<{ exitCode: number; signal?: number }> = ( listener: (e: { exitCode: number; signal?: number }) => void, ): IDisposable => { exitListeners.push(listener) return { dispose() { const index = exitListeners.indexOf(listener) if (index !== -1) { exitListeners.splice(index, 1) } }, } } const write = (data: string): void => { writes.push(data) } const resize = (newCols: number, newRows: number): void => { cols = newCols rows = newRows resizes.push({ cols: newCols, rows: newRows }) } const kill = (signal?: string): void => { killed = true } const emitData = (data: string): void => { for (const listener of dataListeners) { listener(data) } } const emitExit = (exitCode: number, signal?: number): void => { const event: { exitCode: number; signal?: number } = { exitCode } if (signal !== undefined) { event.signal = signal } for (const listener of exitListeners) { listener(event) } } return { pid, get cols() { return cols }, get rows() { return rows }, onData, onExit, write, resize, kill, writes, resizes, get killed() { return killed }, emitData, emitExit, } }