217 lines
6.4 KiB
TypeScript
217 lines
6.4 KiB
TypeScript
// #109 - Unit tests for /students endpoints
|
|
// Tests purs : fixtures, mock API, mock DB — aucun appel réseau réel
|
|
|
|
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, students } from "../helpers/fixtures.ts";
|
|
|
|
// --- Fixtures ---
|
|
|
|
Deno.test("students: fixtures have correct shape", () => {
|
|
assertEquals(students.length, 3);
|
|
assertEquals(typeof students[0].numEtud, "number");
|
|
assertEquals(typeof students[0].nom, "string");
|
|
assertEquals(typeof students[0].prenom, "string");
|
|
assertEquals(typeof students[0].idPromo, "string");
|
|
});
|
|
|
|
Deno.test("students: two students belong to the same promo", () => {
|
|
const promo4 = students.filter((s) => s.idPromo === "4AFISE25/26");
|
|
assertEquals(promo4.length, 2);
|
|
});
|
|
|
|
// --- Mock API - GET /students ---
|
|
|
|
Deno.test("mock API: GET /students returns list", async () => {
|
|
mockFetch({ "/students": students });
|
|
try {
|
|
const res = await fetch("http://localhost/api/students");
|
|
assertEquals(res.status, 200);
|
|
const data: Student[] = await res.json();
|
|
assertEquals(data.length, 3);
|
|
assertExists(data.find((s) => s.nom === "Dupont"));
|
|
} finally {
|
|
restoreFetch();
|
|
}
|
|
});
|
|
|
|
Deno.test("mock API: GET /students?idPromo filters by promo", async () => {
|
|
const filtered = students.filter((s) => s.idPromo === "4AFISE25/26");
|
|
mockFetch({ "/students": filtered });
|
|
try {
|
|
const res = await fetch(
|
|
"http://localhost/api/students?idPromo=4AFISE25/26",
|
|
);
|
|
const data: Student[] = await res.json();
|
|
assertEquals(data.length, 2);
|
|
assertEquals(data.every((s) => s.idPromo === "4AFISE25/26"), true);
|
|
} finally {
|
|
restoreFetch();
|
|
}
|
|
});
|
|
|
|
Deno.test("mock API: GET /students/:numEtud returns one student", async () => {
|
|
mockFetch({ "/students/21212006": students[0] });
|
|
try {
|
|
const res = await fetch("http://localhost/api/students/21212006");
|
|
assertEquals(res.status, 200);
|
|
const data: Student = await res.json();
|
|
assertEquals(data.numEtud, 21212006);
|
|
assertEquals(data.nom, "Dupont");
|
|
} finally {
|
|
restoreFetch();
|
|
}
|
|
});
|
|
|
|
Deno.test("mock API: GET /students/:numEtud 404 when not found", async () => {
|
|
mockFetch({
|
|
"/students/99999": {
|
|
status: 404,
|
|
body: { error: "Ressource introuvable" },
|
|
},
|
|
});
|
|
try {
|
|
const res = await fetch("http://localhost/api/students/99999");
|
|
assertEquals(res.status, 404);
|
|
} finally {
|
|
restoreFetch();
|
|
}
|
|
});
|
|
|
|
Deno.test("mock API: POST /students creates student", 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({
|
|
nom: "Dupont",
|
|
prenom: "Jean",
|
|
idPromo: "4AFISE25/26",
|
|
}),
|
|
});
|
|
assertEquals(res.status, 201);
|
|
const data: Student = await res.json();
|
|
assertEquals(data.nom, "Dupont");
|
|
} finally {
|
|
restoreFetch();
|
|
}
|
|
});
|
|
|
|
Deno.test("mock API: PUT /students/:numEtud updates student", async () => {
|
|
const updated = { ...students[0], nom: "Dupont-Modifié" };
|
|
mockFetch({
|
|
"/students/21212006": { method: "PUT", status: 200, body: updated },
|
|
});
|
|
try {
|
|
const res = await fetch("http://localhost/api/students/21212006", {
|
|
method: "PUT",
|
|
headers: { "content-type": "application/json" },
|
|
body: JSON.stringify({
|
|
nom: "Dupont-Modifié",
|
|
prenom: "Jean",
|
|
idPromo: "4AFISE25/26",
|
|
}),
|
|
});
|
|
assertEquals(res.status, 200);
|
|
const data: Student = await res.json();
|
|
assertEquals(data.nom, "Dupont-Modifié");
|
|
} finally {
|
|
restoreFetch();
|
|
}
|
|
});
|
|
|
|
Deno.test("mock API: DELETE /students/:numEtud returns 204", async () => {
|
|
mockFetch({ "/students/21212006": { method: "DELETE", status: 204 } });
|
|
try {
|
|
const res = await fetch("http://localhost/api/students/21212006", {
|
|
method: "DELETE",
|
|
});
|
|
assertEquals(res.status, 204);
|
|
} finally {
|
|
restoreFetch();
|
|
}
|
|
});
|
|
|
|
Deno.test("mock API: POST /students 400 on missing fields", async () => {
|
|
mockFetch({ "/students": { method: "POST", status: 400 } });
|
|
try {
|
|
const res = await fetch("http://localhost/api/students", {
|
|
method: "POST",
|
|
headers: { "content-type": "application/json" },
|
|
body: JSON.stringify({ nom: "Test" }),
|
|
});
|
|
assertEquals(res.status, 400);
|
|
} finally {
|
|
restoreFetch();
|
|
}
|
|
});
|
|
|
|
// --- Mock DB ---
|
|
|
|
Deno.test("mock DB: find student by numEtud", () => {
|
|
const db = createMockDb({ tables: { students: [...students] } });
|
|
const s = db.findOne<Student>("students", (r) => r.numEtud === 21212006);
|
|
assertExists(s);
|
|
assertEquals(s.nom, "Dupont");
|
|
});
|
|
|
|
Deno.test("mock DB: filter students by idPromo", () => {
|
|
const db = createMockDb({ tables: { students: [...students] } });
|
|
const rows = db.findMany<Student>(
|
|
"students",
|
|
(s) => s.idPromo === "4AFISE25/26",
|
|
);
|
|
assertEquals(rows.length, 2);
|
|
});
|
|
|
|
Deno.test("mock DB: insert student increments count", () => {
|
|
const db = createMockDb({ tables: { students: [...students] } });
|
|
db.insert<Student>("students", {
|
|
numEtud: 21212099,
|
|
nom: "Test",
|
|
prenom: "Ing",
|
|
idPromo: "4AFISE25/26",
|
|
});
|
|
assertEquals(db.getTable("students").length, 4);
|
|
});
|
|
|
|
Deno.test("mock DB: update student nom", () => {
|
|
const db = createMockDb({ tables: { students: [...students] } });
|
|
const count = db.updateWhere<Student>(
|
|
"students",
|
|
(s) => s.numEtud === 21212006,
|
|
{ nom: "Nouveau" },
|
|
);
|
|
assertEquals(count, 1);
|
|
assertEquals(
|
|
db.findOne<Student>("students", (s) => s.numEtud === 21212006)?.nom,
|
|
"Nouveau",
|
|
);
|
|
});
|
|
|
|
Deno.test("mock DB: delete student removes exactly one", () => {
|
|
const db = createMockDb({ tables: { students: [...students] } });
|
|
const count = db.deleteWhere<Student>(
|
|
"students",
|
|
(s) => s.numEtud === 21212006,
|
|
);
|
|
assertEquals(count, 1);
|
|
assertEquals(db.getTable("students").length, 2);
|
|
});
|
|
|
|
Deno.test("mock API: getFetchCalls tracks student requests", async () => {
|
|
mockFetch({ "/students": students });
|
|
try {
|
|
await fetch("http://localhost/api/students");
|
|
await fetch("http://localhost/api/students?idPromo=4AFISE25/26");
|
|
const calls = getFetchCalls();
|
|
assertEquals(calls.length, 2);
|
|
assertEquals(calls[0].method, "GET");
|
|
} finally {
|
|
restoreFetch();
|
|
}
|
|
});
|