test(e2e): fix failures and improve stability (#23480)

- Narrow toolbar width and set window minimums for consistent testing
- Add node_modules symlink to fixture for ESM import resolution
- Exercise manual paging and fix button selector
- Preserve repo filters in reveal workflow
- Adjust timing strategy and increase test timeout
This commit is contained in:
Jinjing
2026-09-27 16:17:06 -07:00
committed by GitHub
parent fb51e6cb4c
commit 29847641ab
6 changed files with 48 additions and 14 deletions
@@ -24,8 +24,8 @@ import { BROWSER_ADDRESS_BAR_MIN_INLINE_WIDTH } from '../../src/renderer/src/com
// the middle of that band rather than a fixed window width, because how much
// chrome flanks the pane (left sidebar, and a right sidebar that other startup
// paths may re-open) varies between runs.
const TARGET_TOOLBAR_WIDTH = 420
const MIN_USABLE_TOOLBAR_WIDTH = BROWSER_ADDRESS_BAR_MIN_INLINE_WIDTH + 100
const TARGET_TOOLBAR_WIDTH = 260
const MIN_USABLE_TOOLBAR_WIDTH = BROWSER_ADDRESS_BAR_MIN_INLINE_WIDTH + 20
const NARROW_WINDOW_HEIGHT = 800
async function startDestinationServer(): Promise<{ url: string; close: () => Promise<void> }> {
@@ -62,6 +62,8 @@ async function setWindowWidth(electronApp: ElectronApplication, width: number):
if (!window) {
throw new Error('No Electron window')
}
// Window minimums otherwise mask the narrow-pane state on some runners.
window.setMinimumSize(0, 0)
window.setSize(size.width, size.height)
},
{ width: Math.round(width), height: NARROW_WINDOW_HEIGHT }
@@ -118,8 +120,11 @@ async function settleToSqueezedRestingState(
// Chrome flanking the pane is everything the toolbar didn't get.
await setWindowWidth(electronApp, innerWidth - toolbar + TARGET_TOOLBAR_WIDTH)
await addressBarInput(page).evaluate((node) => node.blur())
const measuredToolbar = await toolbarWidth(page)
return {
toolbar: (await toolbarWidth(page)) > MIN_USABLE_TOOLBAR_WIDTH,
toolbar:
measuredToolbar > MIN_USABLE_TOOLBAR_WIDTH &&
measuredToolbar <= TARGET_TOOLBAR_WIDTH + 5,
collapsed: (await addressBarOverlay(page).count()) === 0
}
},
@@ -1,4 +1,12 @@
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import {
existsSync,
mkdirSync,
mkdtempSync,
readFileSync,
rmSync,
symlinkSync,
writeFileSync
} from 'node:fs'
import { homedir, tmpdir } from 'node:os'
import path from 'node:path'
import { build } from 'esbuild'
@@ -109,6 +117,12 @@ export async function createDaemonGenerationRuntime(
const reconnectClientEntryPath = path.join(rootDir, 'daemon-generation-reconnect-client.cjs')
const legacyCloseClientEntryPath = path.join(rootDir, 'daemon-generation-legacy-close-client.cjs')
const repoRoot = process.cwd()
// ESM imports in the bundled fixture resolve from its temp directory, not NODE_PATH.
symlinkSync(
path.join(repoRoot, 'node_modules'),
path.join(rootDir, 'node_modules'),
process.platform === 'win32' ? 'junction' : 'dir'
)
await buildFixtureEntry(
path.join(repoRoot, 'tests/e2e/fixtures/daemon-generation-entry.ts'),
entryPath
@@ -138,6 +138,13 @@ test.describe('Native chat transcript anchoring', () => {
sessionId,
transcriptPath
})
// Exercise the supported manual paging fallback while the reader stays mid-transcript.
await orcaPage.evaluate(() => {
Object.defineProperty(window, 'IntersectionObserver', {
value: undefined,
configurable: true
})
})
await toggleTerminalTabToChatView(orcaPage, {
tabId,
worktreeId: descriptor.worktreeId
+1 -1
View File
@@ -143,7 +143,7 @@ test.describe('Native chat message rail', () => {
// Activating the hover preview transfers focus into the prompt picker.
await rail.press('Enter')
await expect(panel.getByRole('button').first()).toBeFocused()
await expect(panel.locator('button[data-current="true"]')).toBeFocused()
await panel.getByRole('button', { name: 'Question 5:', exact: false }).click()
await expect(panel).not.toBeVisible()
const target = transcriptWindow.locator('[data-index="10"]')
@@ -20,7 +20,7 @@ import {
} from './helpers/terminal'
import { parkHiddenTabBehindDecoy, waitForTabParked } from './helpers/terminal-hidden-parking'
import { waitForPtyShellEcho } from './terminal-pty-readiness'
import { TERMINAL_TAB_PARK_FLIP_BURST_WINDOW_MS } from '../../src/renderer/src/components/terminal-pane/terminal-park-verdict-flip-telemetry'
import { TERMINAL_TAB_PARK_FLIP_WINDOW_MS } from '../../src/renderer/src/components/terminal-pane/terminal-park-verdict-flip-telemetry'
// Why: the parking wiring registers this handle (dev/exposeStore builds only)
// so tests can detect that hidden-view parking is compiled in and which delay
@@ -43,7 +43,7 @@ test.use({
const PARKED_FRAME_SCRIPT_DELAY_MS = 750
const PARKED_FRAME_COUNT = 25
const PARK_VERDICT_BURST_SETTLE_MS = TERMINAL_TAB_PARK_FLIP_BURST_WINDOW_MS * 4
const PARK_VERDICT_WINDOW_SETTLE_MS = Math.ceil(TERMINAL_TAB_PARK_FLIP_WINDOW_MS / 5)
function parkedTuiFrame(runId: string, frame: number): string {
const progress = `${'█'.repeat((frame % 8) + 1)}${'░'.repeat(8 - ((frame % 8) + 1))}`
@@ -478,7 +478,7 @@ test.describe('Terminal hidden view parking', () => {
orcaPage,
testRepoPath
}, testInfo: TestInfo) => {
test.setTimeout(180_000)
test.setTimeout(420_000)
await waitForSessionReady(orcaPage)
const setup = await setUpParkableTabA(orcaPage)
const { worktreeId, tabAId, tabAPtyId } = setup
@@ -542,8 +542,8 @@ test.describe('Terminal hidden view parking', () => {
const mismatches: string[] = []
for (let cycle = 1; cycle < CYCLES; cycle++) {
// Why: each cycle intentionally flips this tab's rendered verdict twice.
// Let the production anti-churn burst window lapse before the next one.
await orcaPage.waitForTimeout(PARK_VERDICT_BURST_SETTLE_MS)
// Keep each tab below the 12-flip sustained-churn pin in a 60s window.
await orcaPage.waitForTimeout(PARK_VERDICT_WINDOW_SETTLE_MS)
const rows = await runOneParkRevealCycle(cycle)
if (JSON.stringify(rows) !== JSON.stringify(referenceRows)) {
mismatches.push(
+12 -4
View File
@@ -40,7 +40,7 @@ test.describe('Reveal active workspace button', () => {
// (not a scenario real users hit). Reveal-into-view is covered robustly by
// the "outside the virtualized window" test below.
test('clears sidebar filters before revealing a hidden current workspace', async ({
test('adjusts sidebar filters before revealing a hidden current workspace', async ({
orcaPage,
testRepoPath
}, testInfo) => {
@@ -94,6 +94,13 @@ test.describe('Reveal active workspace button', () => {
if (!targetId) {
throw new Error('Seeded secondary worktree is missing')
}
const targetRepoId = await orcaPage.evaluate(
(repoPath) => window.__store!.getState().repos.find((repo) => repo.path === repoPath)?.id,
testRepoPath
)
if (!targetRepoId) {
throw new Error('Seeded repository is missing')
}
const targetRows = orcaPage.locator(
`[data-worktree-sidebar] [data-worktree-id=${JSON.stringify(targetId)}]`
@@ -132,7 +139,7 @@ test.describe('Reveal active workspace button', () => {
await revealButton.click()
await orcaPage
.getByRole('dialog', { name: 'Reveal hidden workspace?' })
.getByRole('button', { name: 'Clear filters and reveal' })
.getByRole('button', { name: 'Adjust filters and reveal' })
.click()
await expect(targetRow).toBeVisible()
@@ -149,10 +156,11 @@ test.describe('Reveal active workspace button', () => {
}),
{
timeout: 10_000,
message: 'Reveal button should clear repo filters that hide the current workspace'
message:
'Reveal button should preserve selected repos while revealing the current workspace'
}
)
.toEqual([])
.toEqual([filterRepoId, targetRepoId])
})
test('reveals the current workspace when it starts outside the virtualized window', async ({