mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
* test(app/e2e): stream auto-scroll and working-indicator→copy-button (Cluster G5) Wire in the unused agent-bottom-anchor helpers and add two new agent stream UI specs: auto-scroll stays pinned to the bottom across token bursts, and the inline working-indicator transitions to a copy-button when the stream ends. Both tests use the mock provider so there is no real LLM dependency in CI. Adds three helpers to helpers/agent-stream.ts: - expectInlineWorkingIndicator - expectTurnCopyButton - expectScrolledToBottom (wraps agent-bottom-anchor) * fixup: address review blockers and nits - Replace expectScrolledToBottom passthrough with expectScrollFollowsNewContent that encapsulates readScrollMetrics → waitForContentGrowth → expectNearBottom - Remove direct agent-bottom-anchor imports from spec body (DSL leak) - Add awaitAssistantMessage before expectInlineWorkingIndicator to anchor on real content before asserting the working indicator - Add comment to expectInlineWorkingIndicator explaining why testId is used (animated spinner View has no ARIA role)
36 lines
1.5 KiB
TypeScript
36 lines
1.5 KiB
TypeScript
import { expect, type Page } from "@playwright/test";
|
|
import { readScrollMetrics, waitForContentGrowth, expectNearBottom } from "./agent-bottom-anchor";
|
|
|
|
export async function awaitAssistantMessage(page: Page, hasText?: string | RegExp): Promise<void> {
|
|
const messages = page.getByTestId("assistant-message");
|
|
const target = hasText === undefined ? messages.first() : messages.filter({ hasText }).first();
|
|
await expect(target).toBeVisible({ timeout: 30_000 });
|
|
}
|
|
|
|
export async function awaitToolCall(page: Page, toolName: string | RegExp): Promise<void> {
|
|
await expect(
|
|
page.getByTestId("tool-call-badge").filter({ hasText: toolName }).first(),
|
|
).toBeVisible({ timeout: 30_000 });
|
|
}
|
|
|
|
export async function expectAgentIdle(page: Page, timeout = 30_000): Promise<void> {
|
|
await expect(page.getByRole("button", { name: /stop|cancel/i })).toHaveCount(0, { timeout });
|
|
}
|
|
|
|
// The working indicator is an animated spinner View — no semantic ARIA role, testId is correct.
|
|
export async function expectInlineWorkingIndicator(page: Page): Promise<void> {
|
|
await expect(page.getByTestId("turn-working-indicator")).toBeVisible({ timeout: 30_000 });
|
|
}
|
|
|
|
export async function expectTurnCopyButton(page: Page): Promise<void> {
|
|
await expect(page.getByRole("button", { name: "Copy turn" }).first()).toBeVisible({
|
|
timeout: 30_000,
|
|
});
|
|
}
|
|
|
|
export async function expectScrollFollowsNewContent(page: Page): Promise<void> {
|
|
const { contentHeight } = await readScrollMetrics(page);
|
|
await waitForContentGrowth(page, contentHeight);
|
|
await expectNearBottom(page);
|
|
}
|