From 4f961421129568411a5c7396a4cbc2f3d2309b00 Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com> Date: Tue, 3 Nov 2026 10:04:10 +0000 Subject: [PATCH] test(app): read expanded turns across the virtual window Verify every command remains accessible while scrolling and after older history loads. Requiring all expanded rows in the DOM at once contradicts bounded desktop mounting. Co-authored-by: luke --- .../app/e2e/browser/turn-collapse.spec.ts | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/packages/app/e2e/browser/turn-collapse.spec.ts b/packages/app/e2e/browser/turn-collapse.spec.ts index d990e33009..82d653208e 100644 --- a/packages/app/e2e/browser/turn-collapse.spec.ts +++ b/packages/app/e2e/browser/turn-collapse.spec.ts @@ -3,6 +3,7 @@ import path from "node:path"; import { holdOlderHistoryPages, userScrollsTimelineToHistoryStart, + waitForTimelineGeometryToSettle, } from "../support/helpers/timeline-pagination"; import { getActiveTabTestId } from "../support/helpers/launcher"; import type { Page, Locator } from "@playwright/test"; @@ -407,6 +408,38 @@ async function seedWholeTurnHistory() { return agent; } +/** Read every command across the scroll window, without requiring offscreen rows to mount. */ +async function expectExpandedCommandsReadable(page: Page, count: number) { + const timeline = page.getByTestId("agent-chat-scroll"); + const commands = new Set(); + await timeline.hover(); + for (let step = 0; step < count && commands.size < count; step += 1) { + const labels = await timeline + .getByRole("button", { name: /echo stress-\d+/ }) + .allTextContents(); + for (const label of labels) { + const command = /echo stress-(\d+)/.exec(label); + if (command) commands.add(Number(command[1])); + } + if (commands.size < count) { + await page.mouse.wheel(0, 300); + await waitForTimelineGeometryToSettle(page); + } + } + expect([...commands].sort((a, b) => a - b)).toEqual( + Array.from({ length: count }, (_, index) => index), + ); +} + +async function returnToExpandedSummary(page: Page, summary: Locator) { + await page.getByTestId("agent-chat-scroll").hover(); + for (let step = 0; step < 120 && !(await summary.isVisible()); step += 1) { + await page.mouse.wheel(0, -300); + await waitForTimelineGeometryToSettle(page); + } + await summary.scrollIntoViewIfNeeded(); +} + test("loads complete long turns and preserves expansion while revealing older history", async ({ page, }) => { @@ -423,7 +456,7 @@ test("loads complete long turns and preserves expansion while revealing older hi await expect(latest).toBeVisible(); await expect.poll(() => rowsBetweenLatestSummaryAndReply(page)).toBe(0); await latest.click(); - await expect.poll(() => rowsBetweenLatestSummaryAndReply(page)).toBe(120); + await expectExpandedCommandsReadable(page, 120); await userScrollsTimelineToHistoryStart(page); await history.expectRequestedPages(1); history.releasePage(1); @@ -432,9 +465,9 @@ test("loads complete long turns and preserves expansion while revealing older hi .getByTestId("turn-summary") .getByRole("button", { name: "Ran 60 commands", exact: true }), ).toBeVisible(); - await expect.poll(() => rowsBetweenLatestSummaryAndReply(page)).toBe(120); + await expectExpandedCommandsReadable(page, 120); history.expectNoRepeatedEntries(); - await latest.scrollIntoViewIfNeeded(); + await returnToExpandedSummary(page, latest); await latest.click(); await expect.poll(() => rowsBetweenLatestSummaryAndReply(page)).toBe(0); } finally {