Files
paseo/packages/app/e2e/helpers/project-status-badge.ts
T
Mohamed BoudraandGitHub ccb668b3b4 Improve sidebar workspace readability and host identity (#2790)
* fix(app): align turn footer actions

Keep running-turn actions in the same position as completed-turn actions and use the shared small icon size for both copy and fork controls.

* feat(app): improve sidebar workspace identity

Make dense sidebar workspace rows easier to scan and let each device control how connected hosts are identified.

* fix(app): keep host badges readable

Use a compact display menu and keep identity color on the host icon so translated controls fit and badge text retains standard contrast.

* fix(app): announce selected sidebar badge mode

* fix(app): retain icon-only host names for screen readers

* fix(app): name hoisted workspace rows

* fix(app): retain host identity in workspace labels

* fix(app): retain workspace status in row labels

* fix(app): defer host appearance until identity resolves

* fix(app): serialize host appearance writes

* fix(app): serialize host registry writes

* fix(app): bound sidebar host badge labels

* test(app): match workspace status labels

* fix(app): consolidate sidebar identity behavior

* test(app): assert status grouping behavior

* fix(app): keep sidebar row actions accessible

* fix(app): stabilize optimistic message layout
2026-08-02 16:58:20 +02:00

113 lines
3.5 KiB
TypeScript

import { expect, type Page } from "@playwright/test";
import { gotoAppShell } from "../support/helpers/app";
import { seedWorkspace, type SeededWorkspace } from "../support/helpers/seed-client";
import { waitForSidebarHydration } from "../support/helpers/workspace-ui";
export interface StatusProject {
seed: SeededWorkspace;
needsInputWorkspaceId: string;
}
export async function seedStatusProject(): Promise<StatusProject> {
const seed = await seedWorkspace({
repoPrefix: "project-status-badge-",
title: "Working workspace",
});
const created = await seed.client.createWorkspace({
source: { kind: "directory", path: seed.repoPath, projectId: seed.projectId },
title: "Needs input workspace",
});
if (!created.workspace) {
await seed.cleanup();
throw new Error(created.error ?? "Failed to create the needs-input workspace");
}
return { seed, needsInputWorkspaceId: created.workspace.id };
}
export async function openAndCollapseStatusProject(
page: Page,
project: StatusProject,
): Promise<void> {
await gotoAppShell(page);
await waitForSidebarHydration(page);
await projectRow(page, project).click();
await page.mouse.move(1200, 850);
await expect(workspaceRow(page, "Working workspace")).toHaveCount(0);
}
export async function expandStatusProject(page: Page, project: StatusProject): Promise<void> {
await projectRow(page, project).click();
await expect(workspaceRow(page, "Working workspace")).toBeVisible();
}
export async function startWorkingWorkspace(project: StatusProject): Promise<void> {
await project.seed.client.createAgent({
provider: "mock",
cwd: project.seed.repoPath,
workspaceId: project.seed.workspaceId,
title: "Working agent",
modeId: "load-test",
model: "thirty-minute-stream",
initialPrompt: "keep streaming for the test",
});
}
export async function startNeedsInputWorkspace(project: StatusProject): Promise<void> {
await project.seed.client.createAgent({
provider: "mock",
cwd: project.seed.repoPath,
workspaceId: project.needsInputWorkspaceId,
title: "Needs input agent",
modeId: "load-test",
model: "thirty-minute-stream",
initialPrompt: "emit a synthetic plan approval",
});
}
export async function expectCollapsedProjectStatus(
page: Page,
project: StatusProject,
status: "Working" | "Needs input",
): Promise<void> {
await expect(projectRow(page, project).getByRole("status", { name: status })).toBeVisible({
timeout: 60_000,
});
}
export async function expectProjectStatusHidden(page: Page, project: StatusProject): Promise<void> {
await expect(projectRow(page, project).getByRole("status")).toHaveCount(0, {
timeout: 60_000,
});
}
export async function expectWorkspaceStatus(
page: Page,
workspaceName: string,
status: "running" | "needs_input",
): Promise<void> {
await expect(
workspaceRow(page, workspaceName).getByTestId(`workspace-status-indicator-${status}`),
).toBeVisible({ timeout: 60_000 });
}
function projectGroup(page: Page, project: StatusProject) {
return page.getByRole("group", { name: project.seed.projectDisplayName, exact: true });
}
function projectRow(page: Page, project: StatusProject) {
return projectGroup(page, project)
.getByRole("button")
.filter({ hasText: project.seed.projectDisplayName })
.first();
}
function workspaceRow(page: Page, workspaceName: string) {
return page.getByRole("button", {
name: new RegExp(`^${escapeRegExp(workspaceName)}(?:,|$)`),
});
}
function escapeRegExp(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}