readline.spec.ts 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import { EventEmitter } from 'node:events'
  2. import type { Readable, Writable } from 'node:stream'
  3. import { describe, expect, it, vi } from 'vitest'
  4. import type { Context } from 'cordis'
  5. import type { StdioRuntime } from '../src/index.ts'
  6. const createInterface = vi.hoisted(() => vi.fn(() => {
  7. const reader = new EventEmitter() as EventEmitter & { close(): void }
  8. reader.close = vi.fn()
  9. return reader
  10. }))
  11. vi.mock('node:readline', () => ({ createInterface }))
  12. function fakeContext(): Context {
  13. return {
  14. on: vi.fn(() => vi.fn()),
  15. effect: vi.fn((callback: () => () => void) => callback()),
  16. // The UI seeds its root target from the registry at install; this suite only
  17. // exercises readline terminal-mode selection, so an empty roster suffices.
  18. agents: { roots: vi.fn(() => []) },
  19. userInteraction: { registerProvider: vi.fn(() => vi.fn()) },
  20. } as unknown as Context
  21. }
  22. function fakeRuntime(inputIsTTY: boolean, outputIsTTY: boolean): StdioRuntime {
  23. return {
  24. input: { isTTY: inputIsTTY } as Readable & { isTTY: boolean },
  25. output: { isTTY: outputIsTTY, write: vi.fn(() => true) } as unknown as Writable & { isTTY: boolean },
  26. exit: vi.fn(),
  27. }
  28. }
  29. describe('createStdioChat readline mode', () => {
  30. it('enables terminal editing only when both stdio streams are TTYs', async () => {
  31. const { createStdioChat } = await import('../src/index.ts')
  32. const tty = fakeRuntime(true, true)
  33. createStdioChat(fakeContext(), {}, tty)
  34. expect(createInterface).toHaveBeenLastCalledWith({
  35. input: tty.input,
  36. output: tty.output,
  37. terminal: true,
  38. })
  39. const piped = fakeRuntime(true, false)
  40. createStdioChat(fakeContext(), {}, piped)
  41. expect(createInterface).toHaveBeenLastCalledWith({
  42. input: piped.input,
  43. output: piped.output,
  44. terminal: false,
  45. })
  46. })
  47. })