From 7b7daf4f288a68a44ae4d161cd56e098455e0df6 Mon Sep 17 00:00:00 2001 From: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Date: Mon, 7 Sep 2026 20:12:35 -0700 Subject: [PATCH] test(e2e): extract remote handle polling into helper function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `expectMirroredRemoteHandles` to eliminate duplication and document why links open with `focusOnCreate: false` create background tabs that never mount a pane — only their mirrored handles are observable, arriving a beat before the URL. --- .../paired-cmd-j-host-qualified-tabs.spec.ts | 2 + ...d-remote-browser-link-open-routing.spec.ts | 42 +++++++++++++++---- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/tests/e2e/paired-cmd-j-host-qualified-tabs.spec.ts b/tests/e2e/paired-cmd-j-host-qualified-tabs.spec.ts index af068289764..2157f9adb40 100644 --- a/tests/e2e/paired-cmd-j-host-qualified-tabs.spec.ts +++ b/tests/e2e/paired-cmd-j-host-qualified-tabs.spec.ts @@ -24,6 +24,8 @@ test('routes same-id browser and simulator Cmd-J rows to their owning paired hos if (!worktreeId) { throw new Error('Host has no active worktree for the paired Cmd-J fixture') } + // Why: only an activated host tab lands in a rendered group, which is what the seeding step + // below requires of the mirrored remote group before it will seed the collision rows. const workspace = state.createBrowserTab( worktreeId, 'data:text/html,Remote browser proof', diff --git a/tests/e2e/paired-remote-browser-link-open-routing.spec.ts b/tests/e2e/paired-remote-browser-link-open-routing.spec.ts index bb1edb87763..c409fad4c11 100644 --- a/tests/e2e/paired-remote-browser-link-open-routing.spec.ts +++ b/tests/e2e/paired-remote-browser-link-open-routing.spec.ts @@ -121,6 +121,32 @@ async function readRemotePaneUrls(page: Page, worktreeId: string): Promise { + await expect + .poll( + async () => { + const urls = await readRemotePaneUrls(page, worktreeId) + return ( + urls.length === expected.count && urls.some((url) => url.startsWith(expected.linkUrl)) + ) + }, + { + timeout: 60_000, + message: 'the client never mirrored the link as a remote handle carrying its URL' + } + ) + .toBe(true) +} + /** The client mirrors host browser tabs on its own; this finds the mirrored page for one URL. */ async function findMirroredPage( page: Page, @@ -299,15 +325,16 @@ test('opens a remote pane link on the pane runtime and refuses to fall back to t message: 'the runtime process never held a page for the link' }) .toHaveLength(1) - // The cold background page is mirrored as a handle before it publishes its loaded URL. - await expect - .poll(async () => (await readRemotePaneUrls(page, worktreeId)).length, { timeout: 60_000 }) - .toBe(remoteHandleCountBeforeOpen + 1) + await expectMirroredRemoteHandles(page, worktreeId, { + count: remoteHandleCountBeforeOpen + 1, + linkUrl: fixture.linkUrl + }) expect(await readLocalBrowserViewUrls(page)).toHaveLength(0) // Drop every tab except the pane's, so the next act drives the pane it started with against a // host that no longer holds the link. await closeBrowserTabsExceptPane(page, worktreeId, fixture.paneUrl) + // The background link tab never mounted a pane, so its handle going away is the mirror's signal. await expect .poll(async () => (await readRemotePaneUrls(page, worktreeId)).length, { timeout: 60_000 }) .toBe(remoteHandleCountBeforeOpen) @@ -349,9 +376,10 @@ test('opens a remote pane link on the pane runtime and refuses to fall back to t .toHaveLength(1) expect(await readOwnedPageUrls(client!.app, fixture.linkUrl)).toHaveLength(0) expect(await readLocalBrowserViewUrls(page)).toHaveLength(0) - await expect - .poll(async () => (await readRemotePaneUrls(page, worktreeId)).length, { timeout: 60_000 }) - .toBe(remoteHandleCountBeforeOpen + 1) + await expectMirroredRemoteHandles(page, worktreeId, { + count: remoteHandleCountBeforeOpen + 1, + linkUrl: fixture.linkUrl + }) // The store drops the tab synchronously and only then fires browser.tabClose, so settle the // mirror, host inventory, and host guest before act 3 reads them as its own baseline.