// Unit tests for /ue-modules endpoints — fixtures, mock API, mock DB import { assertEquals, assertExists } from "@std/assert"; import { mockFetch, restoreFetch } from "../helpers/api_mock.ts"; import { createMockDb } from "../helpers/db_mock.ts"; import { type UeModule, ueModules } from "../helpers/fixtures.ts"; // --- Fixtures --- Deno.test("ue_modules: fixtures have correct shape", () => { assertEquals(ueModules.length, 3); assertEquals(typeof ueModules[0].idModule, "string"); assertEquals(typeof ueModules[0].idUE, "number"); assertEquals(typeof ueModules[0].idPromo, "string"); assertEquals(typeof ueModules[0].coeff, "number"); }); // --- Mock API --- Deno.test("mock API: GET /ue-modules returns list", async () => { mockFetch({ "/ue-modules": ueModules }); try { const res = await fetch("http://localhost/api/ue-modules"); assertEquals(res.status, 200); const data: UeModule[] = await res.json(); assertEquals(data.length, 3); } finally { restoreFetch(); } }); Deno.test("mock API: GET /ue-modules?idPromo filters by promo", async () => { const filtered = ueModules.filter((u) => u.idPromo === "4AFISE25/26"); mockFetch({ "/ue-modules": filtered }); try { const res = await fetch("http://localhost/api/ue-modules?idPromo=4AFISE25%2F26"); const data: UeModule[] = await res.json(); assertEquals(data.length, 2); assertEquals(data.every((u) => u.idPromo === "4AFISE25/26"), true); } finally { restoreFetch(); } }); Deno.test("mock API: GET /ue-modules?idUE filters by UE", async () => { const filtered = ueModules.filter((u) => u.idUE === 1); mockFetch({ "/ue-modules": filtered }); try { const res = await fetch("http://localhost/api/ue-modules?idUE=1"); const data: UeModule[] = await res.json(); assertEquals(data.length, 2); assertEquals(data.every((u) => u.idUE === 1), true); } finally { restoreFetch(); } }); Deno.test("mock API: POST /ue-modules creates association (201)", async () => { const newUeModule: UeModule = { idModule: "JIN705C", idUE: 2, idPromo: "3AFISE25/26", coeff: 3.0 }; mockFetch({ "/ue-modules": { method: "POST", status: 201, body: newUeModule } }); try { const res = await fetch("http://localhost/api/ue-modules", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(newUeModule), }); assertEquals(res.status, 201); const data: UeModule = await res.json(); assertEquals(data.idModule, "JIN705C"); assertEquals(data.coeff, 3.0); } finally { restoreFetch(); } }); Deno.test("mock API: POST /ue-modules 400 on missing fields", async () => { mockFetch({ "/ue-modules": { method: "POST", status: 400 } }); try { const res = await fetch("http://localhost/api/ue-modules", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ idModule: "X" }), }); assertEquals(res.status, 400); } finally { restoreFetch(); } }); Deno.test("mock API: GET /ue-modules/:idModule/:idUE/:idPromo returns association (employee)", async () => { mockFetch({ "/ue-modules/JIN702C/1/4AFISE25": ueModules[0] }); try { const res = await fetch("http://localhost/api/ue-modules/JIN702C/1/4AFISE25%2F26"); assertEquals(res.status, 200); const data: UeModule = await res.json(); assertEquals(data.coeff, 3.0); } finally { restoreFetch(); } }); Deno.test("mock API: GET /ue-modules/:idModule/:idUE/:idPromo 403 for non-employee", async () => { mockFetch({ "/ue-modules/JIN702C/1/4AFISE25": { status: 403 } }); try { const res = await fetch("http://localhost/api/ue-modules/JIN702C/1/4AFISE25%2F26"); assertEquals(res.status, 403); } finally { restoreFetch(); } }); Deno.test("mock API: PUT /ue-modules/:idModule/:idUE/:idPromo updates coeff", async () => { const updated: UeModule = { ...ueModules[0], coeff: 5.0 }; mockFetch({ "/ue-modules/JIN702C/1/4AFISE25": { method: "PUT", status: 200, body: updated } }); try { const res = await fetch("http://localhost/api/ue-modules/JIN702C/1/4AFISE25%2F26", { method: "PUT", headers: { "content-type": "application/json" }, body: JSON.stringify({ coeff: 5.0 }), }); assertEquals(res.status, 200); const data: UeModule = await res.json(); assertEquals(data.coeff, 5.0); } finally { restoreFetch(); } }); Deno.test("mock API: DELETE /ue-modules/:idModule/:idUE/:idPromo returns 204", async () => { mockFetch({ "/ue-modules/JIN702C/1/4AFISE25": { method: "DELETE", status: 204 } }); try { const res = await fetch("http://localhost/api/ue-modules/JIN702C/1/4AFISE25%2F26", { method: "DELETE" }); assertEquals(res.status, 204); } finally { restoreFetch(); } }); // --- Mock DB --- Deno.test("mock DB: find ue-module by composite key", () => { const db = createMockDb({ tables: { ueModules: [...ueModules] } }); const u = db.findOne("ueModules", (u) => u.idModule === "JIN702C" && u.idUE === 1 && u.idPromo === "4AFISE25/26"); assertExists(u); assertEquals(u.coeff, 3.0); }); Deno.test("mock DB: filter ue-modules by promo", () => { const db = createMockDb({ tables: { ueModules: [...ueModules] } }); const rows = db.findMany("ueModules", (u) => u.idPromo === "4AFISE25/26"); assertEquals(rows.length, 2); }); Deno.test("mock DB: insert ue-module", () => { const db = createMockDb({ tables: { ueModules: [...ueModules] } }); db.insert("ueModules", { idModule: "JIN705C", idUE: 2, idPromo: "3AFISE25/26", coeff: 1.5 }); assertEquals(db.getTable("ueModules").length, 4); }); Deno.test("mock DB: update ue-module coeff", () => { const db = createMockDb({ tables: { ueModules: [...ueModules] } }); db.updateWhere("ueModules", (u) => u.idModule === "JIN702C" && u.idUE === 1, { coeff: 6.0 }); assertEquals( db.findOne("ueModules", (u) => u.idModule === "JIN702C" && u.idUE === 1)?.coeff, 6.0, ); }); Deno.test("mock DB: delete ue-module", () => { const db = createMockDb({ tables: { ueModules: [...ueModules] } }); db.deleteWhere("ueModules", (u) => u.idModule === "JIN702C" && u.idUE === 1); assertEquals(db.getTable("ueModules").length, 2); });