// #112 - Unit tests for /roles endpoints import { assertEquals, assertExists } from "@std/assert"; import { mockFetch, restoreFetch } from "../helpers/api_mock.ts"; import { createMockDb } from "../helpers/db_mock.ts"; interface Role { id: number; nom: string; permissions: string[]; } const roles: Role[] = [ { id: 1, nom: "admin", permissions: ["student_read", "student_write"] }, { id: 2, nom: "employee", permissions: ["student_read"] }, ]; // --- Fixtures --- Deno.test("roles: fixtures have correct shape", () => { assertEquals(roles.length, 2); assertEquals(typeof roles[0].id, "number"); assertEquals(typeof roles[0].nom, "string"); assertEquals(Array.isArray(roles[0].permissions), true); }); Deno.test("roles: permissions are strings", () => { assertEquals(roles[0].permissions.every((p) => typeof p === "string"), true); }); // --- Mock API --- Deno.test("mock API: GET /roles returns list with permissions", async () => { mockFetch({ "/roles": roles }); try { const res = await fetch("http://localhost/api/roles"); assertEquals(res.status, 200); const data: Role[] = await res.json(); assertEquals(data.length, 2); assertExists(data.find((r) => r.nom === "admin")); assertEquals(data[0].permissions.length, 2); } finally { restoreFetch(); } }); Deno.test("mock API: GET /roles/:id returns role", async () => { mockFetch({ "/roles/1": roles[0] }); try { const res = await fetch("http://localhost/api/roles/1"); assertEquals(res.status, 200); const data: Role = await res.json(); assertEquals(data.nom, "admin"); assertEquals(data.permissions.length, 2); } finally { restoreFetch(); } }); Deno.test("mock API: GET /roles/:id 404 when not found", async () => { mockFetch({ "/roles/99": { status: 404, body: { error: "Ressource introuvable" } }, }); try { const res = await fetch("http://localhost/api/roles/99"); assertEquals(res.status, 404); } finally { restoreFetch(); } }); Deno.test("mock API: POST /roles creates role (201)", async () => { const newRole: Role = { id: 3, nom: "viewer", permissions: [] }; mockFetch({ "/roles": { method: "POST", status: 201, body: newRole } }); try { const res = await fetch("http://localhost/api/roles", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ nom: "viewer" }), }); assertEquals(res.status, 201); const data: Role = await res.json(); assertEquals(data.nom, "viewer"); assertEquals(data.permissions.length, 0); } finally { restoreFetch(); } }); Deno.test("mock API: POST /roles 400 on missing nom", async () => { mockFetch({ "/roles": { method: "POST", status: 400 } }); try { const res = await fetch("http://localhost/api/roles", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({}), }); assertEquals(res.status, 400); } finally { restoreFetch(); } }); Deno.test("mock API: PUT /roles/:id updates role and permissions", async () => { const updated: Role = { id: 2, nom: "teacher", permissions: ["note_read"] }; mockFetch({ "/roles/2": { method: "PUT", status: 200, body: updated } }); try { const res = await fetch("http://localhost/api/roles/2", { method: "PUT", headers: { "content-type": "application/json" }, body: JSON.stringify({ nom: "teacher", permissions: ["note_read"] }), }); assertEquals(res.status, 200); const data: Role = await res.json(); assertEquals(data.nom, "teacher"); assertEquals(data.permissions, ["note_read"]); } finally { restoreFetch(); } }); Deno.test("mock API: DELETE /roles/:id returns 204", async () => { mockFetch({ "/roles/2": { method: "DELETE", status: 204 } }); try { const res = await fetch("http://localhost/api/roles/2", { method: "DELETE", }); assertEquals(res.status, 204); } finally { restoreFetch(); } }); // --- Mock DB --- Deno.test("mock DB: find role by id", () => { const db = createMockDb({ tables: { roles: [...roles] } }); const r = db.findOne("roles", (r) => r.id === 1); assertExists(r); assertEquals(r.nom, "admin"); }); Deno.test("mock DB: insert role", () => { const db = createMockDb({ tables: { roles: [...roles] } }); db.insert("roles", { id: 3, nom: "viewer", permissions: [] }); assertEquals(db.getTable("roles").length, 3); }); Deno.test("mock DB: update role nom", () => { const db = createMockDb({ tables: { roles: [...roles] } }); db.updateWhere("roles", (r) => r.id === 2, { nom: "teacher" }); assertEquals(db.findOne("roles", (r) => r.id === 2)?.nom, "teacher"); }); Deno.test("mock DB: delete role", () => { const db = createMockDb({ tables: { roles: [...roles] } }); db.deleteWhere("roles", (r) => r.id === 1); assertEquals(db.getTable("roles").length, 1); });