test(web): connect a Workspace in the e2e boot path and refresh goldens
The startup-selection flow leaves a fresh world (no Workspace) in the locked view state, so every e2e scenario that types into the composer now connects one first via the shared connectFreshWorkspace helper (hero picker create-by-name dialog; the default 'workspace' name keeps the session-header cwd assertions intact). Golden refreshes carry the current composer chrome: the plan/model control seats are empty until their owning plugins register (the seats shipped without occupants on this branch), the sidebar shows the connected workspace group pre-send, and the bash details material renders Input/code/Output as separate nodes. The cancel scenario polls the frozen-partial swap instead of counting synchronously — the abort frame reaches the browser over SSE after the host settles.
This commit is contained in:
@@ -23,7 +23,7 @@ import {
|
||||
assertFixtureInventory, captureStableAria, compareOrRefreshGolden, fixtureUserPrompts,
|
||||
launchWebScaffold, recordFixture, watchConsole, webSnapshotMode, type WebScaffold,
|
||||
} from './scaffold.ts'
|
||||
import { saveFailureShot } from './support.ts'
|
||||
import { connectFreshWorkspace, saveFailureShot } from './support.ts'
|
||||
|
||||
const SNAPSHOT_DIR = fileURLToPath(new URL('./snapshots/live-interactions', import.meta.url))
|
||||
const FIXTURE = join(SNAPSHOT_DIR, 'session.jsonl')
|
||||
@@ -94,6 +94,8 @@ describe('web e2e: live-turn interactions (cancel / error / retry)', () => {
|
||||
tripwire = watchConsole(page)
|
||||
await page.goto(scaffold.baseUrl, { waitUntil: 'load' })
|
||||
await page.waitForSelector('[class*="frame"]', { timeout: 30_000 })
|
||||
// Fresh world: connect a Workspace so the composer scenarios start live.
|
||||
await connectFreshWorkspace(page)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,9 +136,11 @@ describe('web e2e: live-turn interactions (cancel / error / retry)', () => {
|
||||
await page.getByRole('button', { name: 'Stop generating' }).click()
|
||||
await settled
|
||||
expect(turnEndReasons(sessionEvents).at(-1)).toBe('aborted')
|
||||
// Composer recovered; no streaming node lingers.
|
||||
// Composer recovered; no streaming node lingers. The host settled first
|
||||
// (awaited above), but the abort frame reaches the browser over SSE — the
|
||||
// frozen-partial swap is eventually consistent, so poll rather than count.
|
||||
await expect.poll(() => page.locator('textarea').first().isEnabled(), { timeout: 10_000 }).toBe(true)
|
||||
expect(await page.locator('[data-streaming="true"]').count()).toBe(0)
|
||||
await expect.poll(() => page.locator('[data-streaming="true"]').count(), { timeout: 10_000 }).toBe(0)
|
||||
// Golden of the aborted end-state: the prompt bubble plus the frozen
|
||||
// partial ('partial' is the hang entry's replayed prefix) and no more.
|
||||
const snapshot = await captureStableAria(page, '[class*="centerCol"]', scaffold!.workspaceCwd)
|
||||
|
||||
Reference in New Issue
Block a user