/** * Tests for the ServerStatusBar component. * * Covers loading state, online / offline rendering, and correct tooltip * wording that distinguishes the fail2ban daemon version from the BanGUI * application version. */ import { describe, it, expect, vi, beforeEach } from "vitest"; import { render, screen } from "@testing-library/react"; import { FluentProvider, webLightTheme } from "@fluentui/react-components"; import { ServerStatusBar } from "../ServerStatusBar"; // --------------------------------------------------------------------------- // Mock useServerStatus so tests never touch the network. // --------------------------------------------------------------------------- vi.mock("../../hooks/useServerStatus"); import { useServerStatus } from "../../hooks/useServerStatus"; const mockedUseServerStatus = vi.mocked(useServerStatus); function renderBar(): void { render( , ); } // --------------------------------------------------------------------------- // Tests // --------------------------------------------------------------------------- describe("ServerStatusBar", () => { beforeEach(() => { vi.clearAllMocks(); }); it("shows a spinner while the initial load is in progress", () => { mockedUseServerStatus.mockReturnValue({ status: null, loading: true, error: null, refresh: vi.fn(), }); renderBar(); // The status-area spinner is labelled "Checking\u2026". expect(screen.getByText("Checking\u2026")).toBeInTheDocument(); }); it("renders an Online badge when the server is reachable", () => { mockedUseServerStatus.mockReturnValue({ status: { online: true, version: "1.1.0", active_jails: 3, total_bans: 10, total_failures: 5, }, loading: false, error: null, refresh: vi.fn(), }); renderBar(); expect(screen.getByText("Online")).toBeInTheDocument(); }); it("renders an Offline badge when the server is unreachable", () => { mockedUseServerStatus.mockReturnValue({ status: { online: false, version: null, active_jails: 0, total_bans: 0, total_failures: 0, }, loading: false, error: null, refresh: vi.fn(), }); renderBar(); expect(screen.getByText("Offline")).toBeInTheDocument(); }); it("displays the daemon version string when available", () => { mockedUseServerStatus.mockReturnValue({ status: { online: true, version: "1.2.3", active_jails: 1, total_bans: 0, total_failures: 0, }, loading: false, error: null, refresh: vi.fn(), }); renderBar(); expect(screen.getByText("v1.2.3")).toBeInTheDocument(); }); it("does not render a separate BanGUI version badge", () => { mockedUseServerStatus.mockReturnValue({ status: { online: true, version: "1.2.3", active_jails: 1, total_bans: 0, total_failures: 0, }, loading: false, error: null, refresh: vi.fn(), }); renderBar(); expect(screen.queryByText("BanGUI v9.9.9")).toBeNull(); }); it("does not render the version element when version is null", () => { mockedUseServerStatus.mockReturnValue({ status: { online: false, version: null, active_jails: 0, total_bans: 0, total_failures: 0, }, loading: false, error: null, refresh: vi.fn(), }); renderBar(); // No version string should appear in the document. expect(screen.queryByText(/^v\d/)).not.toBeInTheDocument(); }); it("shows jail / ban / failure counts when the server is online", () => { mockedUseServerStatus.mockReturnValue({ status: { online: true, version: "1.0.0", active_jails: 4, total_bans: 21, total_failures: 99, }, loading: false, error: null, refresh: vi.fn(), }); renderBar(); expect(screen.getByText("4")).toBeInTheDocument(); expect(screen.getByText("21")).toBeInTheDocument(); expect(screen.getByText("99")).toBeInTheDocument(); // Verify the "Failed Attempts:" label (renamed from "Failures:"). expect(screen.getByText("Failed Attempts:")).toBeInTheDocument(); }); it("renders an error message when the status fetch fails", () => { mockedUseServerStatus.mockReturnValue({ status: null, loading: false, error: "Network error", refresh: vi.fn(), }); renderBar(); expect(screen.getByText("Network error")).toBeInTheDocument(); }); });