mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
* fix(e2e): repair release e2e suite — parking regression tests, stale/flaky specs, profile switcher gate Diagnosed 20 failing tests across the release e2e shards. Most are test debt, plus two genuine product-side issues. Product fixes: - OrcaProfileSwitcher: the PROD gate hid the "Switch profile" button in the e2e build (electron-vite build bakes NODE_ENV=production). Exempt MODE==='e2e' so the specs render it while packaged prod builds stay hidden. Parking cluster (8 tests): #8262 intentionally keeps the most-recently-hidden tab warm (exempt from cold-park). The specs hid exactly one tab — always the exempt one — so it never parked. Open a throwaway decoy tab that absorbs the last-active exemption so the target parks. (terminal-hidden-view-parking, terminal-pane-close-layout-consistency) Stale tests updated to match intended product behavior: - rich-markdown-link-bubble: match Edit link by aria-label (title dropped in #8307) - terminal-codex-hidden-startup-background: drop the dead hiddenRendererSkipCount poll (Phase-4 main-side delivery gate #7214 bypasses that renderer path) Brittle threshold/geometry/timing hardening (no product regression): - agent-session-log-tail-stability: assert full-model length instead of a machine-specific word-wrap pixel baseline - artificial-opencode revisit: dedicated under-backpressure latency bound - terminal-history-size-typing-latency: gate p90 not max (tolerate one checkpoint-in-window spike; median stays strict) - combined-diff-scroll-restore: assert viewport barely moved vs exact anchor key - terminal-shortcuts: idempotent kitty-flag reset instead of a racing stack pop - agent-session-live-force-exit-resume: drive the product quit-capture path - renderer-crash-recovery-terminal-input: poll the transport probe over the recovery budget (still flags a permanently frozen pane) terminal-push-delivery-loss-recovery left unchanged (no safe test-only improvement; recovery is wall-clock bounded with ample slack). * Extract shared parking helpers into terminal-hidden-parking.ts for e2e s - Deduplicate waitForTabParked/parkHiddenTabBehindDecoy, previously copy-pasted across the parking and layout-consistency specs - Parameterize parkDelayMs so the helper no longer depends on a file-local PARKING_DELAY_MS constant
160 lines
6.5 KiB
TypeScript
160 lines
6.5 KiB
TypeScript
/**
|
|
* Reliability contract:
|
|
* - Invariant: link actions remain visible and interactive when they cross the Explorer seam.
|
|
* - Failure source: the in-editor bubble was clipped by overflow-hidden workbench ancestors.
|
|
* - Oracle: a real Chromium hit test inside the bubble/Explorer overlap resolves to the bubble.
|
|
* - Layer: Electron is required because DOM shims cannot model clipping or stacking contexts.
|
|
* - Wait: visible editor, Explorer, link, and bubble locators; no timing sleeps.
|
|
* - Artifacts: Playwright retains a trace and screenshot on failure.
|
|
* - Maturity: experimental pending CI soak history.
|
|
*/
|
|
|
|
import { test, expect } from './helpers/orca-app'
|
|
import { waitForActiveWorktree, waitForSessionReady } from './helpers/store'
|
|
import {
|
|
cleanupMarkdownFixture,
|
|
createMarkdownFixture,
|
|
getActiveWorktreeContext,
|
|
openMarkdownFixture,
|
|
waitForRichMarkdownEditor
|
|
} from './helpers/markdown-ordered-list-exit'
|
|
|
|
const LINK_HREF = 'https://example.com/a/very/long/path/that/makes/the-link-bubble-wide'
|
|
const MARKDOWN = `# Rich markdown link overlay repro
|
|
|
|
This paragraph deliberately places the link near the right edge of the editor so its URL bubble reaches the Explorer boundary: alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu xi omicron pi rho sigma tau [hover this URL](${LINK_HREF}).
|
|
`
|
|
|
|
type OverlapHitTest = {
|
|
bubbleRight: number
|
|
explorerLeft: number
|
|
overlapWidth: number
|
|
topElementIsBubble: boolean
|
|
}
|
|
|
|
test.describe('Rich markdown link bubble stacking', () => {
|
|
test('link actions stay above the right Explorer', async ({ orcaPage }, testInfo) => {
|
|
await orcaPage.setViewportSize({ width: 1920, height: 1080 })
|
|
await waitForSessionReady(orcaPage)
|
|
await waitForActiveWorktree(orcaPage)
|
|
|
|
const context = await getActiveWorktreeContext(orcaPage)
|
|
let filePath: string | null = null
|
|
|
|
try {
|
|
filePath = await createMarkdownFixture(
|
|
context,
|
|
'link-bubble-stacking',
|
|
testInfo.workerIndex,
|
|
MARKDOWN
|
|
)
|
|
await openMarkdownFixture(orcaPage, context, filePath)
|
|
await waitForRichMarkdownEditor(orcaPage)
|
|
|
|
await orcaPage.evaluate(() => {
|
|
const store = window.__store
|
|
if (!store) {
|
|
throw new Error('window.__store is not available — is the app in dev mode?')
|
|
}
|
|
store.setState({
|
|
rightSidebarOpen: true,
|
|
rightSidebarTab: 'explorer',
|
|
rightSidebarWidth: 780
|
|
})
|
|
})
|
|
|
|
const explorer = orcaPage.locator('[data-orca-explorer-shell]')
|
|
const link = orcaPage.locator(`.rich-markdown-editor a[href="${LINK_HREF}"]`)
|
|
await expect(explorer).toBeVisible()
|
|
await expect(link).toBeVisible()
|
|
|
|
await link.click()
|
|
|
|
const bubble = orcaPage.locator('.rich-markdown-link-bubble')
|
|
await expect(bubble).toBeVisible()
|
|
await expect(bubble.locator('.rich-markdown-link-url')).toContainText('https://example.com')
|
|
|
|
const overlap = await orcaPage.evaluate((): OverlapHitTest => {
|
|
const bubble = document.querySelector<HTMLElement>('.rich-markdown-link-bubble')
|
|
const explorer = document.querySelector<HTMLElement>('[data-orca-explorer-shell]')
|
|
if (!bubble || !explorer) {
|
|
throw new Error('Link bubble or Explorer was not rendered')
|
|
}
|
|
|
|
const bubbleRect = bubble.getBoundingClientRect()
|
|
const explorerRect = explorer.getBoundingClientRect()
|
|
const overlapLeft = Math.max(bubbleRect.left, explorerRect.left)
|
|
const overlapRight = Math.min(bubbleRect.right, explorerRect.right)
|
|
const overlapWidth = Math.max(0, overlapRight - overlapLeft)
|
|
const probeX = overlapLeft + Math.min(4, overlapWidth / 2)
|
|
const probeY = bubbleRect.top + bubbleRect.height / 2
|
|
const topElement = document.elementFromPoint(probeX, probeY)
|
|
|
|
return {
|
|
bubbleRight: bubbleRect.right,
|
|
explorerLeft: explorerRect.left,
|
|
overlapWidth,
|
|
topElementIsBubble: topElement !== null && bubble.contains(topElement)
|
|
}
|
|
})
|
|
|
|
expect(overlap.bubbleRight).toBeGreaterThan(overlap.explorerLeft)
|
|
expect(overlap.overlapWidth).toBeGreaterThan(8)
|
|
expect(overlap.topElementIsBubble).toBe(true)
|
|
|
|
// The Edit action exposes its label via aria-label (a shadcn Button +
|
|
// Radix tooltip), not a title attribute, so match by accessible name.
|
|
const editButton = bubble.getByRole('button', { name: 'Edit link' })
|
|
const editButtonBounds = await editButton.boundingBox()
|
|
const explorerBounds = await explorer.boundingBox()
|
|
expect(editButtonBounds).not.toBeNull()
|
|
expect(explorerBounds).not.toBeNull()
|
|
expect(editButtonBounds!.x + editButtonBounds!.width).toBeGreaterThan(explorerBounds!.x)
|
|
await editButton.click()
|
|
const input = bubble.locator('input')
|
|
await expect(input).toBeFocused()
|
|
await input.fill(`https://example.com/${'long-url-segment/'.repeat(30)}`)
|
|
await input.press('End')
|
|
expect(await input.evaluate((element) => element.scrollLeft)).toBeGreaterThan(0)
|
|
await expect(input).toBeFocused()
|
|
await expect(bubble).toBeVisible()
|
|
await orcaPage.keyboard.press('Escape')
|
|
await expect(bubble.locator('.rich-markdown-link-url')).toBeVisible()
|
|
|
|
await explorer.getByPlaceholder('Find files').click()
|
|
await expect(bubble).toHaveCount(0)
|
|
|
|
await orcaPage.getByRole('heading', { name: 'Rich markdown link overlay repro' }).click()
|
|
await link.click()
|
|
await expect(bubble).toBeVisible()
|
|
const originalEditorZoom = await orcaPage.evaluate(() => {
|
|
const store = window.__store
|
|
if (!store) {
|
|
throw new Error('window.__store is not available — is the app in dev mode?')
|
|
}
|
|
const zoom = store.getState().editorFontZoomLevel
|
|
store.getState().setEditorFontZoomLevel(zoom + 1)
|
|
return zoom
|
|
})
|
|
await expect(bubble).toHaveCount(0)
|
|
await orcaPage.evaluate((zoom) => {
|
|
window.__store?.getState().setEditorFontZoomLevel(zoom)
|
|
}, originalEditorZoom)
|
|
|
|
await orcaPage.getByRole('heading', { name: 'Rich markdown link overlay repro' }).click()
|
|
await link.click()
|
|
await expect(bubble).toBeVisible()
|
|
await orcaPage.evaluate(() => {
|
|
const store = window.__store
|
|
if (!store) {
|
|
throw new Error('window.__store is not available — is the app in dev mode?')
|
|
}
|
|
store.getState().setActiveView('settings')
|
|
})
|
|
await expect(bubble).toHaveCount(0)
|
|
} finally {
|
|
await cleanupMarkdownFixture(filePath)
|
|
}
|
|
})
|
|
})
|