/** * @file AgentsTable.test.tsx * @description The Sessions page's Agents tab: it asks only for agents, renders * a page of rows with session links, sorts by an allowed column on a header * click (flipping on a second), and points both export links at the filter. * @author Nguyễn Ngọc Trí Vĩ */ import { render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { MemoryRouter } from "react-router-dom"; import { beforeEach, describe, expect, it, vi } from "vitest"; import i18n from "i18next"; const { query } = vi.hoisted(() => ({ query: { page: vi.fn(), exportUrl: (p: URLSearchParams, f: string) => `/api/query?${p.toString()}&format=${f}`, }, })); vi.mock("../../lib/api", () => ({ api: { query } })); vi.mock("../../hooks/useAiTools", () => ({ useAiTools: () => ({ tools: [{ id: "codex", label: "Codex" }] }), })); import { AgentsTable } from "../AgentsTable"; const lastParams = () => { const calls = query.page.mock.calls; return calls[calls.length - 1]![0] as URLSearchParams; }; beforeEach(() => { i18n.changeLanguage("en"); vi.clearAllMocks(); query.page.mockResolvedValue({ entity: "agents", columns: ["id", "session_id", "name", "started_at"], sortable: ["started_at", "name"], statuses: ["working", "waiting", "completed", "error"], rows: [{ id: "a1", session_id: "sess-abcdef12", name: "first", started_at: "2026-10-01" }], total: 1, limit: 50, offset: 0, export_cap: 50000, }); }); describe("AgentsTable", () => { it("lists agents, sorts by an allowed column and exports the filter", async () => { const user = userEvent.setup(); render( ); expect(await screen.findByText("first")).toBeInTheDocument(); expect(lastParams().get("entity")).toBe("agents"); expect(screen.getByRole("link", { name: "sess-abc" })).toHaveAttribute( "href", "/sessions/sess-abcdef12" ); expect(screen.getByRole("button", { name: /Status/ })).toBeInTheDocument(); await user.click(screen.getByRole("button", { name: "name" })); await waitFor(() => expect(lastParams().get("sort")).toBe("name")); expect(lastParams().get("dir")).toBe("desc"); await user.click(screen.getByRole("button", { name: "name" })); await waitFor(() => expect(lastParams().get("dir")).toBe("asc")); // A column outside `sortable` has no sort button. expect(screen.queryByRole("button", { name: "id" })).toBeNull(); const csv = screen.getByRole("link", { name: /Export CSV/ }); expect(csv.getAttribute("href")).toContain("entity=agents"); expect(csv.getAttribute("href")).toContain("sort=name"); expect(csv.getAttribute("href")).toContain("format=csv"); }); });