Files
orca/tests/e2e/golden-worktree-create-switch.spec.ts
T

88 lines
3.7 KiB
TypeScript

import { removeWorktreeViaStore } from './helpers/dead-terminal'
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 })
}
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 removeWorktreeViaStore(orcaPage, childWorktreeId)
}
}
})