moadim 3.2.4

Loop engine for AI agents — routines over REST, MCP, and a built-in web UI
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { fireEvent, render, screen } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { describe, expect, it } from "vitest";
import type { FleetRunSummary } from "../../api/hooks";
import { RunsPage } from "./RunsPage";

function run(overrides: Partial<FleetRunSummary> = {}): FleetRunSummary {
  return {
    routine_id: "r1",
    routine_title: "Nightly Audit",
    workbench: "nightly-audit-1000",
    started_at: Math.floor(Date.now() / 1000) - 10,
    started_at_local: "",
    finished_at: Math.floor(Date.now() / 1000),
    finished_at_local: "",
    status: "success",
    exit_code: 0,
    ...overrides,
  };
}

function renderPage(runs?: FleetRunSummary[]) {
  const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  if (runs !== undefined) queryClient.setQueryData(["routines", "runs", 100], runs);
  render(
    <QueryClientProvider client={queryClient}>
      <MemoryRouter>
        <RunsPage />
      </MemoryRouter>
    </QueryClientProvider>,
  );
  return queryClient;
}

describe("RunsPage", () => {
  it("shows a spinner before the query has loaded", () => {
    renderPage();
    expect(document.querySelector(".spinner")).toBeInTheDocument();
  });

  it("shows an empty state with no runs at all", () => {
    renderPage([]);
    expect(screen.getByText("NO RUNS")).toBeInTheDocument();
    expect(screen.getByText("no runs yet")).toBeInTheDocument();
  });

  it("lists fetched runs with routine link and status", () => {
    renderPage([
      run({ workbench: "wb1", routine_title: "Nightly Audit", status: "success" }),
      run({ workbench: "wb2", routine_title: "Weekly Digest", status: "failed", exit_code: 1 }),
    ]);

    expect(screen.getByRole("heading", { name: "Runs" })).toBeInTheDocument();
    expect(screen.getByRole("link", { name: "Nightly Audit" })).toHaveAttribute(
      "href",
      "/routines?history=r1",
    );
    expect(screen.getByText("Weekly Digest")).toBeInTheDocument();
    expect(screen.getByText("Showing 2 of 2 fetched")).toBeInTheDocument();
  });

  it("links each run to its own deep-linkable detail page", () => {
    renderPage([run({ workbench: "wb1", routine_title: "Nightly Audit" })]);
    expect(screen.getByRole("link", { name: "VIEW RUN" })).toHaveAttribute("href", "/runs/r1/wb1");
  });

  it("filters the list by status", () => {
    renderPage([
      run({ workbench: "wb1", routine_title: "Nightly Audit", status: "success" }),
      run({ workbench: "wb2", routine_title: "Weekly Digest", status: "failed" }),
    ]);

    fireEvent.change(screen.getByLabelText("Status filter"), { target: { value: "failed" } });

    expect(screen.getByText("Showing 1 of 2 fetched")).toBeInTheDocument();
    expect(screen.queryByText("Nightly Audit")).not.toBeInTheDocument();
    expect(screen.getByText("Weekly Digest")).toBeInTheDocument();
  });

  it("filters the list by routine title search", () => {
    renderPage([
      run({ workbench: "wb1", routine_title: "Nightly Audit" }),
      run({ workbench: "wb2", routine_title: "Weekly Digest" }),
    ]);

    fireEvent.change(screen.getByLabelText("Search runs"), { target: { value: "weekly" } });

    expect(screen.getByText("Showing 1 of 2 fetched")).toBeInTheDocument();
    expect(screen.getByText("Weekly Digest")).toBeInTheDocument();
  });

  it("shows a no-matches empty state distinct from no-runs-yet", () => {
    renderPage([run({ routine_title: "Nightly Audit" })]);
    fireEvent.change(screen.getByLabelText("Search runs"), { target: { value: "nonexistent" } });
    expect(screen.getByText("NO RUNS")).toBeInTheDocument();
    expect(screen.getByText("no runs match the current filters")).toBeInTheDocument();
  });

  it("offers a load-more action once the fetch limit is hit", () => {
    const runs = Array.from({ length: 100 }, (_, i) => run({ workbench: `wb${i}`, started_at: 1_000 + i }));
    renderPage(runs);
    expect(screen.getByRole("button", { name: "Load more" })).toBeInTheDocument();
  });

  it("does not offer load-more under the fetch limit", () => {
    renderPage([run()]);
    expect(screen.queryByRole("button", { name: "Load more" })).not.toBeInTheDocument();
  });
});