| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
- import { EventEmitter } from 'node:events'
- import type { Readable, Writable } from 'node:stream'
- import { describe, expect, it, vi } from 'vitest'
- import type { Context } from 'cordis'
- import type { StdioRuntime } from '../src/index.ts'
- const createInterface = vi.hoisted(() => vi.fn(() => {
- const reader = new EventEmitter() as EventEmitter & { close(): void }
- reader.close = vi.fn()
- return reader
- }))
- vi.mock('node:readline', () => ({ createInterface }))
- function fakeContext(): Context {
- return {
- on: vi.fn(() => vi.fn()),
- effect: vi.fn((callback: () => () => void) => callback()),
- // The UI seeds its root target from the registry at install; this suite only
- // exercises readline terminal-mode selection, so an empty roster suffices.
- agents: { roots: vi.fn(() => []) },
- userInteraction: { registerProvider: vi.fn(() => vi.fn()) },
- } as unknown as Context
- }
- function fakeRuntime(inputIsTTY: boolean, outputIsTTY: boolean): StdioRuntime {
- return {
- input: { isTTY: inputIsTTY } as Readable & { isTTY: boolean },
- output: { isTTY: outputIsTTY, write: vi.fn(() => true) } as unknown as Writable & { isTTY: boolean },
- exit: vi.fn(),
- }
- }
- describe('createStdioChat readline mode', () => {
- it('enables terminal editing only when both stdio streams are TTYs', async () => {
- const { createStdioChat } = await import('../src/index.ts')
- const tty = fakeRuntime(true, true)
- createStdioChat(fakeContext(), {}, tty)
- expect(createInterface).toHaveBeenLastCalledWith({
- input: tty.input,
- output: tty.output,
- terminal: true,
- })
- const piped = fakeRuntime(true, false)
- createStdioChat(fakeContext(), {}, piped)
- expect(createInterface).toHaveBeenLastCalledWith({
- input: piped.input,
- output: piped.output,
- terminal: false,
- })
- })
- })
|