267 lines
7.4 KiB
TypeScript
267 lines
7.4 KiB
TypeScript
import { assertEquals, assertExists } from "@std/assert";
|
|
import { getFetchCalls, mockFetch, restoreFetch } from "../helpers/api_mock.ts";
|
|
import { createMockDb } from "../helpers/db_mock.ts";
|
|
import {
|
|
ERROR_CONFLICT,
|
|
ERROR_NOT_FOUND,
|
|
modules,
|
|
notes,
|
|
type Student,
|
|
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<Student>("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<Student>("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<Student>("students", (r) => r.numEtud === 21212099)?.nom,
|
|
"Test",
|
|
);
|
|
});
|
|
|
|
Deno.test("mockDb - updateWhere modifies matching rows", () => {
|
|
const db = createMockDb({ tables: { students: [...students] } });
|
|
const updated = db.updateWhere<Student>(
|
|
"students",
|
|
(r) => r.numEtud === 21212006,
|
|
{ prenom: "Marie" },
|
|
);
|
|
assertEquals(updated, 1);
|
|
assertEquals(
|
|
db.findOne<Student>("students", (r) => r.numEtud === 21212006)?.prenom,
|
|
"Marie",
|
|
);
|
|
});
|
|
|
|
Deno.test("mockDb - deleteWhere removes matching rows", () => {
|
|
const db = createMockDb({ tables: { students: [...students] } });
|
|
const deleted = db.deleteWhere<Student>(
|
|
"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<Student>(
|
|
"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<Student>("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();
|
|
}
|
|
},
|
|
});
|