From b1da8d8930fad0d16b75f54cf152e26e61868f77 Mon Sep 17 00:00:00 2001 From: brennanb2025 Date: Sun, 5 Jul 2026 21:05:35 -0700 Subject: [PATCH] Poll for PTY column re-sync in desync repro tests The two shortest-wait cases (:129 visible resize, :169 pty:getSize applied size) asserted an exact match after a fixed 400-500ms wait. The PTY re-sync after a resize is async (renderer fit -> pty:resize -> daemon -> ioctl); under CI load it lands later than the fixed wait, so the exact check sampled mid-flight and flaked. Poll until the sizes agree (bounded 15s). A genuinely dropped resize that never re-syncs still fails, matching the sibling re-sync tests in this file that already tolerate async timing with longer waits. Co-authored-by: Orca --- .../e2e/terminal-column-desync-repro.spec.ts | 74 ++++++++++++++----- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/tests/e2e/terminal-column-desync-repro.spec.ts b/tests/e2e/terminal-column-desync-repro.spec.ts index 1dad7c22b17..f90d47b862a 100644 --- a/tests/e2e/terminal-column-desync-repro.spec.ts +++ b/tests/e2e/terminal-column-desync-repro.spec.ts @@ -105,6 +105,57 @@ async function readColumnSnapshot(page: Page, ptyId: string): Promise { + const deadline = Date.now() + timeoutMs + let snapshot: ColumnSnapshot = { xtermCols: -1, ptyCols: -1 } + do { + snapshot = await readColumnSnapshot(page, ptyId) + if (snapshot.ptyCols === snapshot.xtermCols) { + return + } + await page.waitForTimeout(500) + } while (Date.now() < deadline) + throw new Error( + `${label}: PTY cols (${snapshot.ptyCols}) never re-synced to xterm cols (${snapshot.xtermCols}) ` + + `within ${timeoutMs}ms; a stale PTY width that never re-syncs is the column-desync bug` + ) +} + +async function waitForReportedColsToMatchPty( + page: Page, + ptyId: string, + timeoutMs = COLUMN_RESYNC_TIMEOUT_MS +): Promise { + const deadline = Date.now() + timeoutMs + let reportedCols = -1 + let ptyCols = -1 + do { + ptyCols = await readPtyCols(page, ptyId) + reportedCols = await readReportedPtyCols(page, ptyId) + if (reportedCols === ptyCols) { + return + } + await page.waitForTimeout(500) + } while (Date.now() < deadline) + throw new Error( + `pty:getSize reported ${reportedCols} but the PTY's process.stdout.columns is ${ptyCols} and ` + + `never re-synced within ${timeoutMs}ms; getSize must reflect the APPLIED size so the ` + + `drift-check can detect a dropped resize` + ) +} + async function closeRightSidebarAndFeatureTips(page: Page): Promise { await page.evaluate(() => { const store = window.__store @@ -144,20 +195,10 @@ test.describe('Terminal column desync repro', () => { // Shrink the window while the terminal is visible, then widen it. xterm // reflows via the ResizeObserver; the PTY must follow. await orcaPage.setViewportSize({ width: 760, height: 800 }) - await orcaPage.waitForTimeout(400) - const narrow = await readColumnSnapshot(orcaPage, ptyId) - expect( - narrow.ptyCols, - `after shrink, PTY cols (${narrow.ptyCols}) should equal xterm cols (${narrow.xtermCols})` - ).toBe(narrow.xtermCols) + await waitForPtyColsToMatchXterm(orcaPage, ptyId, 'after shrink') await orcaPage.setViewportSize({ width: 1280, height: 800 }) - await orcaPage.waitForTimeout(400) - const wide = await readColumnSnapshot(orcaPage, ptyId) - expect( - wide.ptyCols, - `after widen, PTY cols (${wide.ptyCols}) should equal xterm cols (${wide.xtermCols})` - ).toBe(wide.xtermCols) + await waitForPtyColsToMatchXterm(orcaPage, ptyId, 'after widen') }) // Why: guards the applied-size IPC contract the desync fix relies on. The @@ -175,15 +216,8 @@ test.describe('Terminal column desync repro', () => { const ptyId = await settleTerminal(orcaPage) await orcaPage.setViewportSize({ width: 900, height: 800 }) - await orcaPage.waitForTimeout(500) - const ptyCols = await readPtyCols(orcaPage, ptyId) - const reportedCols = await readReportedPtyCols(orcaPage, ptyId) - expect( - reportedCols, - `pty:getSize reported ${reportedCols} but the PTY's process.stdout.columns is ${ptyCols}; ` + - `getSize must reflect the APPLIED size so the drift-check can detect a dropped resize` - ).toBe(ptyCols) + await waitForReportedColsToMatchPty(orcaPage, ptyId) }) test('PTY columns re-sync after the terminal is resized while hidden', async ({ orcaPage }) => {