import { fireEvent, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it } from "vitest";
import AnimateCountClient, { AnimateCount } from "@/components/AnimatedCount";
import ErrorBoundary from "@/components/ErrorBoundary";
import ChartSkeleton from "@/components/loading/ChartSkeleton";
import { Loader, LoadingSpinner } from "@/components/loading/Loader";
import NetworkChartLoading from "@/components/NetworkChartLoading";
import { SearchButton } from "@/components/SearchButton";
import ServerOverview from "@/components/ServerOverview";
import ServerUsageBar from "@/components/ServerUsageBar";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Separator } from "@/components/ui/separator";
import { Skeleton } from "@/components/ui/skeleton";
import { CommandProvider } from "@/context/command-provider";
import { StatusProvider } from "@/context/status-provider";
import { useCommand } from "@/hooks/use-command";
import { useStatus } from "@/hooks/use-status";
function BrokenComponent(): never {
throw new Error("render failed");
}
function CommandReadout() {
const { isOpen } = useCommand();
return
{isOpen ? "command-open" : "command-closed"}
;
}
function StatusReadout() {
const { status } = useStatus();
return {`status:${status}`}
;
}
describe("basic display components", () => {
it("renders animated counts with padded digits", () => {
render({7});
expect(screen.getAllByText("0")).toHaveLength(4);
expect(screen.getAllByText("7")).toHaveLength(1);
});
it("keeps the animated count client stable across count changes", () => {
const { rerender } = render(
,
);
expect(screen.getAllByText("1")).toHaveLength(2);
rerender();
expect(screen.getByText("2")).toBeInTheDocument();
});
it("renders server usage colors for healthy, warning, and critical values", () => {
const { rerender } = render();
expect(screen.getByRole("progressbar").firstElementChild).toHaveClass(
"bg-green-500",
);
rerender();
expect(screen.getByRole("progressbar").firstElementChild).toHaveClass(
"bg-orange-400",
);
rerender();
expect(screen.getByRole("progressbar").firstElementChild).toHaveClass(
"bg-red-500",
);
});
it("renders loading primitives", () => {
const { container } = render(
<>
>,
);
expect(
container.querySelector("[data-visible='true']"),
).toBeInTheDocument();
expect(container.querySelectorAll(".hamster-loading-bar")).toHaveLength(16);
expect(container.querySelector(".animate-spin")).toBeInTheDocument();
expect(container.querySelector(".h-\\[250px\\]")).toBeInTheDocument();
});
it("catches render errors with ErrorBoundary", () => {
render(
,
);
expect(screen.getByText("500")).toBeInTheDocument();
expect(screen.getByText("render failed")).toBeInTheDocument();
});
});
describe("interactive app controls", () => {
it("opens command search from the search button", async () => {
const user = userEvent.setup();
render(
,
);
expect(screen.getByText("command-closed")).toBeInTheDocument();
await user.click(screen.getByRole("button", { name: "Search" }));
expect(screen.getByText("command-open")).toBeInTheDocument();
});
it("lets overview cards update the global status filter", () => {
render(
{}}
activeView="servers"
/>
,
);
expect(screen.getByText("status:all")).toBeInTheDocument();
fireEvent.click(screen.getByText("serverOverview.onlineServers"));
expect(screen.getByText("status:online")).toBeInTheDocument();
fireEvent.click(screen.getByText("serverOverview.offlineServers"));
expect(screen.getByText("status:offline")).toBeInTheDocument();
fireEvent.click(screen.getByText("serverOverview.totalServers"));
expect(screen.getByText("status:all")).toBeInTheDocument();
});
});
describe("ui primitives", () => {
it("forwards classes and events through Button and Input", async () => {
const user = userEvent.setup();
const onClick = vi.fn();
const onChange = vi.fn();
render(
<>
>,
);
await user.click(screen.getByRole("button", { name: "Save" }));
await user.type(screen.getByPlaceholderText("Name"), "edge");
expect(onClick).toHaveBeenCalledOnce();
expect(onChange).toHaveBeenCalled();
expect(screen.getByRole("button", { name: "Save" })).toHaveClass(
"bg-secondary",
);
});
it("renders skeletons and separators with expected orientation classes", () => {
const { container } = render(
<>
>,
);
expect(screen.getByTestId("skeleton")).toHaveClass("animate-pulse", "h-4");
expect(screen.getByTestId("horizontal")).toHaveClass("h-px", "w-full");
expect(screen.getByTestId("vertical")).toHaveClass("h-full", "w-px");
expect(container.querySelectorAll("[data-orientation]")).toHaveLength(2);
});
});