e75098083a
- unit: fixture shapes, mock API (GET/POST/PUT/DELETE), mock DB CRUD - integration: list, create, assign permissions, update, reset perms, delete - e2e: handler calls with mock context + real DB, covers 400/404 cases
156 lines
4.8 KiB
TypeScript
156 lines
4.8 KiB
TypeScript
// #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<Role>("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<Role>("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<Role>("roles", (r) => r.id === 2, { nom: "teacher" });
|
|
assertEquals(db.findOne<Role>("roles", (r) => r.id === 2)?.nom, "teacher");
|
|
});
|
|
|
|
Deno.test("mock DB: delete role", () => {
|
|
const db = createMockDb({ tables: { roles: [...roles] } });
|
|
db.deleteWhere<Role>("roles", (r) => r.id === 1);
|
|
assertEquals(db.getTable("roles").length, 1);
|
|
});
|