Files
orca/tests/e2e/golden-worktree-create-switch.spec.ts
Neil 72d61c459f fix(e2e): wait for terminal remount after golden worktree switch (#21837)
Mac release goldens failed after switching back to the original worktree:
sidebar aria-current landed while the store still pointed at the child tab,
so waitForActiveTerminalManager timed out. Wait for activeWorktreeId, force
the terminal tab visible, and restore this spec from the workflow ref so
older cut SHAs pick up the harness.
2026-09-20 14:28:03 -07:00

93 lines
3.9 KiB
TypeScript

import { openSidebarWorkspaceComposer } from './helpers/sidebar-project-dialog'
import type { Page } from '@stablyai/playwright-test'
import { expect, test } from './helpers/orca-app'
import {
ensureTerminalVisible,
getActiveWorktreeId,
waitForActiveWorktree,
waitForSessionReady
} from './helpers/store'
import { createTerminalTabFromMenu } from './helpers/terminal-tab-menu'
import {
execInTerminal,
waitForActivePanePtyId,
waitForActiveTerminalManager,
waitForTerminalOutput
} from './helpers/terminal'
import { splitMarkerEchoCommand } from './terminal-marker-echo-command'
import { waitForPtyShellEcho } from './terminal-pty-readiness'
async function createWorkspace(page: Page, name: string): Promise<void> {
await openSidebarWorkspaceComposer(page)
const dialog = page.getByRole('dialog', { name: /Create (Workspace|Worktree)/i })
await expect(dialog).toBeVisible()
await dialog.getByPlaceholder(/Type a name/i).fill(name)
await dialog.getByRole('button', { name: /Create (Workspace|Worktree)/i }).click()
await expect(dialog).toBeHidden({ timeout: 20_000 })
}
async function removeCreatedWorktree(page: Page, worktreeId: string): Promise<void> {
await page.evaluate(async (id) => {
await window.__store?.getState().removeWorktree(id, true)
}, worktreeId)
}
test('creates a worktree, keeps its terminal isolated, and switches back @golden', async ({
orcaPage
}) => {
test.setTimeout(180_000)
await waitForSessionReady(orcaPage)
const originalWorktreeId = await waitForActiveWorktree(orcaPage)
await waitForActiveTerminalManager(orcaPage, 30_000)
const parentPtyId = await waitForActivePanePtyId(orcaPage)
const workspaceName = `golden-switch-${Date.now()}`
let childWorktreeId: string | null = null
try {
await createWorkspace(orcaPage, workspaceName)
await expect(
orcaPage.locator('[role="option"][aria-current="page"]').filter({ hasText: workspaceName })
).toBeVisible({ timeout: 30_000 })
childWorktreeId = await waitForActiveWorktree(orcaPage)
// Why: the cleanup force-removes childWorktreeId, so it must never resolve to the original.
expect(childWorktreeId).not.toBe(originalWorktreeId)
await expect(
orcaPage.locator(`[role="option"][data-worktree-id="${childWorktreeId}"]`)
).toHaveAttribute('aria-current', 'page')
await createTerminalTabFromMenu(orcaPage)
await waitForActiveTerminalManager(orcaPage, 30_000)
const childPtyId = await waitForActivePanePtyId(orcaPage)
expect(childPtyId).not.toBe(parentPtyId)
await waitForPtyShellEcho(orcaPage, childPtyId, 15_000)
await execInTerminal(orcaPage, childPtyId, splitMarkerEchoCommand('worktree', '-b'))
await waitForTerminalOutput(orcaPage, 'worktree-b')
await orcaPage.locator(`[role="option"][data-worktree-id="${originalWorktreeId}"]`).click()
await expect(
orcaPage.locator(`[role="option"][data-worktree-id="${originalWorktreeId}"]`)
).toHaveAttribute('aria-current', 'page', { timeout: 20_000 })
// Why: sidebar aria-current can land before the store/terminal remount.
// Mac release goldens then wait 30s on a child tab whose PaneManager is gone.
await expect
.poll(() => getActiveWorktreeId(orcaPage), {
timeout: 20_000,
message: 'store did not activate the original worktree after sidebar click'
})
.toBe(originalWorktreeId)
await ensureTerminalVisible(orcaPage)
await waitForActiveTerminalManager(orcaPage, 30_000)
expect(await waitForActivePanePtyId(orcaPage, 30_000)).toBe(parentPtyId)
} finally {
if (childWorktreeId) {
if ((await getActiveWorktreeId(orcaPage).catch(() => null)) !== originalWorktreeId) {
await orcaPage
.locator(`[role="option"][data-worktree-id="${originalWorktreeId}"]`)
.click()
.catch(() => undefined)
}
await removeCreatedWorktree(orcaPage, childWorktreeId).catch(() => undefined)
}
}
})