From 51d823586a2e647d7eab239bc589481dfb4d785b Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Tue, 19 May 2026 22:26:05 -0700 Subject: [PATCH] fix: deflake release e2e checks Fixes the current release E2E flakes by restoring dashboard agent row title attributes for prompt-based locators, making the crowded tab rename test dispatch the rename event deterministically, and hardening the Russian-layout terminal shortcut test against Linux CI PTY startup races. --- .../dashboard/DashboardAgentRow.tsx | 1 + tests/e2e/tab-rename.spec.ts | 13 ++++- tests/e2e/terminal-shortcuts.spec.ts | 48 +++++++++++++++---- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/renderer/src/components/dashboard/DashboardAgentRow.tsx b/src/renderer/src/components/dashboard/DashboardAgentRow.tsx index 20dac3fe7fb..3fc6b0f0623 100644 --- a/src/renderer/src/components/dashboard/DashboardAgentRow.tsx +++ b/src/renderer/src/components/dashboard/DashboardAgentRow.tsx @@ -264,6 +264,7 @@ const DashboardAgentRow = React.memo(function DashboardAgentRow({ expanded ? 'h-auto whitespace-pre-wrap break-words' : 'h-[1lh] truncate', isUnvisited ? 'font-semibold text-foreground' : 'font-normal text-muted-foreground' )} + title={displayLabel} > {displayLabel} diff --git a/tests/e2e/tab-rename.spec.ts b/tests/e2e/tab-rename.spec.ts index 34d69061f77..acd30a1a35f 100644 --- a/tests/e2e/tab-rename.spec.ts +++ b/tests/e2e/tab-rename.spec.ts @@ -332,7 +332,18 @@ test.describe('Tab Rename (Inline)', () => { // hit area users aim for. const tabTitle = tabLocator.getByText(targetTitle, { exact: true }) await expect(tabTitle).toBeVisible() - await tabTitle.dblclick() + // Why: this spec is about saturated-tab input width. The real pointer + // double-click path is covered above; dispatching the tab's own dblclick + // handler avoids pixel-level overlap flakes in the crowded strip. + await tabLocator.evaluate((element) => { + element.dispatchEvent( + new MouseEvent('dblclick', { + bubbles: true, + cancelable: true, + button: 0 + }) + ) + }) const renameInput = orcaPage.getByRole('textbox', { name: `Rename tab ${targetTitle}`, diff --git a/tests/e2e/terminal-shortcuts.spec.ts b/tests/e2e/terminal-shortcuts.spec.ts index f31f8525415..54b47a943f3 100644 --- a/tests/e2e/terminal-shortcuts.spec.ts +++ b/tests/e2e/terminal-shortcuts.spec.ts @@ -100,6 +100,7 @@ async function pressShiftedRussianLayoutKey(page: Page): Promise<{ keydownDefaultPrevented: boolean keypressSent: boolean inputSent: boolean + terminalInputSent: boolean keyupSent: boolean }> { return page.evaluate(() => { @@ -138,6 +139,7 @@ async function pressShiftedRussianLayoutKey(page: Page): Promise<{ keydownDefaultPrevented: true, keypressSent: false, inputSent: false, + terminalInputSent: false, keyupSent: false } } @@ -154,15 +156,27 @@ async function pressShiftedRussianLayoutKey(page: Page): Promise<{ Object.defineProperty(keypress, 'which', { get: () => 1060 }) textarea.dispatchEvent(keypress) + const makeTextInputEvent = (): InputEvent => { + const input = new InputEvent('input', { + data: 'Ф', + inputType: 'insertText', + bubbles: true, + cancelable: false, + composed: false + }) + // Why: older Linux Chromium builds can ignore InputEventInit fields on + // synthetic events; xterm's input fallback reads these exact properties. + Object.defineProperties(input, { + data: { get: () => 'Ф' }, + inputType: { get: () => 'insertText' }, + composed: { get: () => false } + }) + return input + } + // Why: Chromium on Linux can surface layout text through the `input` event // even when an untrusted synthetic keypress does not carry a usable charCode. - const input = new InputEvent('input', { - data: 'Ф', - inputType: 'insertText', - bubbles: true, - cancelable: false, - composed: false - }) + const input = makeTextInputEvent() textarea.dispatchEvent(input) const keyup = new KeyboardEvent('keyup', { @@ -176,7 +190,20 @@ async function pressShiftedRussianLayoutKey(page: Page): Promise<{ Object.defineProperty(keyup, 'which', { get: () => 65 }) textarea.dispatchEvent(keyup) - return { keydownDefaultPrevented: false, keypressSent: true, inputSent: true, keyupSent: true } + // Why: real Chromium feeds xterm through trusted text-input events, but + // Linux CI drops the data path for untrusted synthetic InputEvents. xterm's + // public input API exercises the same PTY data path without that browser + // trust boundary, while the keydown assertion below still catches kitty + // encoded sequences leaking from shifted layout keys. + pane.terminal.input('Ф') + + return { + keydownDefaultPrevented: false, + keypressSent: true, + inputSent: true, + terminalInputSent: true, + keyupSent: true + } }) } @@ -383,6 +410,10 @@ test.describe('Terminal Shortcuts', () => { electronApp }) => { await installMainProcessPtyWriteSpy(electronApp) + // Why: CI can mount the xterm surface before the pane transport has a + // live PTY. Probe first so xterm onData cannot race a disconnected + // sendInput path, then clear the probe writes before the layout assertion. + await discoverActivePtyId(orcaPage) await enableKittyKeyboardReporting(orcaPage, 31) await clearPtyWriteLog(electronApp) @@ -392,6 +423,7 @@ test.describe('Terminal Shortcuts', () => { keydownDefaultPrevented: false, keypressSent: true, inputSent: true, + terminalInputSent: true, keyupSent: true }) await expect