import { describe, it, expect, vi, beforeEach } from "vitest"; import { render, screen, waitFor } from "@testing-library/react"; import { MemoryRouter, Route, Routes } from "react-router-dom"; import { ReplayPage } from "./ReplayPage"; vi.mock("../api", () => ({ fetchReplay: vi.fn(), })); vi.mock("../components/ReplayTimeline", () => ({ ReplayTimeline: ({ steps }: { steps: unknown[] }) => (
{steps.length} steps
), })); import { fetchReplay } from "../api"; const mockFetchReplay = vi.mocked(fetchReplay); beforeEach(() => { mockFetchReplay.mockReset(); }); function renderWithRoute(threadId: string) { return render( } /> ); } describe("ReplayPage", () => { it("renders loading state initially", () => { mockFetchReplay.mockReturnValue(new Promise(() => {})); renderWithRoute("t1"); expect(document.querySelector(".skeleton-box")).toBeTruthy(); }); it("renders replay steps on success", async () => { mockFetchReplay.mockResolvedValue({ thread_id: "t1", total_steps: 2, page: 1, per_page: 100, steps: [ { step: 1, type: "message", content: "Hello", agent: null, tool: null, params: null, result: null, timestamp: "2026-04-01T00:00:00Z" }, { step: 2, type: "response", content: "Hi!", agent: "bot", tool: null, params: null, result: null, timestamp: "2026-04-01T00:00:01Z" }, ], }); renderWithRoute("t1"); await waitFor(() => { expect(screen.getByTestId("replay-timeline")).toBeInTheDocument(); }); expect(screen.getByText("2 steps")).toBeInTheDocument(); // Thread ID appears in multiple places (header + sidebar) expect(screen.getAllByText("t1").length).toBeGreaterThan(0); }); it("renders empty state when no steps", async () => { mockFetchReplay.mockResolvedValue({ thread_id: "t1", total_steps: 0, page: 1, per_page: 100, steps: [], }); renderWithRoute("t1"); await waitFor(() => { expect(screen.getByText("No replay steps found")).toBeInTheDocument(); }); }); it("renders error state on fetch failure", async () => { mockFetchReplay.mockRejectedValue(new Error("Not found")); renderWithRoute("t1"); await waitFor(() => { expect(screen.getByText("Failed to load replay")).toBeInTheDocument(); }); expect(screen.getByText("Not found")).toBeInTheDocument(); }); });