import { mkdtemp, mkdir, writeFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import type { Locator, TestInfo } from "@playwright/test";
import { test, expect, type Page } from "@playwright/test";
import { gotoAppShell } from "./app";
import { buildAgentRoute } from "./mock-agent";
import { openCommandCenter } from "./command-center";
import {
closeCompactWorkspaceMenu,
compactWorkspaceMenu,
goBackInMenu,
openCompactWorkspaceMenu,
} from "./compact-workspace-scripts";
import { connectNewWorkspaceDaemonClient } from "./new-workspace";
import { seedWorkspace } from "./seed-client";
import { pluginRequirements } from "./plugin-fixture";
const PLUGIN_ID = "button-showcase";
const WIDE = { width: 1440, height: 900 };
const COMPACT = { width: 390, height: 844 };
function clientSource(workspaceId: string, agentId: string): string {
return `import React from "react";
import { Text, View, Pressable } from "react-native";
import { useWorkspace, useRpc, usePaseo } from "@getpaseo/plugin/client";
import { useQuery } from "@tanstack/react-query";
import { summary } from "./shared/rpc";
function StatusIcon({ size, theme }) {
return ;
}
function Details({ workspaceId, theme, layout, close }) {
const workspace = useWorkspace(workspaceId, (workspace) => workspace.name);
const paseo = usePaseo();
const [ownerId, setOwnerId] = React.useState("");
const [updates, setUpdates] = React.useState(0);
const [failed, setFailed] = React.useState(false);
React.useEffect(() => {
const owner = paseo.observeEvents(["project.update"]);
owner.subscribe({ snapshot(value) { setOwnerId(value.subscriptionId); }, update() { setUpdates((n) => n + 1); } });
return () => { void owner.release(); };
}, [paseo]);
const rpc = useRpc(summary);
const query = useQuery({ queryKey: ["summary"], queryFn: () => rpc({}) });
if (failed) throw new Error("Button content failed");
return
{ownerId}
Observed updates: {updates}
setFailed(true)}>Fail content
Deployment status
{workspace}
{query.data?.message ?? "Loading deployment..."}
3 checks passed ยท Production
Presentation: {layout.compact ? "compact" : "wide"}
Done
;
}
export default function contribute(client) {
const workspaceId = ${JSON.stringify(workspaceId)};
const agentId = ${JSON.stringify(agentId)};
const registrations = [];
let finish = () => {};
let finishReview = () => {};
let attempts = 0;
const action = { kind: "action", async onPress() {
if (++attempts % 2 === 1) throw new Error("Deployment failed. Try again.");
await new Promise((resolve) => { finish = resolve; });
deploy.update({ label: "Deployed" });
} };
const header = (id, button) => { const registration = client.addHeaderButton({ id, workspaceId, button }); registrations.push(registration); return registration; };
const pill = (id, button) => { const registration = client.addComposerPill({ id, workspaceId, agentId, button }); registrations.push(registration); return registration; };
const menu = { kind: "menu", items: [
{ kind: "item", id: "run", title: "Run checks", icon: "Play", behavior: { kind: "action", onPress() { checks.update({ label: "Checks passed" }); } } },
{ kind: "separator", id: "divider" },
{ kind: "item", id: "environment", title: "Environment", behavior: { kind: "menu", items: [
{ kind: "item", id: "staging", title: "Staging", icon: "FlaskConical", behavior: { kind: "action", onPress() {} } },
{ kind: "item", id: "production", title: "Production", icon: "Globe", disabled: true, behavior: { kind: "action", onPress() {} } },
] } },
{ kind: "item", id: "details", title: "Deployment details", icon: "Activity", behavior: { kind: "popover", Content: Details } },
] };
const deploy = header("deploy", { title: "Deploy application", icon: "Rocket", label: "Deploy", behavior: action });
const checks = header("checks", { title: "Header checks", icon: "ListChecks", label: "Checks", behavior: menu });
header("status", { title: "Header status", icon: StatusIcon, label: "Healthy", behavior: { kind: "popover", Content: Details } });
header("logs", { title: "Open deployment logs", icon: "ScrollText", behavior: { kind: "popover", Content: Details } });
header("locked", { title: "Production locked", icon: "Lock", disabled: true, behavior: { kind: "action", onPress() {} } });
const review = pill("review", { title: "Run review", icon: "Scan", label: "Review", behavior: { kind: "action", async onPress() { await new Promise((resolve) => { finishReview = resolve; }); review.update({ label: "Reviewed" }); } } });
const pillMenu = pill("checks", { title: "Composer checks", icon: "ListChecks", label: "Checks", behavior: menu });
pill("usage", { title: "Composer status", icon: StatusIcon, label: "Status", behavior: { kind: "popover", Content: Details } });
const command = (id, title, onSelect) => client.addCommandCenterItem({ id, title, icon: "Settings", context: "workspace", onSelect });
command("finish", "Finish deployment", () => finish());
command("finish-review", "Finish review", () => finishReview());
command("hide-deploy", "Hide deployment button", () => deploy.update({ visible: false }));
command("show-deploy", "Show deployment button", () => deploy.update({ visible: true }));
command("hide", "Hide review button", () => review.update({ visible: false }));
command("show", "Show review button", () => review.update({ visible: true, label: "Review ready" }));
command("disable", "Disable example buttons", () => { deploy.update({ disabled: true }); review.update({ disabled: true }); });
command("enable", "Enable example buttons", () => { deploy.update({ disabled: false }); review.update({ disabled: false }); });
command("icon-only", "Use icon-only header", () => deploy.update({ label: undefined }));
command("hide-menu", "Hide composer menu", () => pillMenu.update({ visible: false }));
command("show-menu", "Show composer menu", () => pillMenu.update({ visible: true }));
const lifetime = new AbortController();
const applyWorkspace = (workspace) => {
if (workspace.id !== workspaceId) return;
deploy.update({ visible: workspace.name !== "Compact checks" });
pillMenu.update({ visible: workspace.name !== "Hide composer menu" });
};
void client.paseo.workspaces.list({ subscribe: {}, signal: lifetime.signal }).then(({ subscription }) => {
subscription.subscribe({
snapshot({ entries }) { for (const workspace of entries) applyWorkspace(workspace); },
update(message) { if (message.type === "workspace_update" && message.payload.kind === "upsert") applyWorkspace(message.payload.workspace); },
});
}).catch((error) => { if (!lifetime.signal.aborted) console.error(error); });
return () => { lifetime.abort(); finish(); finishReview(); for (const registration of registrations) registration.remove(); };
}`;
}
async function installShowcase(workspaceId: string, agentId: string) {
const client = await connectNewWorkspaceDaemonClient({ ownProjects: false });
const config = await client.getDaemonConfig();
const directory = await mkdtemp(path.join(tmpdir(), "paseo-buttons-"));
await mkdir(path.join(directory, "shared"));
await writeFile(
path.join(directory, "paseo-plugin.json"),
JSON.stringify({ id: PLUGIN_ID, requirements: pluginRequirements }),
);
await writeFile(path.join(directory, "index.client.tsx"), clientSource(workspaceId, agentId));
await writeFile(
path.join(directory, "shared/rpc.ts"),
`import { defineRpc } from "@getpaseo/plugin"; import { z } from "zod"; export const summary = defineRpc({ name: "summary", input: z.object({}), output: z.object({ message: z.string() }) });`,
);
await writeFile(
path.join(directory, "index.server.ts"),
`import { summary } from "./shared/rpc"; export default function contribute(server) { server.handle(summary, async () => ({ message: "All systems operational" })); return () => {}; }`,
);
await client.patchDaemonConfig({ pluginsEnabled: true });
await client.installDirectoryPlugin(directory);
return {
disable: () => client.disablePlugin(PLUGIN_ID),
setTitle: (title: string) => client.setWorkspaceTitle(workspaceId, title),
async cleanup() {
await client.removePlugin(PLUGIN_ID);
await client.patchDaemonConfig({ pluginsEnabled: config.config.pluginsEnabled });
await client.close();
await rm(directory, { recursive: true, force: true });
},
};
}
async function press(page: Page, title: string) {
await page.getByRole("button", { name: title, exact: true }).click();
}
async function openHeaderOverflow(page: Page) {
await page
.getByRole("toolbar", { name: "Workspace actions", exact: true })
.getByRole("button", { name: "More actions", exact: true })
.click();
}
async function choose(page: Page, title: string) {
await page.getByRole("menuitem", { name: title, exact: true }).click();
}
async function command(page: Page, title: string) {
const panel = await openCommandCenter(page);
await panel.getByTestId("command-center-input").fill(title);
await panel.getByRole("button", { name: title, exact: true }).click();
await expect(panel).not.toBeVisible();
}
/** The command center opens from the sidebar, which compact layouts keep closed. */
async function commandFromCompact(page: Page, title: string) {
await page.setViewportSize(WIDE);
await command(page, title);
await page.setViewportSize(COMPACT);
}
async function expectSurfaceVisible(
page: Page,
subject: Locator = page.getByRole("toolbar", { name: "Workspace actions", exact: true }),
) {
await expect(subject).toBeInViewport();
}
async function expectDetails(page: Page) {
await expect(page.getByText("All systems operational", { exact: true })).toBeInViewport();
}
function workspaceMenuRow(page: Page, title: string): Locator {
return compactWorkspaceMenu(page).getByRole("menuitem", { name: title, exact: true });
}
async function expectWorkspaceMenuRows(page: Page, titles: readonly string[]) {
const rows = compactWorkspaceMenu(page).getByRole("menuitem");
for (const [index, title] of titles.entries()) {
await expect(rows.nth(index)).toHaveAccessibleName(title);
}
}
async function chooseInWorkspaceMenu(page: Page, title: string) {
await workspaceMenuRow(page, title).click();
}
async function expectWorkspaceMenuClosed(page: Page) {
await expect(compactWorkspaceMenu(page)).toBeHidden({ timeout: 10_000 });
}
async function expectCompactDetails(page: Page) {
const menu = compactWorkspaceMenu(page);
await expect(menu.getByText("All systems operational", { exact: true })).toBeInViewport();
await expect(menu.getByText("Presentation: compact", { exact: true })).toBeVisible();
}
/** Resolves once `subject` renders the same pixels twice in a row: entering animations are done. */
async function expectStill(subject: Locator) {
let previous: Buffer | null = null;
await expect
.poll(
async () => {
const current = await subject.screenshot();
const still = previous !== null && current.equals(previous);
previous = current;
return still;
},
{ intervals: [150] },
)
.toBe(true);
}
/** Attaches the screen once per colour scheme, for review alongside the run. */
async function captureSchemes(page: Page, info: TestInfo, name: string, subject: Locator) {
for (const colorScheme of ["light", "dark"] as const) {
await page.emulateMedia({ colorScheme });
await expectStill(subject);
const file = info.outputPath(`${name}-${colorScheme}.png`);
await info.attach(`${name}-${colorScheme}`, {
body: await page.screenshot({ path: file }),
contentType: "image/png",
});
}
await page.emulateMedia({ colorScheme: "light" });
}
async function expectHeaderTextTruncated(page: Page) {
const title = page.getByTestId("workspace-header-title");
const subtitle = page.getByTestId("workspace-header-subtitle");
await expect(title).toHaveCSS("text-overflow", "ellipsis");
await expect(subtitle).toHaveCSS("text-overflow", "ellipsis");
// The text itself must overflow its box, rather than being clipped by an ancestor.
await expect
.poll(() => title.evaluate((element) => element.scrollWidth > element.clientWidth))
.toBe(true);
await expect
.poll(() => subtitle.evaluate((element) => element.scrollWidth > element.clientWidth))
.toBe(true);
const titleBox = await title.boundingBox();
const subtitleBox = await subtitle.boundingBox();
const actionsBox = await page
.getByRole("button", { name: "Workspace actions", exact: true })
.boundingBox();
expect(titleBox).not.toBeNull();
expect(subtitleBox).not.toBeNull();
expect(actionsBox).not.toBeNull();
expect(titleBox!.x + titleBox!.width).toBeLessThanOrEqual(actionsBox!.x);
expect(subtitleBox!.x + subtitleBox!.width).toBeLessThanOrEqual(actionsBox!.x);
const hostIcon = page.getByLabel("localhost", { exact: true }).locator("svg");
await expect.poll(async () => (await hostIcon.boundingBox())?.width).toBe(12);
}
export async function withButtonShowcase(
page: Page,
info: TestInfo,
run: (buttons: {
openWideMenusAndPopovers(): Promise;
runAndUpdateActions(): Promise;
openCompactSheets(): Promise;
useCompactWorkspaceMenu(): Promise;
hideAndUnloadOpenButtons(): Promise;
verifyObservationLifetime(): Promise;
}) => Promise,
) {
const released = new Set();
page.on("websocket", (socket) =>
socket.on("framereceived", ({ payload }) => {
if (typeof payload !== "string") return;
const frame = JSON.parse(payload);
if (frame.message?.type === "subscription.release.response")
released.add(frame.message.payload.subscriptionId);
}),
);
const workspace = await seedWorkspace({ repoPrefix: "plugin-buttons-" });
const agent = await workspace.client.createAgent({
provider: "mock",
cwd: workspace.repoPath,
workspaceId: workspace.workspaceId,
title: "Button showcase",
model: "ten-second-stream",
modeId: "load-test",
});
const showcase = await installShowcase(workspace.workspaceId, agent.id);
try {
await page.setViewportSize(WIDE);
await gotoAppShell(page);
await page.goto(buildAgentRoute(workspace.workspaceId, agent.id));
await expect(page.getByRole("button", { name: "Run review", exact: true })).toBeVisible();
await run({
verifyObservationLifetime: () =>
test.step("closing and crashing content release its owner while sibling buttons and app remain live", async () => {
await press(page, "Header status");
await expectDetails(page);
const observation = page.getByLabel("Content observation", { exact: true });
await expect(observation).not.toHaveText("");
const first = (await observation.textContent())!;
await press(page, "Close deployment details");
await expect.poll(() => released.has(first)).toBe(true);
await press(page, "Composer status");
await expectDetails(page);
const second = (await observation.textContent())!;
expect(second).not.toBe(first);
await workspace.client.renameProject(workspace.projectId, "Observer control");
await expect(page.getByText("Observed updates: 1", { exact: true })).toBeVisible();
await press(page, "Fail button content");
await expect(
page.getByText("Plugin failed: Button content failed", { exact: true }),
).toBeVisible();
await expect.poll(() => released.has(second)).toBe(true);
await page.keyboard.press("Escape");
await press(page, "Header status");
await expectDetails(page);
const recovered = (await observation.textContent())!;
expect([first, second]).not.toContain(recovered);
await showcase.setTitle("Healthy app after button failure");
await expect(page.getByTestId("workspace-header-title")).toHaveText(
"Healthy app after button failure",
);
await press(page, "Close deployment details");
await expect.poll(() => released.has(recovered)).toBe(true);
await showcase.setTitle("Button showcase");
}),
openWideMenusAndPopovers: () =>
test.step("wide buttons have placement-owned labels and chevrons", async () => {
await expect(
page
.getByRole("button", { name: "Header checks", exact: true })
.getByTestId("plugin-button-chevron"),
).toHaveCount(1);
await expect(
page
.getByRole("button", { name: "Composer checks", exact: true })
.getByTestId("plugin-button-chevron"),
).toHaveCount(0);
await expectSurfaceVisible(page);
await captureSchemes(
page,
info,
"desktop-wide-header",
page.getByRole("toolbar", { name: "Workspace actions", exact: true }),
);
await press(page, "Header checks");
await expect(
page.getByRole("menuitem", { name: "Run checks", exact: true }),
).toBeVisible();
await expectSurfaceVisible(
page,
page.getByRole("menuitem", { name: "Run checks", exact: true }),
);
await choose(page, "Environment");
await expect(page.getByRole("menuitem", { name: "Staging", exact: true })).toBeVisible();
await expectSurfaceVisible(
page,
page.getByRole("menuitem", { name: "Staging", exact: true }),
);
await choose(page, "Staging");
await openHeaderOverflow(page);
await expect(
page.getByRole("menuitem", { name: "Production locked", exact: true }),
).toBeDisabled();
await captureSchemes(
page,
info,
"desktop-overflow",
page.getByRole("menuitem", { name: "Production locked", exact: true }),
);
await expectSurfaceVisible(
page,
page.getByRole("menuitem", { name: "Production locked", exact: true }),
);
await choose(page, "Open deployment logs");
await expectDetails(page);
await press(page, "Close deployment details");
await press(page, "Header status");
await expectDetails(page);
await expectSurfaceVisible(
page,
page.getByRole("button", { name: "Close deployment details", exact: true }),
);
await press(page, "Close deployment details");
await press(page, "Composer checks");
await expectSurfaceVisible(
page,
page.getByRole("menuitem", { name: "Run checks", exact: true }),
);
await choose(page, "Deployment details");
await expectDetails(page);
await expectSurfaceVisible(
page,
page.getByRole("button", { name: "Close deployment details", exact: true }),
);
await press(page, "Close deployment details");
await press(page, "Composer status");
await expectDetails(page);
await expectSurfaceVisible(
page,
page.getByRole("button", { name: "Close deployment details", exact: true }),
);
await press(page, "Close deployment details");
}),
runAndUpdateActions: () =>
test.step("actions fail visibly, retry, and remain busy until completion", async () => {
await press(page, "Deploy application");
await expect(
page.getByText("Deployment failed. Try again.", { exact: true }),
).toBeVisible();
await expectSurfaceVisible(
page,
page.getByText("Deployment failed. Try again.", { exact: true }),
);
await press(page, "Deploy application");
await expect(
page.getByRole("button", { name: "Deploy application", exact: true }),
).toBeDisabled();
await expectSurfaceVisible(page);
await command(page, "Finish deployment");
await expect(
page.getByRole("button", { name: "Deploy application", exact: true }),
).toContainText("Deployed");
await press(page, "Run review");
await expect(
page.getByRole("button", { name: "Run review", exact: true }),
).toBeDisabled();
await expectSurfaceVisible(page);
await command(page, "Finish review");
await expect(page.getByRole("button", { name: "Run review", exact: true })).toContainText(
"Reviewed",
);
await command(page, "Disable example buttons");
await expect(
page.getByRole("button", { name: "Run review", exact: true }),
).toBeDisabled();
await expectSurfaceVisible(page);
await command(page, "Enable example buttons");
await command(page, "Use icon-only header");
await expect(
page.getByRole("button", { name: "Deploy application", exact: true }),
).toHaveText("");
await expectSurfaceVisible(page);
await expect(
page.getByText("Deployment failed. Try again.", { exact: true }),
).toHaveCount(0);
await captureSchemes(
page,
info,
"desktop-icon-only-header",
page.getByRole("toolbar", { name: "Workspace actions", exact: true }),
);
await command(page, "Hide review button");
await expect(page.getByRole("button", { name: "Run review", exact: true })).toHaveCount(
0,
);
await command(page, "Show review button");
await expect(page.getByRole("button", { name: "Run review", exact: true })).toContainText(
"Review ready",
);
}),
openCompactSheets: () =>
test.step("compact header leaves plugin actions to the workspace menu while composer triggers open sheets", async () => {
await page.setViewportSize(COMPACT);
await expect(page.getByTestId("plugin-button-chevron")).toHaveCount(0);
await expect(
page.getByRole("button", { name: "Composer checks", exact: true }),
).toContainText("Checks");
await workspace.client.renameProject(
workspace.projectId,
"Plugin buttons with a long project name",
);
await expect(page.getByTestId("workspace-header-subtitle")).toHaveText(
"Plugin buttons with a long project name",
);
await showcase.setTitle("Button showcase with a long workspace title");
await expect(page.getByTestId("workspace-header-title")).toHaveText(
"Button showcase with a long workspace title",
);
await expectHeaderTextTruncated(page);
await expect(
page.getByRole("toolbar", { name: "Workspace actions", exact: true }),
).toHaveCount(0);
await expect(
page.getByRole("button", { name: "Open menu", exact: true }),
).toBeInViewport();
await showcase.setTitle("Button showcase");
await press(page, "Composer status");
await expectDetails(page);
await expectSurfaceVisible(
page,
page.getByRole("button", { name: "Close deployment details", exact: true }),
);
await press(page, "Close deployment details");
await press(page, "Composer checks");
await expectSurfaceVisible(
page,
page.getByRole("menuitem", { name: "Run checks", exact: true }),
);
await choose(page, "Run checks");
}),
useCompactWorkspaceMenu: () =>
test.step("compact workspace menu carries header buttons with their actions, menus, and content", async () => {
await openCompactWorkspaceMenu(page);
await expectWorkspaceMenuRows(page, [
"Deploy application",
"Header checks",
"Header status",
"Open deployment logs",
"Production locked",
"Copy workspace path",
]);
await expect(workspaceMenuRow(page, "Production locked")).toBeDisabled();
// Deploy lost its label to "Use icon-only header" and logs never had one; rows read titles.
await expect(workspaceMenuRow(page, "Deploy application")).toHaveText(
"Deploy application",
);
await expect(workspaceMenuRow(page, "Open deployment logs")).toHaveText(
"Open deployment logs",
);
await captureSchemes(page, info, "compact-root-icon-only", compactWorkspaceMenu(page));
await showcase.setTitle("Compact checks");
await expect(workspaceMenuRow(page, "Deploy application")).toHaveCount(0);
await showcase.setTitle("Button showcase");
await expect(workspaceMenuRow(page, "Deploy application")).toBeVisible();
await chooseInWorkspaceMenu(page, "Deploy application");
await expectWorkspaceMenuClosed(page);
await expect(
page.getByText("Deployment failed. Try again.", { exact: true }),
).toBeVisible();
await openCompactWorkspaceMenu(page);
await chooseInWorkspaceMenu(page, "Deploy application");
await expectWorkspaceMenuClosed(page);
await openCompactWorkspaceMenu(page);
await expect(workspaceMenuRow(page, "Deploy application")).toBeDisabled();
await captureSchemes(page, info, "compact-row-states", compactWorkspaceMenu(page));
await closeCompactWorkspaceMenu(page);
await commandFromCompact(page, "Finish deployment");
await openCompactWorkspaceMenu(page);
await expect(workspaceMenuRow(page, "Deploy application")).toBeEnabled();
await captureSchemes(page, info, "compact-root", compactWorkspaceMenu(page));
await chooseInWorkspaceMenu(page, "Header checks");
await expectWorkspaceMenuRows(page, ["Run checks", "Environment", "Deployment details"]);
await captureSchemes(page, info, "compact-header-checks", compactWorkspaceMenu(page));
await goBackInMenu(page);
await expect(workspaceMenuRow(page, "Header status")).toBeVisible();
await chooseInWorkspaceMenu(page, "Header checks");
await chooseInWorkspaceMenu(page, "Environment");
await expectWorkspaceMenuRows(page, ["Staging", "Production"]);
await expect(workspaceMenuRow(page, "Production")).toBeDisabled();
await captureSchemes(page, info, "compact-environment", compactWorkspaceMenu(page));
await goBackInMenu(page);
await expect(workspaceMenuRow(page, "Run checks")).toBeVisible();
await goBackInMenu(page);
await expect(workspaceMenuRow(page, "Header checks")).toBeVisible();
await chooseInWorkspaceMenu(page, "Header checks");
await chooseInWorkspaceMenu(page, "Deployment details");
await expectCompactDetails(page);
await captureSchemes(
page,
info,
"compact-deployment-details",
compactWorkspaceMenu(page),
);
await goBackInMenu(page);
await expect(workspaceMenuRow(page, "Run checks")).toBeVisible();
await chooseInWorkspaceMenu(page, "Deployment details");
await expectCompactDetails(page);
await press(page, "Close deployment details");
await expectWorkspaceMenuClosed(page);
await openCompactWorkspaceMenu(page);
await chooseInWorkspaceMenu(page, "Header status");
await expectCompactDetails(page);
await captureSchemes(page, info, "compact-header-status", compactWorkspaceMenu(page));
await press(page, "Fail button content");
await expect(
compactWorkspaceMenu(page).getByText("Plugin failed: Button content failed", {
exact: true,
}),
).toBeVisible();
await goBackInMenu(page);
await expect(workspaceMenuRow(page, "Header status")).toBeVisible();
await chooseInWorkspaceMenu(page, "Open deployment logs");
await expectCompactDetails(page);
await captureSchemes(page, info, "compact-logs-popover", compactWorkspaceMenu(page));
await press(page, "Close deployment details");
await expectWorkspaceMenuClosed(page);
}),
hideAndUnloadOpenButtons: () =>
test.step("hiding an open button and unloading a plugin remove its surfaces", async () => {
await page.setViewportSize(WIDE);
await press(page, "Composer checks");
await showcase.setTitle("Hide composer menu");
await expect(page.getByRole("menuitem", { name: "Run checks", exact: true })).toHaveCount(
0,
);
await expect(
page.getByRole("button", { name: "Composer checks", exact: true }),
).toHaveCount(0);
await showcase.setTitle("Button showcase");
await page.emulateMedia({ colorScheme: "dark" });
await expectSurfaceVisible(page);
await press(page, "Header status");
await expectDetails(page);
await expectSurfaceVisible(
page,
page.getByRole("button", { name: "Close deployment details", exact: true }),
);
const observation = page.getByLabel("Content observation", { exact: true });
await expect(observation).not.toHaveText("");
const owner = (await observation.textContent())!;
await showcase.disable();
await expect.poll(() => released.has(owner)).toBe(true);
await expect(
page.getByRole("button", { name: "Header status", exact: true }),
).toHaveCount(0);
await expect(page.getByRole("button", { name: "Run review", exact: true })).toHaveCount(
0,
);
await expect(page.getByText("All systems operational", { exact: true })).toHaveCount(0);
await page.setViewportSize(COMPACT);
await openCompactWorkspaceMenu(page);
await expect(workspaceMenuRow(page, "Header checks")).toHaveCount(0);
await expect(workspaceMenuRow(page, "Header status")).toHaveCount(0);
await closeCompactWorkspaceMenu(page);
await page.setViewportSize(WIDE);
await showcase.setTitle("Healthy app after plugin unload");
await expect(page.getByTestId("workspace-header-title")).toHaveText(
"Healthy app after plugin unload",
);
}),
});
} finally {
await showcase.cleanup();
await workspace.cleanup();
}
}