import { assertEquals, assertExists } from "@std/assert"; import { getFetchCalls, mockFetch, restoreFetch, } from "../helpers/api_mock.ts"; import { createMockDb } from "../helpers/db_mock.ts"; import { type Student, ERROR_CONFLICT, ERROR_NOT_FOUND, modules, notes, students, } from "../helpers/fixtures.ts"; import { cleanupDOM, setupDOM } from "../helpers/render.ts"; // --- Fixtures --- Deno.test("fixtures - students match API shape", () => { assertEquals(students.length, 3); assertEquals(students[0].numEtud, 21212006); assertEquals(students[0].idPromo, "4AFISE25/26"); assertEquals(typeof students[0].idPromo, "string"); }); Deno.test("fixtures - modules have string ids", () => { assertEquals(modules[0].id, "JIN702C"); assertEquals(typeof modules[0].id, "string"); }); Deno.test("fixtures - notes use decimal values", () => { assertEquals(notes[0].note, 15.5); assertEquals(notes[0].idModule, "JIN702C"); }); // --- Mock fetch simple (GET 200) --- Deno.test("mockFetch - GET returns mocked data", async () => { mockFetch({ "/students": students }); try { const res = await fetch("http://localhost/api/students"); assertEquals(res.status, 200); const data = await res.json(); assertEquals(data.length, 3); assertEquals(data[0].nom, "Dupont"); } finally { restoreFetch(); } }); Deno.test("mockFetch - returns 404 for unknown routes", async () => { mockFetch({}); try { const res = await fetch("http://localhost/api/unknown"); assertEquals(res.status, 404); } finally { restoreFetch(); } }); // --- Mock fetch avancé (méthodes + status codes) --- Deno.test("mockFetch - POST 201 created", async () => { const newStudent = students[0]; mockFetch({ "/students": { method: "POST", status: 201, body: newStudent }, }); try { const res = await fetch("http://localhost/api/students", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(newStudent), }); assertEquals(res.status, 201); const data = await res.json(); assertEquals(data.numEtud, 21212006); } finally { restoreFetch(); } }); Deno.test("mockFetch - DELETE 204 no content", async () => { mockFetch({ "/students/21212006": { method: "DELETE", status: 204 }, }); try { const res = await fetch("http://localhost/api/students/21212006", { method: "DELETE", }); assertEquals(res.status, 204); assertEquals(res.body, null); } finally { restoreFetch(); } }); Deno.test("mockFetch - 404 error response", async () => { mockFetch({ "/students/99999": { status: 404, body: ERROR_NOT_FOUND }, }); try { const res = await fetch("http://localhost/api/students/99999"); assertEquals(res.status, 404); const data = await res.json(); assertEquals(data.error, "Ressource introuvable"); } finally { restoreFetch(); } }); Deno.test("mockFetch - 409 conflict", async () => { mockFetch({ "/enseignements": { method: "POST", status: 409, body: ERROR_CONFLICT }, }); try { const res = await fetch("http://localhost/api/enseignements", { method: "POST", body: JSON.stringify({ idProf: 1, idModule: "JIN702C", idPromo: "4AFISE25/26" }), }); assertEquals(res.status, 409); } finally { restoreFetch(); } }); // --- getFetchCalls --- Deno.test("getFetchCalls - tracks all intercepted calls", async () => { mockFetch({ "/notes": notes }); try { await fetch("http://localhost/api/notes"); await fetch("http://localhost/api/notes?numEtud=21212006"); const calls = getFetchCalls(); assertEquals(calls.length, 2); assertEquals(calls[0].method, "GET"); assertEquals(calls[1].url, "http://localhost/api/notes?numEtud=21212006"); } finally { restoreFetch(); } }); Deno.test("getFetchCalls - captures POST body", async () => { mockFetch({ "/notes": { method: "POST", status: 201, body: notes[0] } }); try { await fetch("http://localhost/api/notes", { method: "POST", body: JSON.stringify(notes[0]), }); const calls = getFetchCalls(); assertEquals(calls.length, 1); assertEquals(calls[0].method, "POST"); assertEquals((calls[0].body as { note: number }).note, 15.5); } finally { restoreFetch(); } }); // --- Mock DB --- Deno.test("mockDb - getTable returns seeded rows", () => { const db = createMockDb({ tables: { students: [...students] } }); assertEquals(db.getTable("students").length, 3); }); Deno.test("mockDb - findOne by key", () => { const db = createMockDb({ tables: { students: [...students] } }); const found = db.findOne("students", (r) => r.numEtud === 21212006); assertExists(found); assertEquals(found.nom, "Dupont"); }); Deno.test("mockDb - findOne returns undefined for missing", () => { const db = createMockDb({ tables: { students: [...students] } }); const found = db.findOne("students", (r) => r.numEtud === 99999); assertEquals(found, undefined); }); Deno.test("mockDb - insert adds a row", () => { const db = createMockDb({ tables: { students: [] } }); const newStudent: Student = { numEtud: 21212099, nom: "Test", prenom: "User", idPromo: "4AFISE25/26", }; db.insert("students", newStudent); assertEquals(db.getTable("students").length, 1); assertEquals( db.findOne("students", (r) => r.numEtud === 21212099)?.nom, "Test", ); }); Deno.test("mockDb - updateWhere modifies matching rows", () => { const db = createMockDb({ tables: { students: [...students] } }); const updated = db.updateWhere( "students", (r) => r.numEtud === 21212006, { prenom: "Marie" }, ); assertEquals(updated, 1); assertEquals( db.findOne("students", (r) => r.numEtud === 21212006)?.prenom, "Marie", ); }); Deno.test("mockDb - deleteWhere removes matching rows", () => { const db = createMockDb({ tables: { students: [...students] } }); const deleted = db.deleteWhere( "students", (r) => r.numEtud === 21212006, ); assertEquals(deleted, 1); assertEquals(db.getTable("students").length, 2); }); Deno.test("mockDb - findMany with filter", () => { const db = createMockDb({ tables: { students: [...students] } }); const promo4 = db.findMany( "students", (r) => r.idPromo === "4AFISE25/26", ); assertEquals(promo4.length, 2); }); Deno.test("mockDb - reset clears all tables", () => { const db = createMockDb({ tables: { students: [...students], notes: [...notes] }, }); db.reset(); assertEquals(db.getTable("students").length, 0); assertEquals(db.getTable("notes").length, 0); }); Deno.test("mockDb - isolated between instances", () => { const db1 = createMockDb({ tables: { students: [...students] } }); const db2 = createMockDb({ tables: { students: [...students] } }); db1.deleteWhere("students", () => true); assertEquals(db1.getTable("students").length, 0); assertEquals(db2.getTable("students").length, 3); }); // --- happy-dom --- Deno.test({ name: "happy-dom - document is available after setup", sanitizeResources: false, sanitizeOps: false, fn() { setupDOM(); try { const doc = globalThis.document; assertExists(doc); const div = doc.createElement("div"); div.textContent = "hello"; doc.body.appendChild(div); assertEquals(doc.body.textContent, "hello"); } finally { cleanupDOM(); } }, });