This repository has been archived on 2026-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
orchestrator/agent-team/web/src/components/TaskList.test.tsx
Adam Moussa 677f3d3c71 feat(agent-team): React/Vite status-dashboard SPA
New web/ SPA (React 18 + Vite 5 + TypeScript + React Flow + dagre, all pinned, no
CDN). Dark, three-pane layout: summary top bar, filterable task list, center
auto-laid pipeline map, and a right drawer showing a selected task's history
through each node (timeline with timestamps/duration/cost + Q&A/verdicts/plan).
Map nodes color by live state, loop-backs render dashed, clicking a node filters
the list, selecting a task highlights its path. Polls /api/state every 4s;
topology fetched once. dist/ is gitignored (built on the Mac, rsynced).
2026-06-23 17:15:23 -04:00

74 lines
2.7 KiB
TypeScript

import { fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { TaskList } from "./TaskList";
import type { StateResponse, Topology } from "../api";
const TOPO: Topology = {
trees: [
{ id: "core", label: "Core" },
{ id: "sdlc", label: "SDLC" },
],
nodes: [
{ id: "intake", label: "Intake", agent: "coordinator", tree: "core", kind: "phase", gated: false },
{ id: "plan", label: "Plan", agent: "Claude", tree: "sdlc", kind: "phase", gated: false },
],
edges: [],
};
function makeState(): StateResponse {
return {
ok: true,
error: null,
generated_at: "now",
db_path: "x",
tasks: [
{ thread_id: "aaaa1111", short_id: "aaaa1111", task: "remediate CVE", current_phase: "plan", status: "active", waiting: false, waiting_since: null },
{ thread_id: "bbbb2222", short_id: "bbbb2222", task: "fix login bug", current_phase: "intake", status: "parked", waiting: false, waiting_since: null },
],
waiting: [],
question_counts: {},
summary: { active: 1, parked: 1, waiting: 0, open_questions: 0, total: 2 },
budget: { available: false },
nodes: {},
};
}
describe("TaskList", () => {
it("renders all tasks", () => {
render(
<TaskList state={makeState()} topology={TOPO} selectedId={null} nodeFilter={null}
onSelect={() => {}} onClearNodeFilter={() => {}} />,
);
expect(screen.getByText("remediate CVE")).toBeInTheDocument();
expect(screen.getByText("fix login bug")).toBeInTheDocument();
});
it("filters by status", () => {
render(
<TaskList state={makeState()} topology={TOPO} selectedId={null} nodeFilter={null}
onSelect={() => {}} onClearNodeFilter={() => {}} />,
);
fireEvent.change(screen.getByLabelText("Filter by status"), { target: { value: "parked" } });
expect(screen.queryByText("remediate CVE")).not.toBeInTheDocument();
expect(screen.getByText("fix login bug")).toBeInTheDocument();
});
it("honors a node filter (map click)", () => {
render(
<TaskList state={makeState()} topology={TOPO} selectedId={null} nodeFilter="plan"
onSelect={() => {}} onClearNodeFilter={() => {}} />,
);
expect(screen.getByText("remediate CVE")).toBeInTheDocument();
expect(screen.queryByText("fix login bug")).not.toBeInTheDocument();
});
it("fires onSelect when a row is clicked", () => {
const onSelect = vi.fn();
render(
<TaskList state={makeState()} topology={TOPO} selectedId={null} nodeFilter={null}
onSelect={onSelect} onClearNodeFilter={() => {}} />,
);
fireEvent.click(screen.getByText("remediate CVE"));
expect(onSelect).toHaveBeenCalledWith("aaaa1111");
});
});