learning_ai_notes/web/src/components/AuthGuard.test.tsx

83 lines
3.1 KiB
TypeScript

import { render, screen, waitFor } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
const { checkKillSwitchMock, logoutMock, refreshStoredAuthSessionMock, replaceMock, useAuthMock } = vi.hoisted(() => ({
checkKillSwitchMock: vi.fn(async () => ({ disabled: false, message: "" })),
logoutMock: vi.fn(),
refreshStoredAuthSessionMock: vi.fn(async () => true),
replaceMock: vi.fn(),
useAuthMock: vi.fn(() => ({ isAuthenticated: true, isLoading: false, logout: logoutMock })),
}));
vi.mock("next/navigation", () => ({
useRouter: () => ({ replace: replaceMock }),
}));
vi.mock("@/lib/auth", () => ({
useAuth: useAuthMock,
}));
vi.mock("@/lib/auth-session", () => ({
refreshStoredAuthSession: refreshStoredAuthSessionMock,
}));
vi.mock("@/lib/kill-switch", () => ({
checkKillSwitch: checkKillSwitchMock,
}));
import { AuthGuard } from "./AuthGuard";
describe("AuthGuard", () => {
beforeEach(() => {
vi.clearAllMocks();
useAuthMock.mockReturnValue({ isAuthenticated: true, isLoading: false, logout: logoutMock });
refreshStoredAuthSessionMock.mockResolvedValue(true);
checkKillSwitchMock.mockResolvedValue({ disabled: false, message: "" });
});
it("redirects unauthenticated users to login", async () => {
useAuthMock.mockReturnValue({ isAuthenticated: false, isLoading: false, logout: logoutMock });
render(<AuthGuard><div>Private app</div></AuthGuard>);
await waitFor(() => expect(replaceMock).toHaveBeenCalledWith("/login"));
expect(screen.queryByText("Private app")).not.toBeInTheDocument();
});
it("refreshes an expired stored session before showing protected content", async () => {
render(<AuthGuard><div>Private app</div></AuthGuard>);
await waitFor(() => expect(refreshStoredAuthSessionMock).toHaveBeenCalledOnce());
expect(await screen.findByText("Private app")).toBeInTheDocument();
expect(logoutMock).not.toHaveBeenCalled();
});
it("logs out and redirects when session refresh fails", async () => {
refreshStoredAuthSessionMock.mockResolvedValue(false);
render(<AuthGuard><div>Private app</div></AuthGuard>);
await waitFor(() => expect(logoutMock).toHaveBeenCalledOnce());
expect(replaceMock).toHaveBeenCalledWith("/login");
expect(screen.queryByText("Private app")).not.toBeInTheDocument();
});
it("keeps protected content hidden when the kill switch is active", async () => {
checkKillSwitchMock.mockResolvedValue({ disabled: true, message: "Maintenance window" });
render(<AuthGuard><div>Private app</div></AuthGuard>);
expect(await screen.findByText("Maintenance window")).toBeInTheDocument();
expect(screen.queryByText("Private app")).not.toBeInTheDocument();
});
it("shows a platform-down state when readiness cannot be checked", async () => {
checkKillSwitchMock.mockRejectedValue(new Error("HTTP 503 Service Unavailable"));
render(<AuthGuard><div>Private app</div></AuthGuard>);
expect(await screen.findByText("Platform services are unavailable")).toBeInTheDocument();
expect(screen.queryByText("Private app")).not.toBeInTheDocument();
});
});