diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index a94a7ea2ba5..dd0a00fd042 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -246,7 +246,7 @@ jobs: E2E_PROJECT_ARGS+=(--project=electron-headful) fi xvfb-run --auto-servernum bash .github/scripts/e2e-with-window-manager.sh env "${E2E_ENV[@]}" \ - pnpm run test:e2e "${TEST_FILES[@]}" --workers=1 "${E2E_PROJECT_ARGS[@]}" + pnpm run test:e2e "${TEST_FILES[@]}" --workers=1 "${E2E_PROJECT_ARGS[@]}" --repeat-each=3 - name: Upload Playwright traces if: failure() diff --git a/tests/e2e/terminal-reattach-mouse-mode-leak.spec.ts b/tests/e2e/terminal-reattach-mouse-mode-leak.spec.ts index cbdae675a49..4e9cca43373 100644 --- a/tests/e2e/terminal-reattach-mouse-mode-leak.spec.ts +++ b/tests/e2e/terminal-reattach-mouse-mode-leak.spec.ts @@ -35,6 +35,7 @@ import { discoverActivePtyId, execInTerminal, waitForActiveTerminalManager, + waitForActivePanePtyId, waitForPaneCount, waitForTerminalOutput } from './helpers/terminal' @@ -146,6 +147,11 @@ test.describe('reattach mouse-mode leak', () => { await ensureTerminalVisible(secondLaunch.page) await waitForActiveTerminalManager(secondLaunch.page, 30_000) await waitForPaneCount(secondLaunch.page, 1, 30_000) + // Live output is released only after reattach replay has finished. + const reattachedPtyId = await waitForActivePanePtyId(secondLaunch.page) + await execInTerminal(secondLaunch.page, reattachedPtyId, 'echo ORCA_REATTACHED_$((21+21))') + await waitForTerminalOutput(secondLaunch.page, 'ORCA_REATTACHED_42', 15_000) + // The reattach replay re-arms mouse via rehydrate, then the reset must // clear it. Poll until it settles to 'none' (times out if the reset @@ -261,16 +267,6 @@ test.describe('reattach mouse-mode leak', () => { expect(probe.afterReattach.mode).toBe('none') expect(probe.afterReattach.hasEnableMouseClass).toBe(false) expect(probe.afterReattach.reports).toBe(0) - // Why: the positive control needs the reattached pane to dynamically bind - // xterm's browser MouseService. Some headless CI renderers never do on a warm - // reattach — the core mouseTrackingMode still flips but no DOM class/listener - // attaches — so arming is impossible and the probe can't run. Skip there, - // matching the pane-manager/shell guards above; the reset invariant stays - // covered by repro-7329 + pty-connection unit tests and this suite on macOS. - test.skip( - !probe.armedMouseReporting, - 'Reattached pane does not dynamically bind xterm mouse reporting in this environment' - ) // Positive control proves the motion probe genuinely detects reports. expect(probe.classAfterArm).toBe(true) expect(probe.armedReports).toBeGreaterThan(0)