From f016d38e9cfde1edd75208e3dad91149425cf22f Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sat, 19 Sep 2026 13:00:46 -0700 Subject: [PATCH] test(e2e): prove Pi EOF removes sidebar agent row (#21722) --- .../pty-connection-pty-exit-teardown.test.ts | 19 +++++++ .../e2e/issue-12907-pi-eof-agent-row.spec.ts | 52 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 tests/e2e/issue-12907-pi-eof-agent-row.spec.ts diff --git a/src/renderer/src/components/terminal-pane/pty-connection-pty-exit-teardown.test.ts b/src/renderer/src/components/terminal-pane/pty-connection-pty-exit-teardown.test.ts index fd5b1a7538c..4497bf604d9 100644 --- a/src/renderer/src/components/terminal-pane/pty-connection-pty-exit-teardown.test.ts +++ b/src/renderer/src/components/terminal-pane/pty-connection-pty-exit-teardown.test.ts @@ -855,6 +855,25 @@ describe('connectPanePty', () => { expect(manager.closePane).toHaveBeenCalledWith(2) }) + it('removes the agent row when an established PTY exits through EOF (#12907)', async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-pane-2') + transportFactoryQueue.push(transport) + const manager = createManager(2) + const deps = createDeps({ + restoredLeafId: LEAF_2, + paneTransportsRef: { current: new Map([[1, createMockTransport('pty-pane-1')]]) } + }) + + connectPanePty(createPane(2) as never, manager as never, deps as never) + const onPtyExit = createdTransportOptions[0]?.onPtyExit as ((ptyId: string) => void) | undefined + expect(onPtyExit).toBeTypeOf('function') + + onPtyExit?.('pty-pane-2') + + expect(mockStoreState.removeAgentStatus).toHaveBeenCalledWith(makePaneKey('tab-1', LEAF_2)) + }) + it('closes a split pane when an established PTY exits after terminal input', async () => { const { connectPanePty } = await import('./pty-connection') const pane = createPane(2) diff --git a/tests/e2e/issue-12907-pi-eof-agent-row.spec.ts b/tests/e2e/issue-12907-pi-eof-agent-row.spec.ts new file mode 100644 index 00000000000..a85e41c0708 --- /dev/null +++ b/tests/e2e/issue-12907-pi-eof-agent-row.spec.ts @@ -0,0 +1,52 @@ +import { test, expect } from './helpers/orca-app' +import { ensureTerminalVisible, waitForActiveWorktree, waitForSessionReady } from './helpers/store' +import { + sendToTerminal, + waitForActivePanePtyId, + waitForActiveTerminalManager, + waitForTerminalOutput +} from './helpers/terminal' +import { + stageNodeScriptForTerminal, + type StagedTerminalNodeScript +} from './helpers/run-node-script-in-terminal' +import { worktreeRow } from './worktree-row-locators' + +test('Pi EOF removes the completed agent row from the live Electron sidebar (#12907)', async ({ + orcaPage +}, testInfo) => { + await waitForSessionReady(orcaPage) + const worktreeId = await waitForActiveWorktree(orcaPage) + await ensureTerminalVisible(orcaPage) + await waitForActiveTerminalManager(orcaPage) + const ptyId = await waitForActivePanePtyId(orcaPage) + await orcaPage.evaluate(() => { + const state = window.__store?.getState() + if (!state) { + throw new Error('window.__store is unavailable') + } + state.setAgentActivityDisplayMode('full') + if (!state.worktreeCardProperties.includes('inline-agents')) { + state.toggleWorktreeCardProperty('inline-agents') + } + }) + + const script: StagedTerminalNodeScript = stageNodeScriptForTerminal( + "process.stdout.write('PI_EOF_AGENT_READY\\r\\n\\x1b]0;Pi\\x07'); process.stdin.resume(); process.stdin.on('end', () => process.exit(0))" + ) + // Keep the shell from becoming the surviving process after the child accepts + // EOF. The queued `exit` runs after node exits, on POSIX shells used here. + await sendToTerminal(orcaPage, ptyId, `${script.command}; exit\r`) + try { + await waitForTerminalOutput(orcaPage, 'PI_EOF_AGENT_READY', 15_000) + const agentRows = worktreeRow(orcaPage, worktreeId).locator('[aria-label="Agents"] > div') + await expect(agentRows).toHaveCount(1) + await orcaPage.screenshot({ path: testInfo.outputPath('pi-row-before-eof.png') }) + + await sendToTerminal(orcaPage, ptyId, '\u0004') + await expect(agentRows).toHaveCount(0, { timeout: 15_000 }) + await orcaPage.screenshot({ path: testInfo.outputPath('pi-row-after-eof.png') }) + } finally { + script.cleanup() + } +})