fix(win-e2e): keep overlay retries inside composer

This commit is contained in:
Brennan Benson
2026-07-22 15:58:20 -07:00
parent 42886779e2
commit aa4bcf9d8d
2 changed files with 119 additions and 25 deletions
+31 -17
View File
@@ -275,19 +275,30 @@ async function createWorkspaceFromSeededRepo(page, timeoutMs) {
// timeout by another full click attempt.
await newWorkspace.click({ timeout: 1 })
}
// Choose the plain-terminal mode (best-effort — if it is already the default
// or the label differs, the create below still produces a worktree).
await tryClickWithKnownOverlayRetry(
page,
page.getByRole('button', { name: 'Blank Terminal' }).first(),
15_000
)
const composer = page.getByRole('dialog', { name: 'Create worktree' }).last()
await composer.waitFor({ state: 'visible', timeout: 15_000 })
const agentPicker = composer
.locator('[data-agent-combobox-root="true"] button[role="combobox"]')
.first()
const selectedAgent = await agentPicker.innerText({ timeout: 15_000 }).catch(() => '')
if (!selectedAgent.includes('Blank Terminal')) {
if (!(await tryClickWithKnownOverlayRetry(page, agentPicker, 15_000))) {
await agentPicker.click({ timeout: 1 })
}
const blankTerminalOption = page
.locator('[data-agent-combobox-root="true"] [data-slot="command-item"]:visible')
.filter({ hasText: 'Blank Terminal' })
.first()
if (!(await tryClickWithKnownOverlayRetry(page, blankTerminalOption, 15_000))) {
await blankTerminalOption.click({ timeout: 1 })
}
}
// Submit. The create button's accessible name carries the shortcut hint
// ("Create worktreeCtrl"), so match by prefix; fall back to the documented
// Ctrl+Enter shortcut if the button is not directly clickable.
const created = await tryClickWithKnownOverlayRetry(
page,
page.getByRole('button', { name: /^Create worktree/ }).last(),
composer.getByRole('button', { name: /^Create worktree/ }).last(),
15_000
)
if (!created) {
@@ -296,18 +307,21 @@ async function createWorkspaceFromSeededRepo(page, timeoutMs) {
}
const OVERLAY_DISMISS_LABELS = ['Got it', 'Dismiss setup scripts', 'Dismiss tip', 'Dismiss update']
const DIALOG_CLOSE_BUTTON = '[data-slot="dialog-content"]:visible [data-slot="dialog-close"]'
const CLI_FEATURE_TIP_TITLE = 'Let agents drive Orca with the Orca CLI'
async function dismissKnownOverlays(page) {
let acted = false
// Why: a global "Close" role also matches the Windows/Linux title-bar button.
const dialogClose = page.locator(DIALOG_CLOSE_BUTTON).first()
if (await dialogClose.isVisible().catch(() => false)) {
const clicked = await dialogClose
.click({ timeout: 3_000 })
.then(() => true)
.catch(() => false)
acted ||= clicked
const cliFeatureTip = page.getByRole('dialog', { name: CLI_FEATURE_TIP_TITLE }).first()
if (await cliFeatureTip.isVisible().catch(() => false)) {
// Why: a global "Close" role also matches the Windows/Linux title-bar button.
const dialogClose = cliFeatureTip.locator('[data-slot="dialog-close"]').first()
if (await dialogClose.isVisible().catch(() => false)) {
const clicked = await dialogClose
.click({ timeout: 3_000 })
.then(() => true)
.catch(() => false)
acted ||= clicked
}
}
for (const name of OVERLAY_DISMISS_LABELS) {
const btn = page.getByRole('button', { name }).first()
+88 -8
View File
@@ -23,10 +23,20 @@ describe('dismissOverlays', () => {
click: vi.fn().mockRejectedValue(new Error('window closed'))
}
windowClose.first.mockReturnValue(windowClose)
const featureTipDialog = {
first: vi.fn(),
isVisible: vi.fn().mockResolvedValue(true),
locator: vi.fn().mockReturnValue(dialogClose)
}
featureTipDialog.first.mockReturnValue(featureTipDialog)
const page = {
locator: vi.fn().mockReturnValue(dialogClose),
getByRole: vi.fn((_role, { name }) => (name === 'Close' ? windowClose : hiddenButton())),
getByRole: vi.fn((role, { name }) => {
if (role === 'dialog') {
return featureTipDialog
}
return name === 'Close' ? windowClose : hiddenButton()
}),
keyboard: { press: vi.fn().mockResolvedValue(undefined) },
waitForTimeout: vi.fn().mockResolvedValue(undefined)
}
@@ -35,9 +45,9 @@ describe('dismissOverlays', () => {
expect(dialogClose.click).toHaveBeenCalledOnce()
expect(windowClose.click).not.toHaveBeenCalled()
expect(page.locator).toHaveBeenCalledWith(
'[data-slot="dialog-content"]:visible [data-slot="dialog-close"]'
)
expect(page.getByRole).toHaveBeenCalledWith('dialog', {
name: 'Let agents drive Orca with the Orca CLI'
})
})
it('keeps overlay retries within the caller timeout budget', async () => {
@@ -53,9 +63,12 @@ describe('dismissOverlays', () => {
newWorkspace.first.mockReturnValue(newWorkspace)
const page = {
locator: vi.fn().mockImplementation(() => hiddenButton()),
getByRole: vi.fn((_role, { name }) =>
name === 'New workspace' ? newWorkspace : hiddenButton()
),
getByRole: vi.fn((role, { name }) => {
if (role === 'dialog') {
return hiddenButton()
}
return name === 'New workspace' ? newWorkspace : hiddenButton()
}),
keyboard: { press: vi.fn().mockResolvedValue(undefined) },
isClosed: vi.fn().mockReturnValue(false)
}
@@ -71,4 +84,71 @@ describe('dismissOverlays', () => {
vi.useRealTimers()
}
})
it('submits within the composer without reopening the selected Blank Terminal picker', async () => {
const newWorkspace = {
first: vi.fn(),
click: vi.fn().mockResolvedValue(undefined)
}
newWorkspace.first.mockReturnValue(newWorkspace)
const agentPicker = {
first: vi.fn(),
innerText: vi.fn().mockResolvedValue('Blank Terminal'),
click: vi.fn()
}
agentPicker.first.mockReturnValue(agentPicker)
const createWorktree = {
last: vi.fn(),
click: vi
.fn()
.mockRejectedValueOnce(new Error('submit was briefly intercepted'))
.mockResolvedValueOnce(undefined)
}
createWorktree.last.mockReturnValue(createWorktree)
const composer = {
last: vi.fn(),
waitFor: vi.fn().mockResolvedValue(undefined),
locator: vi.fn().mockReturnValue(agentPicker),
getByRole: vi.fn().mockReturnValue(createWorktree)
}
composer.last.mockReturnValue(composer)
const xterm = {
first: vi.fn(),
waitFor: vi.fn().mockResolvedValue(undefined)
}
xterm.first.mockReturnValue(xterm)
const terminalSurface = {
first: vi.fn(),
isVisible: vi.fn().mockResolvedValue(false),
waitFor: vi.fn().mockResolvedValue(undefined),
locator: vi.fn().mockReturnValue(xterm)
}
terminalSurface.first.mockReturnValue(terminalSurface)
const unintendedDialogClose = {
first: vi.fn(),
isVisible: vi.fn().mockResolvedValue(true),
click: vi.fn().mockResolvedValue(undefined)
}
unintendedDialogClose.first.mockReturnValue(unintendedDialogClose)
const page = {
locator: vi.fn((selector) =>
selector.includes('dialog-close') ? unintendedDialogClose : terminalSurface
),
getByRole: vi.fn((role, { name }) => {
if (role === 'dialog') {
return name === 'Create worktree' ? composer : hiddenButton()
}
return name === 'New workspace' ? newWorkspace : hiddenButton()
}),
keyboard: { press: vi.fn().mockResolvedValue(undefined) },
isClosed: vi.fn().mockReturnValue(false)
}
await ensureTerminal(page)
expect(agentPicker.click).not.toHaveBeenCalled()
expect(composer.getByRole).toHaveBeenCalledWith('button', { name: /^Create worktree/ })
expect(unintendedDialogClose.click).not.toHaveBeenCalled()
expect(createWorktree.click).toHaveBeenCalledTimes(2)
})
})