import { describe, expect, it, vi, beforeEach } from "vitest"; import { appRouter } from "./routers"; import type { TrpcContext } from "./_core/context"; // ─── Helpers ───────────────────────────────────────────────────────────────── function makeAdminCtx(): TrpcContext { return { user: { id: 1, openId: "admin-test", email: "admin@itinova.fr", name: "Admin Test", loginMethod: "local", role: "admin", createdAt: new Date(), updatedAt: new Date(), lastSignedIn: new Date(), }, req: { protocol: "https", headers: {} } as TrpcContext["req"], res: { clearCookie: vi.fn(), cookie: vi.fn(), } as unknown as TrpcContext["res"], }; } function makeUserCtx(): TrpcContext { return { user: { id: 2, openId: "user-test", email: "user@itinova.fr", name: "User Test", loginMethod: "local", role: "user", createdAt: new Date(), updatedAt: new Date(), lastSignedIn: new Date(), }, req: { protocol: "https", headers: {} } as TrpcContext["req"], res: { clearCookie: vi.fn(), cookie: vi.fn(), } as unknown as TrpcContext["res"], }; } function makeAnonCtx(): TrpcContext { return { user: null, req: { protocol: "https", headers: {} } as TrpcContext["req"], res: { clearCookie: vi.fn(), cookie: vi.fn(), } as unknown as TrpcContext["res"], }; } // ─── Tests Auth ─────────────────────────────────────────────────────────────── describe("auth.logout", () => { it("efface le cookie de session et retourne success", async () => { const { ctx } = { ctx: makeAdminCtx() }; const clearedCookies: string[] = []; ctx.res.clearCookie = (name: string) => { clearedCookies.push(name); }; const caller = appRouter.createCaller(ctx); const result = await caller.auth.logout(); expect(result.success).toBe(true); expect(clearedCookies.length).toBeGreaterThan(0); }); it("retourne l'utilisateur connecté via auth.me", async () => { const ctx = makeAdminCtx(); const caller = appRouter.createCaller(ctx); const user = await caller.auth.me(); expect(user).not.toBeNull(); expect(user?.email).toBe("admin@itinova.fr"); }); it("retourne null pour un utilisateur non connecté", async () => { const ctx = makeAnonCtx(); const caller = appRouter.createCaller(ctx); const user = await caller.auth.me(); expect(user).toBeNull(); }); }); // ─── Tests protection admin ─────────────────────────────────────────────────── describe("protection admin", () => { it("refuse l'accès aux logs pour un utilisateur non admin", async () => { const ctx = makeUserCtx(); const caller = appRouter.createCaller(ctx); await expect(caller.import.logs({ page: 1, pageSize: 10 })).rejects.toThrow(); }); it("refuse l'accès aux paramètres pour un utilisateur non admin", async () => { const ctx = makeUserCtx(); const caller = appRouter.createCaller(ctx); await expect(caller.settings.get()).rejects.toThrow(); }); it("refuse la gestion des utilisateurs pour un non admin", async () => { const ctx = makeUserCtx(); const caller = appRouter.createCaller(ctx); await expect(caller.users.list()).rejects.toThrow(); }); }); // ─── Tests accès public ─────────────────────────────────────────────────────── describe("accès public", () => { it("veille.list est accessible sans authentification", async () => { const ctx = makeAnonCtx(); const caller = appRouter.createCaller(ctx); // Ne devrait pas lever d'erreur UNAUTHORIZED const result = await caller.veille.list({ page: 1, pageSize: 10 }); expect(result).toHaveProperty("items"); expect(result).toHaveProperty("total"); }); it("aap.list est accessible sans authentification", async () => { const ctx = makeAnonCtx(); const caller = appRouter.createCaller(ctx); const result = await caller.aap.list({ page: 1, pageSize: 10 }); expect(result).toHaveProperty("items"); expect(result).toHaveProperty("total"); }); it("veille.filters est accessible sans authentification", async () => { const ctx = makeAnonCtx(); const caller = appRouter.createCaller(ctx); const result = await caller.veille.filters(); expect(result).toHaveProperty("categories"); expect(result).toHaveProperty("niveaux"); expect(result).toHaveProperty("territoires"); }); it("aap.filters est accessible sans authentification", async () => { const ctx = makeAnonCtx(); const caller = appRouter.createCaller(ctx); const result = await caller.aap.filters(); expect(result).toHaveProperty("regions"); expect(result).toHaveProperty("departements"); }); }); // ─── Tests import (admin seulement) ────────────────────────────────────────── describe("import.run protection", () => { it("refuse l'import pour un utilisateur non authentifié", async () => { const ctx = makeAnonCtx(); const caller = appRouter.createCaller(ctx); await expect(caller.import.run({ type: "all" })).rejects.toThrow(); }); it("refuse l'import pour un utilisateur standard", async () => { const ctx = makeUserCtx(); const caller = appRouter.createCaller(ctx); await expect(caller.import.run({ type: "all" })).rejects.toThrow(); }); });