test(web): add 291 tests for parsers, hooks, and UI components

Lib utilities: scopeImportParser (31), status-styles (58),
planningEntryIds (10), uuid (11).

Hooks: useFilters (28), useRowOrder (18), usePermissions (30),
useViewPrefs (24).

Components: AnimatedModal (14), DateInput (22), InfoTooltip (13),
ProgressRing (19).

Web test suite: 75 → 87 files, 553 → 844 tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-10 17:14:11 +02:00
parent 98dca6126f
commit a3d75973ee
12 changed files with 2626 additions and 0 deletions
+243
View File
@@ -0,0 +1,243 @@
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
import { renderHook } from "@testing-library/react";
// ---------------------------------------------------------------------------
// Mock next-auth/react so the hook can run without a real auth provider.
// ---------------------------------------------------------------------------
const mockUseSession = vi.fn();
vi.mock("next-auth/react", () => ({
useSession: () => mockUseSession(),
}));
const { usePermissions } = await import("./usePermissions.js");
// ---------------------------------------------------------------------------
// Helper: build a mock session object with the given role.
// ---------------------------------------------------------------------------
function sessionWith(role: string) {
return { data: { user: { role } } };
}
// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------
describe("usePermissions", () => {
beforeEach(() => {
mockUseSession.mockReset();
});
afterEach(() => {
vi.restoreAllMocks();
});
// -------------------------------------------------------------------------
// No session / unauthenticated
// -------------------------------------------------------------------------
describe("when there is no session", () => {
it("falls back to role USER when data is null", () => {
mockUseSession.mockReturnValue({ data: null });
const { result } = renderHook(() => usePermissions());
expect(result.current.role).toBe("USER");
});
it("falls back to role USER when data is undefined", () => {
mockUseSession.mockReturnValue({ data: undefined });
const { result } = renderHook(() => usePermissions());
expect(result.current.role).toBe("USER");
});
it("falls back to role USER when user has no role property", () => {
mockUseSession.mockReturnValue({ data: { user: {} } });
const { result } = renderHook(() => usePermissions());
expect(result.current.role).toBe("USER");
});
it("denies all privileged permissions for anonymous user", () => {
mockUseSession.mockReturnValue({ data: null });
const { result } = renderHook(() => usePermissions());
expect(result.current.canViewCosts).toBe(false);
expect(result.current.canEdit).toBe(false);
expect(result.current.canManageUsers).toBe(false);
expect(result.current.canManageBlueprints).toBe(false);
expect(result.current.canViewScores).toBe(false);
});
});
// -------------------------------------------------------------------------
// ADMIN role
// -------------------------------------------------------------------------
describe("ADMIN role", () => {
beforeEach(() => {
mockUseSession.mockReturnValue(sessionWith("ADMIN"));
});
it("exposes role as ADMIN", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.role).toBe("ADMIN");
});
it("canViewCosts is true", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canViewCosts).toBe(true);
});
it("canEdit is true", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canEdit).toBe(true);
});
it("canManageUsers is true", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canManageUsers).toBe(true);
});
it("canManageBlueprints is true", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canManageBlueprints).toBe(true);
});
it("canViewScores is true", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canViewScores).toBe(true);
});
});
// -------------------------------------------------------------------------
// MANAGER role
// -------------------------------------------------------------------------
describe("MANAGER role", () => {
beforeEach(() => {
mockUseSession.mockReturnValue(sessionWith("MANAGER"));
});
it("exposes role as MANAGER", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.role).toBe("MANAGER");
});
it("canViewCosts is true", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canViewCosts).toBe(true);
});
it("canEdit is true", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canEdit).toBe(true);
});
it("canManageUsers is false", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canManageUsers).toBe(false);
});
it("canManageBlueprints is false", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canManageBlueprints).toBe(false);
});
it("canViewScores is true", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canViewScores).toBe(true);
});
});
// -------------------------------------------------------------------------
// CONTROLLER role
// -------------------------------------------------------------------------
describe("CONTROLLER role", () => {
beforeEach(() => {
mockUseSession.mockReturnValue(sessionWith("CONTROLLER"));
});
it("exposes role as CONTROLLER", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.role).toBe("CONTROLLER");
});
it("canViewCosts is true", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canViewCosts).toBe(true);
});
it("canEdit is false (CONTROLLER is not in EDIT_ROLES)", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canEdit).toBe(false);
});
it("canManageUsers is false", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canManageUsers).toBe(false);
});
it("canManageBlueprints is false", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canManageBlueprints).toBe(false);
});
it("canViewScores is false (CONTROLLER is not in SCORE_ROLES)", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canViewScores).toBe(false);
});
});
// -------------------------------------------------------------------------
// USER role (default / authenticated but unprivileged)
// -------------------------------------------------------------------------
describe("USER role", () => {
beforeEach(() => {
mockUseSession.mockReturnValue(sessionWith("USER"));
});
it("exposes role as USER", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.role).toBe("USER");
});
it("canViewCosts is false", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canViewCosts).toBe(false);
});
it("canEdit is false", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canEdit).toBe(false);
});
it("canManageUsers is false", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canManageUsers).toBe(false);
});
it("canManageBlueprints is false", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canManageBlueprints).toBe(false);
});
it("canViewScores is false", () => {
const { result } = renderHook(() => usePermissions());
expect(result.current.canViewScores).toBe(false);
});
});
// -------------------------------------------------------------------------
// Unknown / arbitrary role
// -------------------------------------------------------------------------
describe("unknown role", () => {
it("denies all privileged permissions for an unknown role string", () => {
mockUseSession.mockReturnValue(sessionWith("SUPER_DUPER_ADMIN"));
const { result } = renderHook(() => usePermissions());
expect(result.current.canViewCosts).toBe(false);
expect(result.current.canEdit).toBe(false);
expect(result.current.canManageUsers).toBe(false);
expect(result.current.canManageBlueprints).toBe(false);
expect(result.current.canViewScores).toBe(false);
});
it("still surfaces the raw role string for arbitrary roles", () => {
mockUseSession.mockReturnValue(sessionWith("VIEWER"));
const { result } = renderHook(() => usePermissions());
expect(result.current.role).toBe("VIEWER");
});
});
});