test(terminal): reproduce Fish readiness ESC loss

This commit is contained in:
Jinwoo-H
2026-08-12 22:21:23 -04:00
parent 150cc6f50c
commit 79aaddd566
2 changed files with 41 additions and 0 deletions
+24
View File
@@ -1,5 +1,6 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { SESSION_FORCE_KILL_RETRY_MS, Session } from './session'
import { HeadlessEmulator } from './headless-emulator'
import type { SessionState, ShellReadyState } from './types'
import type { TuiAgent } from '../../shared/types'
@@ -430,6 +431,29 @@ describe('Session', () => {
expect(session.getSnapshot()?.snapshotAnsi).not.toContain('orca-shell-ready')
})
it.each([
['after the ready marker', ['\x1b]777;orca-shell-ready\x07', '\x1b[?2004hfish> ']],
['after the ESC introducer', ['\x1b]777;orca-shell-ready\x07\x1b', '[?2004hfish> ']]
])('preserves Fish bracketed-paste output split %s', (_boundary, chunks) => {
createSession({ shellReadySupported: true })
const received: string[] = []
session.attachClient({
onData: (data) => received.push(data),
onExit: () => {}
})
for (const chunk of chunks) {
subprocess.simulateData(chunk)
}
const output = received.join('')
expect(output).toBe('\x1b[?2004hfish> ')
const rendered = new HeadlessEmulator({ cols: 80, rows: 24 })
expect(rendered.writeSync(output)).toBe(true)
expect(rendered.getVisibleLines().join('\n')).not.toContain('[?2004h')
rendered.dispose()
})
it('publishes an absolute output sequence with live snapshots', () => {
createSession()
subprocess.simulateData('first')
@@ -658,6 +658,23 @@ describe('LocalPtyProvider', () => {
}
})
it.each([
['after the ready marker', ['\x1b]777;orca-shell-ready\x07', '\x1b[?2004hfish> ']],
['after the ESC introducer', ['\x1b]777;orca-shell-ready\x07\x1b', '[?2004hfish> ']]
])('preserves Fish bracketed-paste output split %s', async (_boundary, chunks) => {
process.env.SHELL = '/usr/bin/fish'
const received: string[] = []
provider.configure({ onData: (_id, data) => received.push(data) })
await provider.spawn({ cols: 80, rows: 24, command: 'printf ready' })
const dataCallback = mockProc.onData.mock.calls[0]?.[0] as (data: string) => void
for (const chunk of chunks) {
dataCallback(chunk)
}
expect(received.join('')).toBe('\x1b[?2004hfish> ')
})
it('releases held marker-prefix bytes when local shell readiness times out', async () => {
vi.useFakeTimers()
const onData = vi.fn()