From b3acef218a3988e161b88ddab4580b1b7f3ce5c8 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:14:42 -0700 Subject: [PATCH] test: verify imported projects through the virtualized sidebar (#19003) --- .../e2e/helpers/sidebar-project-visibility.ts | 27 +++++++++++++++++++ .../e2e/pr11346-selected-runtime-add.spec.ts | 3 ++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/e2e/helpers/sidebar-project-visibility.ts diff --git a/tests/e2e/helpers/sidebar-project-visibility.ts b/tests/e2e/helpers/sidebar-project-visibility.ts new file mode 100644 index 00000000000..92843ef9461 --- /dev/null +++ b/tests/e2e/helpers/sidebar-project-visibility.ts @@ -0,0 +1,27 @@ +import { expect, type Page } from '@stablyai/playwright-test' + +export async function expectSidebarProjectVisible(page: Page, projectName: string): Promise { + const sidebar = page.getByRole('listbox', { name: 'Worktrees', exact: true }) + const label = sidebar.getByText(projectName, { exact: false }).first() + await sidebar.evaluate((element) => { + element.scrollTop = 0 + element.dispatchEvent(new Event('scroll', { bubbles: true })) + }) + await expect + .poll( + async () => { + if (await label.isVisible()) { + return true + } + // Virtualized project headers mount only as their scroll range enters the viewport. + await sidebar.evaluate((element) => { + element.scrollTop += Math.max(1, Math.floor(element.clientHeight * 0.8)) + element.dispatchEvent(new Event('scroll', { bubbles: true })) + }) + return false + }, + { message: `sidebar never rendered project ${projectName}`, intervals: [100] } + ) + .toBe(true) + await expect(label).toBeVisible() +} diff --git a/tests/e2e/pr11346-selected-runtime-add.spec.ts b/tests/e2e/pr11346-selected-runtime-add.spec.ts index 6225f13c623..09630d277b3 100644 --- a/tests/e2e/pr11346-selected-runtime-add.spec.ts +++ b/tests/e2e/pr11346-selected-runtime-add.spec.ts @@ -1,3 +1,4 @@ +import { expectSidebarProjectVisible } from './helpers/sidebar-project-visibility' import { openSidebarProjectDialog } from './helpers/sidebar-project-dialog' import { rmSync } from 'node:fs' import path from 'node:path' @@ -727,7 +728,7 @@ async function runSelectedRuntimeAddJourney( ...fixture.nestedRepoPaths.map((repoPath) => path.basename(repoPath)) ]) { // Why: duplicate checkout names are disambiguated with a parent path. - await expect(client.page.getByText(projectName, { exact: false }).first()).toBeVisible() + await expectSidebarProjectVisible(client.page, projectName) } expect(await client.getDirectSshAttemptTargetIds()).toEqual([]) // Why: revealing the client must not leak into the HUB's window visibility.