From f821f1eca4aafacc16a6d4398a33d45cb44ac875 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Sun, 2 Aug 2026 23:40:14 +0000 Subject: [PATCH] test(heartbeats): expand tracks idempotently --- .../e2e/browser/agent-heartbeat-track.spec.ts | 7 ++-- .../app/e2e/support/helpers/heartbeats.ts | 33 ++++++++++++++++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/packages/app/e2e/browser/agent-heartbeat-track.spec.ts b/packages/app/e2e/browser/agent-heartbeat-track.spec.ts index 7b9ac862fd..eff632ab3c 100644 --- a/packages/app/e2e/browser/agent-heartbeat-track.spec.ts +++ b/packages/app/e2e/browser/agent-heartbeat-track.spec.ts @@ -9,6 +9,7 @@ import { expectWorkspaceRunning, openHeartbeat, openHeartbeatAndSubagentTracks, + openHeartbeatTrack, removeSeededSubagent, returnToAgentHeartbeat, seedAgentWithHeartbeat, @@ -28,7 +29,7 @@ test("an agent heartbeat stays visible and keeps its workspace running", async ( await expectWorkspaceDone(page); const heartbeat = await scenario.createHeartbeat(); await expectWorkspaceRunning(page); - await openHeartbeatAndSubagentTracks(page); + await openHeartbeatAndSubagentTracks(page, heartbeat, scenario.child.id); await expectHeartbeatVisible(page, heartbeat); await captureHeartbeatEvidence(page, testInfo, "heartbeat-stacked-tracks"); @@ -39,7 +40,7 @@ test("an agent heartbeat stays visible and keeps its workspace running", async ( await removeSeededSubagent(scenario); await returnToAgentHeartbeat(page); await expectWorkspaceRunning(page); - await page.getByRole("button", { name: "1 heartbeat" }).click(); + await openHeartbeatTrack(page, heartbeat); await deleteHeartbeat(page, heartbeat); await expect .poll(() => scenario.readHeartbeatExists(heartbeat.id), { timeout: 30_000 }) @@ -53,7 +54,7 @@ test("an agent heartbeat stays visible and keeps its workspace running", async ( const expiringHeartbeat = await scenario.createHeartbeat({ name: "Temporary watch" }); await expectWorkspaceRunning(page); - await page.getByRole("button", { name: "1 heartbeat" }).click(); + await openHeartbeatTrack(page, expiringHeartbeat); await expectHeartbeatVisible(page, expiringHeartbeat); await scenario.setHeartbeatExpiry( expiringHeartbeat.id, diff --git a/packages/app/e2e/support/helpers/heartbeats.ts b/packages/app/e2e/support/helpers/heartbeats.ts index 60ec611423..7ca6d8946e 100644 --- a/packages/app/e2e/support/helpers/heartbeats.ts +++ b/packages/app/e2e/support/helpers/heartbeats.ts @@ -1,4 +1,4 @@ -import { expect, type Page, type TestInfo } from "@playwright/test"; +import { expect, type Locator, type Page, type TestInfo } from "@playwright/test"; import type { ScheduleSummary } from "@getpaseo/protocol/schedule/types"; import { seedParentWithSubagent } from "./subagents"; import { seedWorkspace, type SeededWorkspace } from "./seed-client"; @@ -137,9 +137,25 @@ export async function expectWorkspaceDone(page: Page): Promise { await expect(workspaceRow.getByTestId("workspace-status-indicator-running")).toHaveCount(0); } -export async function openHeartbeatAndSubagentTracks(page: Page): Promise { - await page.getByRole("button", { name: "1 heartbeat" }).click(); - await page.getByRole("button", { name: "1 subagent" }).click(); +export async function openHeartbeatAndSubagentTracks( + page: Page, + heartbeat: SeededHeartbeat, + subagentId: string, +): Promise { + await openHeartbeatTrack(page, heartbeat); + await ensureTrackExpanded( + page, + "1 subagent", + page.getByTestId(`subagents-track-row-${subagentId}`), + ); +} + +export async function openHeartbeatTrack(page: Page, heartbeat: SeededHeartbeat): Promise { + await ensureTrackExpanded( + page, + "1 heartbeat", + page.getByRole("link", { name: `${heartbeat.name}, ${heartbeat.cadence}` }), + ); } export async function expectHeartbeatVisible( @@ -194,3 +210,12 @@ export async function captureHeartbeatEvidence( await page.screenshot({ path, fullPage: true }); await testInfo.attach(name, { path, contentType: "image/png" }); } + +async function ensureTrackExpanded(page: Page, name: string, content: Locator): Promise { + const disclosure = page.getByRole("button", { name }); + await expect(disclosure).toBeVisible({ timeout: 30_000 }); + if (!(await content.isVisible())) { + await disclosure.click(); + } + await expect(content).toBeVisible({ timeout: 30_000 }); +}