From b7d9ae69681a800fa437dfb4ab24e8aefdf43cfd Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sat, 5 Sep 2026 20:00:14 -0700 Subject: [PATCH] diagnostic: capture dialog exit animation and terminal retirement state --- tests/e2e/helpers/ssh-config-host-picker.ts | 41 +++++++++++++++---- ...red-remote-terminal-stall-recovery.spec.ts | 18 +++++++- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/tests/e2e/helpers/ssh-config-host-picker.ts b/tests/e2e/helpers/ssh-config-host-picker.ts index 1ad35ad7699..4204624cde6 100644 --- a/tests/e2e/helpers/ssh-config-host-picker.ts +++ b/tests/e2e/helpers/ssh-config-host-picker.ts @@ -86,15 +86,38 @@ export async function closeOpenDialogs(page: Page): Promise { throw new Error('Open dialog is missing its Radix identity') } const dialog = page.locator(`[role="dialog"][id=${JSON.stringify(dialogId)}]`) - const cancelOrBack = dialog.getByRole('button', { name: /^(Cancel|Back)$/ }) - await ((await cancelOrBack - .first() - .isVisible() - .catch(() => false)) - ? cancelOrBack.first().click() - : page.keyboard.press('Escape')) - // Back can replace the picker with its parent without reducing the dialog count. - await expect(dialog).toBeHidden({ timeout: 3_000 }) + const back = dialog.getByRole('button', { name: 'Back', exact: true }) + if (await back.isVisible()) { + await back.click() + // The picker and host form reuse the same Radix dialog. + await expect(back).toBeHidden({ timeout: 3_000 }) + await expect(dialog.getByRole('button', { name: 'Cancel', exact: true })).toBeVisible({ + timeout: 3_000 + }) + continue + } + const cancel = dialog.getByRole('button', { name: 'Cancel', exact: true }) + await ((await cancel.isVisible()) ? cancel.click() : page.keyboard.press('Escape')) + await expect(dialog).toBeHidden({ timeout: 3_000 }).catch(async (error) => { + console.log('[dialog-exit-diagnostic]', JSON.stringify(await page.evaluate(() => ({ + visibility: document.visibilityState, + dialogs: Array.from(document.querySelectorAll('[role="dialog"]')).map((element) => { + const style = getComputedStyle(element) + return { + id: element.id, state: element.getAttribute('data-state'), + title: element.querySelector('h2')?.textContent, + animationName: style.animationName, duration: style.animationDuration, + delay: style.animationDelay, playState: style.animationPlayState, + display: style.display, visibility: style.visibility, opacity: style.opacity, + animations: element.getAnimations().map((animation) => ({ + playState: animation.playState, currentTime: animation.currentTime, + pending: animation.pending, timing: animation.effect?.getComputedTiming() + })) + } + }) + })))) + throw error + }) } await expect(page.getByRole('dialog')).toHaveCount(0, { timeout: 3_000 }) } diff --git a/tests/e2e/paired-remote-terminal-stall-recovery.spec.ts b/tests/e2e/paired-remote-terminal-stall-recovery.spec.ts index 4406ebd2f18..5af114bb0ef 100644 --- a/tests/e2e/paired-remote-terminal-stall-recovery.spec.ts +++ b/tests/e2e/paired-remote-terminal-stall-recovery.spec.ts @@ -583,7 +583,23 @@ test('restarts one ACK-starved paired terminal stream without replacing its PTY ]), { timeout: 30_000 } ) - .toEqual([false, false, false]) + .toEqual([false, false, false]).catch(async (error) => { + const inventory = await callRuntime(client.page, 'session.tabs.list', { + worktree: `id:${worktree.id}` + }) + const terminals = await callRuntime(client.page, 'terminal.list', { + worktree: `id:${worktree.id}`, handles: [terminal], + requireFreshPtyLiveness: true, includeVisualLayouts: false + }) + const mirrors = await Promise.all([client.page, observer.page].map((page) => + page.evaluate(({ worktreeId, tabId }) => { + const state = window.__store?.getState() + return { tabs: state?.tabsByWorktree[worktreeId], layout: state?.terminalLayoutsByTabId[tabId] } + }, { worktreeId: worktree.id, tabId: webTabId }) + )) + console.log('[paired-close-diagnostic]', JSON.stringify({ inventory, terminals, mirrors })) + throw error + }) terminal = null await restoreHeadedHost(electronApp, orcaPage)