/** * @file StatusBar.test.tsx * @description Tests for the shell's bottom status bar: the live/disconnected * state with the version (click opens the connection details), the running and * needs-you counts from the shared lane list, today's spend from the * pricing cost call's `daily_costs`, and on the Workspace page the open * workspace's and the shown session's totals. * @author Nguyễn Ngọc Trí Vĩ */ import { describe, it, expect, vi } from "vitest"; import { act, render, screen } from "@testing-library/react"; import { MemoryRouter } from "react-router-dom"; import userEvent from "@testing-library/user-event"; function today() { const d = new Date(); const pad = (n: number) => String(n).padStart(2, "0"); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; } vi.mock("../../lib/api", () => ({ api: { lanes: { list: vi.fn().mockResolvedValue({ lanes: [ { id: 1, status: "running", needs_action: null }, { id: 2, status: "running", needs_action: "permission" }, { id: 3, status: "idle", needs_action: null }, ], counts: {}, }), }, pricing: { totalCost: vi.fn().mockImplementation(async (opts?: { lane?: number }) => ({ total_cost: opts?.lane ? 123.456 : 10, breakdown: [], daily_costs: [ { date: "2000-01-01", cost: 9 }, { date: today(), cost: 1.234 }, ], })), sessionCost: vi.fn().mockImplementation(async (id: string) => ({ total_cost: id === "s-live" ? 4.5 : 7, breakdown: [], daily_costs: [], })), }, }, })); import { api } from "../../lib/api"; import { StatusBar } from "../StatusBar"; import { LIVE_RUNS_EVENT } from "../WorkspaceTree"; const at = (url: string, ui: JSX.Element) => render({ui}); describe("StatusBar", () => { it("shows the connection with the version, the counts and today's spend", async () => { const user = userEvent.setup(); const onConnectionClick = vi.fn(); at("/", ); expect(screen.getByText("Live")).toBeInTheDocument(); expect(screen.getByText(`v${__APP_VERSION__}`)).toBeInTheDocument(); expect(await screen.findByText("Today $1.23")).toBeInTheDocument(); expect(screen.getByTestId("status-bar-counts").textContent).toBe("2 running · 1 need you"); await user.click(screen.getByText("Live")); expect(onConnectionClick).toHaveBeenCalled(); }); it("says Disconnected when the socket is down", () => { at("/", {}} />); expect(screen.getByText("Disconnected")).toBeInTheDocument(); }); it("off the Workspace page shows no workspace or session cost", async () => { at("/sessions", {}} />); await screen.findByText("Today $1.23"); expect(screen.queryByTestId("status-bar-workspace-cost")).toBeNull(); expect(screen.queryByTestId("status-bar-session-cost")).toBeNull(); }); it("shows the open workspace's total and the replayed session's", async () => { at( "/workspace?lane=3&session=s-old", {}} /> ); expect(await screen.findByText("Workspace $123.46")).toBeInTheDocument(); expect(await screen.findByText("Session $7.00")).toBeInTheDocument(); expect(api.pricing.totalCost).toHaveBeenCalledWith({ lane: 3 }); }); it("takes a focused pane's session from the page's run poll", async () => { at( "/workspace?lane=3&run=agenthub-lane-3-1", {}} /> ); await screen.findByText("Workspace $123.46"); expect(screen.queryByTestId("status-bar-session-cost")).toBeNull(); act(() => { window.dispatchEvent( new CustomEvent(LIVE_RUNS_EVENT, { detail: [{ id: "agenthub-lane-3-1", laneId: 3, status: "running", sessionId: "s-live" }], }) ); }); expect(await screen.findByText("Session $4.50")).toBeInTheDocument(); }); });