Files
stack/apps/web/src/components/widgets/__tests__/AgentStatusWidget.test.tsx
Jason Woltje 27bbbe79df
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/pr/woodpecker Pipeline failed
feat(#233): Connect agent dashboard to real orchestrator API
- Add GET /agents endpoint to orchestrator controller
- Update AgentStatusWidget to fetch from real API instead of mock data
- Add comprehensive tests for listAgents endpoint
- Auto-refresh agent list every 30 seconds
- Display agent status with proper icons and formatting
- Show error states when API is unavailable

Fixes #233

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-05 12:31:07 -06:00

154 lines
4.1 KiB
TypeScript

import { render, screen, waitFor } from "@testing-library/react";
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { AgentStatusWidget } from "../AgentStatusWidget";
describe("AgentStatusWidget", () => {
const mockFetch = vi.fn();
beforeEach(() => {
global.fetch = mockFetch as unknown as typeof fetch;
});
afterEach(() => {
vi.clearAllMocks();
});
it("should render loading state initially", () => {
mockFetch.mockImplementation(
// eslint-disable-next-line @typescript-eslint/no-empty-function
() => new Promise(() => {}) // Never resolves
);
render(<AgentStatusWidget id="test-widget" config={{}} />);
expect(screen.getByText("Loading agents...")).toBeInTheDocument();
});
it("should fetch and display agents from API", async () => {
const mockAgents = [
{
agentId: "agent-1",
taskId: "task-1",
status: "running",
agentType: "worker",
spawnedAt: new Date().toISOString(),
},
{
agentId: "agent-2",
taskId: "task-2",
status: "completed",
agentType: "reviewer",
spawnedAt: new Date().toISOString(),
completedAt: new Date().toISOString(),
},
];
mockFetch.mockResolvedValue({
ok: true,
json: () => Promise.resolve(mockAgents),
});
render(<AgentStatusWidget id="test-widget" config={{}} />);
await waitFor(() => {
expect(screen.getByText("Worker Agent")).toBeInTheDocument();
expect(screen.getByText("Code Review Agent")).toBeInTheDocument();
});
expect(screen.getByText("Task: task-1")).toBeInTheDocument();
expect(screen.getByText("Task: task-2")).toBeInTheDocument();
});
it("should display error message when fetch fails", async () => {
mockFetch.mockResolvedValue({
ok: false,
statusText: "Internal Server Error",
});
render(<AgentStatusWidget id="test-widget" config={{}} />);
await waitFor(() => {
expect(screen.getByText(/Failed to fetch agents: Internal Server Error/)).toBeInTheDocument();
});
});
it("should display no agents message when list is empty", async () => {
mockFetch.mockResolvedValue({
ok: true,
json: () => Promise.resolve([]),
});
render(<AgentStatusWidget id="test-widget" config={{}} />);
await waitFor(() => {
expect(screen.getByText("No agents running")).toBeInTheDocument();
});
});
it("should display agent error messages", async () => {
const mockAgents = [
{
agentId: "agent-1",
taskId: "task-1",
status: "failed",
agentType: "tester",
spawnedAt: new Date().toISOString(),
error: "Test execution failed",
},
];
mockFetch.mockResolvedValue({
ok: true,
json: () => Promise.resolve(mockAgents),
});
render(<AgentStatusWidget id="test-widget" config={{}} />);
await waitFor(() => {
expect(screen.getByText("Test execution failed")).toBeInTheDocument();
});
});
it("should display correct stats summary", async () => {
const mockAgents = [
{
agentId: "agent-1",
taskId: "task-1",
status: "running",
agentType: "worker",
spawnedAt: new Date().toISOString(),
},
{
agentId: "agent-2",
taskId: "task-2",
status: "running",
agentType: "reviewer",
spawnedAt: new Date().toISOString(),
},
{
agentId: "agent-3",
taskId: "task-3",
status: "failed",
agentType: "tester",
spawnedAt: new Date().toISOString(),
},
];
mockFetch.mockResolvedValue({
ok: true,
json: () => Promise.resolve(mockAgents),
});
render(<AgentStatusWidget id="test-widget" config={{}} />);
await waitFor(() => {
// Check stats: 3 total, 2 working, 0 idle, 1 error
const stats = screen.getAllByText(/^[0-9]+$/);
expect(stats[0]).toHaveTextContent("3"); // Total
expect(stats[1]).toHaveTextContent("2"); // Working
expect(stats[2]).toHaveTextContent("0"); // Idle
expect(stats[3]).toHaveTextContent("1"); // Error
});
});
});