Files
openworker/surfaces/gui/e2e/team.spec.ts
T
Rohit C Prasad 844a6510a2 Dogfood round 1: propose_work_items gate, team-tie survives turn saves, board wakes render as cards
Leads lose propose_plan (trait-derived exclusion — plan mode is meaningless without execution tools) and gain propose_work_items: mode-independent decomposition whose approval creates the items.
Team field moves off the turn-save upsert to a dedicated setter (workers detached from their lead after one turn); board deliveries carry a MessageSource sidecar; test-worker prefers project-local tool installs.
2026-08-16 15:43:06 -07:00

87 lines
4.0 KiB
TypeScript

// Agent teams (OPE-97): the staffing gate + the sidebar's expandable team entry.
// The fake lead proposes a roster on "staff the team" and suspends; approval
// "pre-spawns" workers (the fixture mirrors create_team by adding worker sessions),
// which then nest under the lead's ONE expandable RECENT entry.
import { expect } from "@playwright/test";
import { test } from "./fixtures";
async function proposeTeam(page: import("@playwright/test").Page) {
await page.goto("/");
await page.getByPlaceholder(/Ask the coworker/).fill("staff the team");
await page.getByRole("button", { name: "Send" }).click();
await expect(page.getByTestId("teamreq-card")).toBeVisible();
}
test("the decomposition gate shows items with criteria; approval lands them on the board", async ({
page,
}) => {
await page.goto("/");
await page.getByPlaceholder(/Ask the coworker/).fill("propose the split");
await page.getByRole("button", { name: "Send" }).click();
const card = page.getByTestId("itemsreq-card");
await expect(card).toBeVisible();
await expect(card).toContainText("Proposed work items — 4");
await expect(card).toContainText("Done when:");
// 3 visible + expander with the true remainder
await expect(card.getByText("Verification pass")).toHaveCount(0);
await card.getByRole("button", { name: /1 more item/ }).click();
await expect(card.getByText("Verification pass")).toBeVisible();
await page.getByTestId("itemsreq-approve").click();
await expect(page.getByText(/Items created on the board/)).toBeVisible();
await expect(page.getByTestId("board-rail")).toBeVisible();
});
test("declining the split returns feedback to the lead", async ({ page }) => {
await page.goto("/");
await page.getByPlaceholder(/Ask the coworker/).fill("propose the split");
await page.getByRole("button", { name: "Send" }).click();
await page.getByTestId("itemsreq-card").waitFor();
await page.getByRole("button", { name: "Not now" }).click();
await expect(page.getByText(/reworking the split/)).toBeVisible();
});
test("the staffing gate shows the roster and the grant sentence", async ({ page }) => {
await proposeTeam(page);
const card = page.getByTestId("teamreq-card");
await expect(card).toContainText("Proposed team — 3 workers");
await expect(card).toContainText("swe-worker");
await expect(card).toContainText("implementation");
await expect(card).toContainText("test-worker");
await expect(card).toContainText(
"Approving grants the lead create, assign & steer — this team only, revocable.",
);
});
test("declining the roster returns the turn to the lead", async ({ page }) => {
await proposeTeam(page);
await page.getByRole("button", { name: "Not now" }).click();
await expect(page.getByText(/tell me how to change the roster/)).toBeVisible();
await expect(page.getByTestId("teamreq-card")).toHaveCount(0);
});
test("approval creates the team; workers nest under the lead's expandable entry", async ({
page,
}) => {
await proposeTeam(page);
await page.getByTestId("teamreq-approve").click();
await expect(page.getByText(/Team created/)).toBeVisible();
// The workers exist as sessions now — but never as top-level RECENT rows.
// (The sidebar refreshes on its 5s poll, so allow one full cycle.)
await expect(page.getByTestId("team-toggle-sess-lead")).toBeVisible({ timeout: 12_000 });
await expect(page.getByText("Build the statements page")).toBeVisible();
await expect(page.getByTestId("team-children-sess-lead")).toHaveCount(0);
await page.getByTestId("team-toggle-sess-lead").click();
const children = page.getByTestId("team-children-sess-lead");
await expect(children).toBeVisible();
await expect(children).toContainText("swe-worker · #1 in progress");
await expect(children).toContainText("design-worker · idle");
await expect(children).toContainText("test-worker · #4 blocked");
// Collapse hides them again — the team is one entry, not a panel.
await page.getByTestId("team-toggle-sess-lead").click();
await expect(page.getByTestId("team-children-sess-lead")).toHaveCount(0);
});