mirror of
https://github.com/stablyai/orca.git
synced 2026-09-23 08:02:31 +00:00
* test(e2e): add golden E2E tests for workspace session management - Restore exact file and terminal state after quit/relaunch - Verify terminal file link activation and external edit detection - Test worktree creation and switching with isolated terminals - Isolate test repo paths between concurrent CI runs with UUIDs * Add platform-aware marker echo command utility - Create splitMarkerEchoCommand() to generate shell commands that safely echo test markers across Windows and Unix platforms - Split markers into prefix/suffix fragments so output assertions prove execution, not just shell echo-back - Consolidate SORTABLE_TAB export and improve tab bar locator logic - Refactor terminal link helpers to extract client point calculation
78 lines
3.4 KiB
TypeScript
78 lines
3.4 KiB
TypeScript
import type { Page } from '@stablyai/playwright-test'
|
|
import { expect, test } from './helpers/orca-app'
|
|
import { 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 page.getByRole('button', { name: 'New workspace', exact: true }).click()
|
|
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 })
|
|
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)
|
|
}
|
|
}
|
|
})
|