diff --git a/tests/e2e/helpers/startup-exec-readiness-oracle.ts b/tests/e2e/helpers/startup-exec-readiness-oracle.ts index 577702c8ea0..7aa56e38863 100644 --- a/tests/e2e/helpers/startup-exec-readiness-oracle.ts +++ b/tests/e2e/helpers/startup-exec-readiness-oracle.ts @@ -9,6 +9,7 @@ import type { import { toWebTerminalSurfaceTabId } from '../../../src/shared/terminal-surface-id' import { expect } from './orca-app' import { getTerminalContent, waitForActivePanePtyId } from './terminal' +import { readFreshTerminalInventory } from './terminal-inventory-observation' const RECOVERY_DEADLINE_MS = 8_000 @@ -76,10 +77,6 @@ function count(text: string, marker: string): number { return text.split(marker).length - 1 } -function isTransientPtyLivenessError(error: unknown): boolean { - return error instanceof Error && error.message.includes('terminal_liveness_unavailable') -} - async function expectSingleOwningPty( page: Page, worktreeId: string, @@ -90,24 +87,15 @@ async function expectSingleOwningPty( await expect .poll( async () => { - try { - const listed = await callStartupExecRuntime( - page, - 'terminal.list', - { - worktree: `id:${worktreeId}`, - requireFreshPtyLiveness: true - } - ) - return listed.terminals - .filter((candidate) => candidate.tabId === tabId) - .map((candidate) => ({ handle: candidate.handle, ptyId: candidate.ptyId })) - } catch (error) { - if (isTransientPtyLivenessError(error)) { - return [] - } - throw error - } + const listed = await readFreshTerminalInventory(() => + callStartupExecRuntime(page, 'terminal.list', { + worktree: `id:${worktreeId}`, + requireFreshPtyLiveness: true + }) + ) + return (listed?.terminals ?? []) + .filter((candidate) => candidate.tabId === tabId) + .map((candidate) => ({ handle: candidate.handle, ptyId: candidate.ptyId })) }, { timeout: 30_000 } ) diff --git a/tests/e2e/helpers/terminal-inventory-observation.ts b/tests/e2e/helpers/terminal-inventory-observation.ts new file mode 100644 index 00000000000..0fcefdb23c8 --- /dev/null +++ b/tests/e2e/helpers/terminal-inventory-observation.ts @@ -0,0 +1,14 @@ +import type { RuntimeTerminalListResult } from '../../../src/shared/runtime-types' + +export async function readFreshTerminalInventory( + read: () => Promise +): Promise { + try { + return await read() + } catch (error) { + if (error instanceof Error && error.message.includes('terminal_liveness_unavailable')) { + return null + } + throw error + } +} diff --git a/tests/e2e/paired-remote-terminal-materialization-reconnect.spec.ts b/tests/e2e/paired-remote-terminal-materialization-reconnect.spec.ts index 64d6b6510d2..fda18fc74c6 100644 --- a/tests/e2e/paired-remote-terminal-materialization-reconnect.spec.ts +++ b/tests/e2e/paired-remote-terminal-materialization-reconnect.spec.ts @@ -16,6 +16,7 @@ import { launchPairedElectronClient } from './helpers/paired-electron-client' import { getTerminalContent, waitForActivePanePtyId } from './helpers/terminal' +import { readFreshTerminalInventory } from './helpers/terminal-inventory-observation' const scratch = mkdtempSync(path.join(os.tmpdir(), 'orca-paired-materialize-')) const fixturePath = path.join(scratch, 'materialize-terminal.mjs') @@ -316,18 +317,17 @@ async function runMaterializationJourney( await tab.click() await expect.poll(() => getTerminalContent(page), { timeout: 10_000 }).toContain(marker) - const listed = await callRuntime( - page, - environmentId, - 'terminal.list', - { - worktree: `id:${worktreeId}`, - requireFreshPtyLiveness: true - } - ) - expect( - listed.terminals.filter((terminal) => terminal.tabId === created.tab.parentTabId) - ).toHaveLength(1) + await expect + .poll(async () => { + const listed = await readFreshTerminalInventory(() => + callRuntime(page, environmentId, 'terminal.list', { + worktree: `id:${worktreeId}`, + requireFreshPtyLiveness: true + }) + ) + return listed?.terminals.filter((terminal) => terminal.tabId === created.tab.parentTabId) + }) + .toHaveLength(1) await callRuntime(page, environmentId, 'terminal.closeTab', { terminal: replacementHandle }) }