mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-22 02:15:26 -06:00
2915e563d6
* feat(workboard): full-board dashboard widget
Adds a third trusted plugin widget kind, workboard:board, rendering the
complete Kanban board (all columns, live plugin.workboard.changed
refresh) inside a session dashboard. Props {boardId} scope it to one
board; without it the widget shows every board, matching workboard:mini
semantics. Card rendering reuses the workboard page renderColumn with an
explicit surface option so page and widget cannot drift; the shared
board filter moved to ui/src/lib/workboard/board-filter.ts. Mutations
follow the connection's canMutate; read-only connections get a
view-only board.
Proof: pnpm test ui/src/lib/board ui/src/pages/workboard
ui/src/lib/workboard extensions/workboard (9,494 passed), i18n baseline
green, autoreview clean (codex/gpt-5.6-sol). tsgo core/ui/extensions
green locally; remote check:changed blocked by Daytona capacity and the
tsgo:core Daytona exit reproduced locally as a heavy-check lock race,
passing on retry.
* test(ui): seed workboard fixtures in the mocked dev server
* fix(ci): register workboard proof capture script
90 lines
3.2 KiB
TypeScript
90 lines
3.2 KiB
TypeScript
#!/usr/bin/env node
|
|
import { mkdir } from "node:fs/promises";
|
|
import path from "node:path";
|
|
import { chromium } from "playwright";
|
|
import {
|
|
canRunPlaywrightChromium,
|
|
resolvePlaywrightChromiumExecutablePath,
|
|
} from "../ui/src/test-helpers/control-ui-e2e.ts";
|
|
|
|
const DEFAULT_BASE_URL = "http://127.0.0.1:5187";
|
|
const DEFAULT_OUTPUT_DIR = path.resolve(".artifacts/control-ui-e2e/workboard-proof");
|
|
const WORKBOARD_SESSION_KEY = "agent:main:workboard-proof";
|
|
|
|
function readOption(name: string): string | undefined {
|
|
const prefix = `--${name}=`;
|
|
const inline = process.argv.slice(2).find((arg) => arg.startsWith(prefix));
|
|
if (inline) {
|
|
return inline.slice(prefix.length);
|
|
}
|
|
const index = process.argv.indexOf(`--${name}`);
|
|
return index >= 0 ? process.argv[index + 1] : undefined;
|
|
}
|
|
|
|
const baseUrl = new URL(readOption("base-url") ?? DEFAULT_BASE_URL);
|
|
const outputDir = path.resolve(readOption("output-dir") ?? DEFAULT_OUTPUT_DIR);
|
|
const executablePath = resolvePlaywrightChromiumExecutablePath(chromium.executablePath());
|
|
if (!canRunPlaywrightChromium(executablePath)) {
|
|
throw new Error(`Playwright Chromium is unavailable at ${executablePath}`);
|
|
}
|
|
|
|
await mkdir(outputDir, { recursive: true });
|
|
const browser = await chromium.launch({ executablePath });
|
|
const context = await browser.newContext({
|
|
colorScheme: "light",
|
|
reducedMotion: "reduce",
|
|
viewport: { width: 1440, height: 900 },
|
|
});
|
|
const page = await context.newPage();
|
|
page.setDefaultTimeout(30_000);
|
|
|
|
const gatewayUrl = new URL(baseUrl);
|
|
gatewayUrl.protocol = gatewayUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
const settingsKey = `openclaw.control.settings.v1:${gatewayUrl.origin}`;
|
|
await page.addInitScript(
|
|
({ key, sessionKey }) => {
|
|
localStorage.setItem(
|
|
key,
|
|
JSON.stringify({
|
|
boardSessionViews: { [sessionKey]: { activeTabId: "main" } },
|
|
theme: "light",
|
|
}),
|
|
);
|
|
},
|
|
{ key: settingsKey, sessionKey: WORKBOARD_SESSION_KEY },
|
|
);
|
|
|
|
try {
|
|
await page.goto(new URL("/workboard/peter-tasks", baseUrl).toString());
|
|
const automationChip = page.locator(".workboard-automation-chip");
|
|
await automationChip.waitFor();
|
|
if ((await automationChip.textContent())?.trim() !== "Automation") {
|
|
throw new Error("Workboard automation chip did not render its expected label");
|
|
}
|
|
await page.getByText("Prepare launch readiness checklist", { exact: true }).waitFor();
|
|
await page.screenshot({
|
|
animations: "disabled",
|
|
path: path.join(outputDir, "workboard-chip.png"),
|
|
});
|
|
|
|
await page.goto(new URL("/dashboard", baseUrl).toString());
|
|
const widget = page.locator('[data-test-id="workboard-board-widget"]');
|
|
await widget.waitFor();
|
|
await page.getByText("Validate onboarding flow", { exact: true }).waitFor();
|
|
await page.getByText("Review accessibility audit", { exact: true }).waitFor();
|
|
await page.locator(".board-session-surface--dock-hidden").waitFor();
|
|
const columnCount = await widget.locator(".workboard-column").count();
|
|
if (columnCount !== 6) {
|
|
throw new Error(`Expected 6 Workboard columns, received ${columnCount}`);
|
|
}
|
|
await page.screenshot({
|
|
animations: "disabled",
|
|
path: path.join(outputDir, "workboard-widget.png"),
|
|
});
|
|
} finally {
|
|
await context.close();
|
|
await browser.close();
|
|
}
|
|
|
|
console.log(`[workboard-ui-proof] ${outputDir}`);
|