.agents/skills/control-ui-e2e/SKILL.md
Use this for Control UI changes that need a real browser flow with deterministic Gateway data.
ui/src/**/*.e2e.test.ts for full GUI flows.ui/src/test-helpers/control-ui-e2e.ts to start the Vite Control UI and install a mocked Gateway WebSocket..browser.test.ts or unit tests for narrow rendering logic; use this E2E lane when the proof should cover routing, app boot, Gateway handshake, requests, and visible UI behavior together.node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner ui/src/ui/e2e/chat-flow.e2e.test.ts
pnpm test:ui:e2e
If dependencies are missing in a Codex worktree, install once with pnpm install; for broad GUI proof or dependency-heavy checks, use Testbox/Crabbox instead of running a wide local pnpm lane.
When running mocked Control UI/dashboard validation for a user-facing feature, produce visual proof by default unless the user explicitly opts out.
pnpm dev:ui:mock -- --port <port>.browser.newContext({ recordVideo: { dir, size }, viewport }), page.screenshot({ path }), and close the context before reporting the video path..artifacts/control-ui-e2e/<short-feature-name>/ or another clearly named local temp directory, and report the absolute paths in the final answer.Start the app server, install the mock before page.goto, then assert both Gateway traffic and visible UI:
const server = await startControlUiE2eServer();
const page = await context.newPage();
const gateway = await installMockGateway(page, {
historyMessages: [{ role: "assistant", content: [{ type: "text", text: "Ready." }] }],
});
await page.goto(`${server.baseUrl}chat`);
await page.locator(".agent-chat__composer-combobox textarea").fill("hello");
await page.getByRole("button", { name: "Send message" }).click();
const request = await gateway.waitForRequest("chat.send");
await gateway.emitChatFinal({ runId: String(request.params.idempotencyKey), text: "Done." });
await page.getByText("Done.").waitFor();
Extend installMockGateway with typed scenario options or method responses when a new flow needs more Gateway surface.