fix: correct handler bugs exposed by test suite
Check Deno code / Check Deno code (pull_request) Failing after 6s
Tests / Unit tests (pull_request) Successful in 13s
Tests / Integration tests (pull_request) Successful in 1m17s

- ajustements [numEtud]/[idUE]: fix .where() missing and() — PUT/DELETE
  were applying only numEtud condition, modifying all rows for a student
- modules/users/enseignements POST: add try/catch, return 500 on invalid JSON
- modules/[idModule] PUT: add try/catch + type check on nom (string required)
- modules POST: add .trim() check to reject whitespace-only id/nom
- users POST: add .trim() check to reject whitespace-only id/nom/prenom
- ues POST: add .trim() check to reject whitespace-only nom
- notes POST: add type check (typeof number) and bounds check (0 ≤ note ≤ 20)
- ue-modules POST: add coeff >= 0 validation

Update robustness tests to reflect fixed behavior (remove [BUG] labels,
replace assertRejects with status code assertions).
This commit is contained in:
2026-04-26 19:01:53 +02:00
parent 2f4d8db1bf
commit b0930b8da2
9 changed files with 166 additions and 99 deletions
+6 -5
View File
@@ -26,11 +26,12 @@ export const handler: Handlers<null, AuthenticatedState> = {
return FORBIDDEN; return FORBIDDEN;
} }
const body: { let body: { idProf: string; idModule: string; idPromo: string };
idProf: string; try {
idModule: string; body = await request.json();
idPromo: string; } catch {
} = await request.json(); return new Response(null, { status: 500 });
}
if (!body.idProf || !body.idModule || !body.idPromo) { if (!body.idProf || !body.idModule || !body.idPromo) {
return new Response(null, { status: 400 }); return new Response(null, { status: 400 });
+7 -2
View File
@@ -31,9 +31,14 @@ export const handler: Handlers<null, AuthenticatedState> = {
return new Response(null, { status: 403 }); return new Response(null, { status: 403 });
} }
const body: { id: string; nom: string } = await request.json(); let body: { id: string; nom: string };
try {
body = await request.json();
} catch {
return new Response(null, { status: 500 });
}
if (!body.id || !body.nom) { if (!body.id || !body.id.trim() || !body.nom || !body.nom.trim()) {
return new Response(null, { status: 400 }); return new Response(null, { status: 400 });
} }
+10 -1
View File
@@ -33,7 +33,16 @@ export const handler: Handlers<null, AuthenticatedState> = {
request: Request, request: Request,
context: FreshContext<AuthenticatedState>, context: FreshContext<AuthenticatedState>,
): Promise<Response> { ): Promise<Response> {
const body: { nom: string } = await request.json(); let body: { nom: string };
try {
body = await request.json();
} catch {
return new Response(null, { status: 500 });
}
if (typeof body.nom !== "string") {
return new Response(null, { status: 400 });
}
const [updated] = await db const [updated] = await db
.update(modules) .update(modules)
+10 -3
View File
@@ -27,10 +27,17 @@ export const handler: Handlers<null, AuthenticatedState> = {
request: Request, request: Request,
_context: FreshContext<AuthenticatedState>, _context: FreshContext<AuthenticatedState>,
): Promise<Response> { ): Promise<Response> {
const body: { id: string; nom: string; prenom: string; idRole: number } = let body: { id: string; nom: string; prenom: string; idRole: number };
await request.json(); try {
body = await request.json();
} catch {
return new Response(null, { status: 500 });
}
if (!body.id || !body.nom || !body.prenom) { if (
!body.id || !body.id.trim() || !body.nom || !body.nom.trim() ||
!body.prenom || !body.prenom.trim()
) {
return new Response(null, { status: 400 }); return new Response(null, { status: 400 });
} }
@@ -2,7 +2,7 @@ import { FreshContext, Handlers } from "$fresh/server.ts";
import { db } from "$root/databases/db.ts"; import { db } from "$root/databases/db.ts";
import { ajustements } from "$root/databases/schema.ts"; import { ajustements } from "$root/databases/schema.ts";
import { AuthenticatedState } from "$root/defaults/interfaces.ts"; import { AuthenticatedState } from "$root/defaults/interfaces.ts";
import { eq } from "npm:drizzle-orm@0.45.2"; import { and, eq } from "npm:drizzle-orm@0.45.2";
const NOT_FOUND = new Response( const NOT_FOUND = new Response(
JSON.stringify({ error: "Ajustement introuvable" }), JSON.stringify({ error: "Ajustement introuvable" }),
@@ -31,7 +31,7 @@ export const handler: Handlers<null, AuthenticatedState> = {
const ajustement = await db const ajustement = await db
.select() .select()
.from(ajustements) .from(ajustements)
.where(eq(ajustements.numEtud, numEtud), eq(ajustements.idUE, idUE)) .where(and(eq(ajustements.numEtud, numEtud), eq(ajustements.idUE, idUE)))
.then((rows) => rows[0] ?? null); .then((rows) => rows[0] ?? null);
if (!ajustement) return NOT_FOUND; if (!ajustement) return NOT_FOUND;
@@ -69,7 +69,7 @@ export const handler: Handlers<null, AuthenticatedState> = {
const [updated] = await db const [updated] = await db
.update(ajustements) .update(ajustements)
.set({ valeur: body.valeur }) .set({ valeur: body.valeur })
.where(eq(ajustements.numEtud, numEtud), eq(ajustements.idUE, idUE)) .where(and(eq(ajustements.numEtud, numEtud), eq(ajustements.idUE, idUE)))
.returning(); .returning();
if (!updated) return NOT_FOUND; if (!updated) return NOT_FOUND;
@@ -97,7 +97,7 @@ export const handler: Handlers<null, AuthenticatedState> = {
const [deleted] = await db const [deleted] = await db
.delete(ajustements) .delete(ajustements)
.where(eq(ajustements.numEtud, numEtud), eq(ajustements.idUE, idUE)) .where(and(eq(ajustements.numEtud, numEtud), eq(ajustements.idUE, idUE)))
.returning(); .returning();
if (!deleted) return NOT_FOUND; if (!deleted) return NOT_FOUND;
+6
View File
@@ -49,6 +49,12 @@ export const handler: Handlers = {
}); });
} }
if (typeof note !== "number" || note < 0 || note > 20) {
return new Response("Champ 'note' doit être un nombre entre 0 et 20", {
status: 400,
});
}
const result = await db.insert(notes).values({ note, numEtud, idModule }) const result = await db.insert(notes).values({ note, numEtud, idModule })
.returning(); .returning();
+6
View File
@@ -47,6 +47,12 @@ export const handler: Handlers = {
); );
} }
if (typeof coeff !== "number" || coeff < 0) {
return new Response("Champ 'coeff' doit être un nombre >= 0", {
status: 400,
});
}
const result = await db.insert(ueModules).values({ const result = await db.insert(ueModules).values({
idModule, idModule,
idUE, idUE,
+1 -1
View File
@@ -24,7 +24,7 @@ export const handler: Handlers = {
const body = await request.json(); const body = await request.json();
const { nom } = body; const { nom } = body;
if (!nom) { if (!nom || !nom.trim()) {
return new Response("Champ 'nom' manquant", { status: 400 }); return new Response("Champ 'nom' manquant", { status: 400 });
} }
+116 -83
View File
@@ -4,7 +4,7 @@
// Les tests marqués [BUG] représentent le comportement ATTENDU — ils échouent // Les tests marqués [BUG] représentent le comportement ATTENDU — ils échouent
// intentionnellement pour exposer un bug dans le handler ciblé. // intentionnellement pour exposer un bug dans le handler ciblé.
import { assertEquals, assertRejects } from "@std/assert"; import { assertEquals } from "@std/assert";
import { import {
makeContextWithAffiliation, makeContextWithAffiliation,
makeEmployeeContext, makeEmployeeContext,
@@ -90,7 +90,8 @@ Deno.test({
}); });
Deno.test({ Deno.test({
name: "robustness: POST /ajustements malformed JSON → 500 (try/catch présent)", name:
"robustness: POST /ajustements malformed JSON → 500 (try/catch présent)",
async fn() { async fn() {
await truncateAll(); await truncateAll();
const res = await ajustementsHandler.POST!( const res = await ajustementsHandler.POST!(
@@ -103,49 +104,43 @@ Deno.test({
sanitizeOps: false, sanitizeOps: false,
}); });
// Handlers SANS try/catch — throwent au lieu de retourner 500
// [BUG] Ces handlers devraient retourner 500, pas throw
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /modules malformed JSON → throw (pas de try/catch)", name: "robustness: POST /modules malformed JSON → 500",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await assertRejects(() => const res = await modulesHandler.POST!(
modulesHandler.POST!( makeMalformedRequest("/modules"),
makeMalformedRequest("/modules"), makeEmployeeContext(),
makeEmployeeContext(),
)
); );
assertEquals(res.status, 500);
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
}); });
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /enseignements malformed JSON → throw (pas de try/catch)", name: "robustness: POST /enseignements malformed JSON → 500",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await assertRejects(() => const res = await enseignementsHandler.POST!(
enseignementsHandler.POST!( makeMalformedRequest("/enseignements"),
makeMalformedRequest("/enseignements"), makeEmployeeContext(),
makeEmployeeContext(),
)
); );
assertEquals(res.status, 500);
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
}); });
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /users malformed JSON → throw (pas de try/catch)", name: "robustness: POST /users malformed JSON → 500",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await assertRejects(() => const res = await usersHandler.POST!(
usersHandler.POST!( makeMalformedRequest("/users"),
makeMalformedRequest("/users"), makeEmployeeContext(),
makeEmployeeContext(),
)
); );
assertEquals(res.status, 500);
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
@@ -170,15 +165,14 @@ Deno.test({
}); });
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /modules sans body → throw (pas de try/catch)", name: "robustness: POST /modules sans body → 500",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await assertRejects(() => const res = await modulesHandler.POST!(
modulesHandler.POST!( makeEmptyBodyRequest("/modules"),
makeEmptyBodyRequest("/modules"), makeEmployeeContext(),
makeEmployeeContext(),
)
); );
assertEquals(res.status, 500);
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
@@ -235,52 +229,42 @@ Deno.test({
// ============================================================================= // =============================================================================
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /modules id=espaces → devrait être 400, retourne 201", name: "robustness: POST /modules id=espaces → 400",
async fn() { async fn() {
await truncateAll(); await truncateAll();
const res = await modulesHandler.POST!( const res = await modulesHandler.POST!(
makeJsonRequest("/modules", "POST", { id: " ", nom: "Test" }), makeJsonRequest("/modules", "POST", { id: " ", nom: "Test" }),
makeEmployeeContext(), makeEmployeeContext(),
); );
// Le handler vérifie !body.id → " " est truthy → passe → s'insère assertEquals(res.status, 400);
// Comportement attendu : 400
// Comportement réel : 201 (bug : pas de trim())
assertEquals(res.status, 400); // ← va échouer, expose le bug
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
}); });
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /ues nom=espaces → devrait être 400, retourne 201", name: "robustness: POST /ues nom=espaces → 400",
async fn() { async fn() {
await truncateAll(); await truncateAll();
const res = await uesHandler.POST!( const res = await uesHandler.POST!(
makeJsonRequest("/ues", "POST", { nom: " " }), makeJsonRequest("/ues", "POST", { nom: " " }),
makeEmployeeContext(), makeEmployeeContext(),
); );
assertEquals(res.status, 400); // ← va échouer, expose le bug assertEquals(res.status, 400);
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
}); });
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /users id=espaces → devrait être 400, retourne 201", name: "robustness: POST /users id=espaces → 400",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await assertRejects( const res = await usersHandler.POST!(
// sans try/catch + whitespace id → s'insère (ou throw si DB rejette) makeJsonRequest("/users", "POST", { id: " ", nom: "X", prenom: "Y" }),
// Dans tous les cas le handler ne valide pas correctement makeEmployeeContext(),
async () => {
const res = await usersHandler.POST!(
makeJsonRequest("/users", "POST", { id: " ", nom: "X", prenom: "Y" }),
makeEmployeeContext(),
);
// Si pas de throw : le handler a inséré des espaces en DB
assertEquals(res.status, 400);
},
); );
assertEquals(res.status, 400);
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
@@ -291,36 +275,40 @@ Deno.test({
// ============================================================================= // =============================================================================
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /notes note=string → devrait être 400, retourne 500", name: "robustness: POST /notes note=string → 400",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await seedPromotions([{ id: "P1" }]); await seedPromotions([{ id: "P1" }]);
const [s] = await seedStudents([{ nom: "Test", prenom: "User", idPromo: "P1" }]); const [s] = await seedStudents([{
nom: "Test",
prenom: "User",
idPromo: "P1",
}]);
await seedModules([{ id: "M1", nom: "Mod" }]); await seedModules([{ id: "M1", nom: "Mod" }]);
const res = await notesHandler.POST!( const res = await notesHandler.POST!(
makeJsonRequest("/notes", "POST", { note: "pas-un-nombre", numEtud: s.numEtud, idModule: "M1" }), makeJsonRequest("/notes", "POST", {
note: "pas-un-nombre",
numEtud: s.numEtud,
idModule: "M1",
}),
makeEmployeeContext(), makeEmployeeContext(),
); );
// "pas-un-nombre" !== undefined → passe la validation → DB rejette → 500 assertEquals(res.status, 400);
// Comportement attendu : 400 (validation de type)
// Comportement réel : 500
assertEquals(res.status, 400); // ← va échouer, expose le bug
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
}); });
Deno.test({ Deno.test({
name: "robustness [BUG]: PUT /modules/:id nom=number → devrait être 400, throw ou insère", name: "robustness: PUT /modules/:id nom=number → 400",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await seedModules([{ id: "M1", nom: "Mod" }]); await seedModules([{ id: "M1", nom: "Mod" }]);
await assertRejects(() => const res = await moduleHandler.PUT!(
moduleHandler.PUT!( makeJsonRequest("/modules/M1", "PUT", { nom: 42 }),
makeJsonRequest("/modules/M1", "PUT", { nom: 42 }), makeEmployeeContext({ idModule: "M1" }),
makeEmployeeContext({ idModule: "M1" }),
)
); );
assertEquals(res.status, 400);
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
@@ -331,12 +319,17 @@ Deno.test({
// ============================================================================= // =============================================================================
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /ajustements numEtud=0 → 400 pour mauvaise raison", name:
"robustness [BUG]: POST /ajustements numEtud=0 → 400 pour mauvaise raison",
async fn() { async fn() {
await truncateAll(); await truncateAll();
const [ue] = await seedUes([{ nom: "UE Info" }]); const [ue] = await seedUes([{ nom: "UE Info" }]);
const res = await ajustementsHandler.POST!( const res = await ajustementsHandler.POST!(
makeJsonRequest("/ajustements", "POST", { numEtud: 0, idUE: ue.id, valeur: 10.0 }), makeJsonRequest("/ajustements", "POST", {
numEtud: 0,
idUE: ue.id,
valeur: 10.0,
}),
makeEmployeeContext(), makeEmployeeContext(),
); );
// !0 === true → retourne 400 à cause du falsy check, pas d'une vraie validation // !0 === true → retourne 400 à cause du falsy check, pas d'une vraie validation
@@ -353,9 +346,17 @@ Deno.test({
async fn() { async fn() {
await truncateAll(); await truncateAll();
await seedPromotions([{ id: "P1" }]); await seedPromotions([{ id: "P1" }]);
const [s] = await seedStudents([{ nom: "Test", prenom: "User", idPromo: "P1" }]); const [s] = await seedStudents([{
nom: "Test",
prenom: "User",
idPromo: "P1",
}]);
const res = await ajustementsHandler.POST!( const res = await ajustementsHandler.POST!(
makeJsonRequest("/ajustements", "POST", { numEtud: s.numEtud, idUE: 0, valeur: 10.0 }), makeJsonRequest("/ajustements", "POST", {
numEtud: s.numEtud,
idUE: 0,
valeur: 10.0,
}),
makeEmployeeContext(), makeEmployeeContext(),
); );
assertEquals(res.status, 400); // !0 → 400, message trompeur assertEquals(res.status, 400); // !0 → 400, message trompeur
@@ -369,14 +370,20 @@ Deno.test({
// ============================================================================= // =============================================================================
Deno.test({ Deno.test({
name: "robustness: POST /ue-modules coeff=0 → 201 (zéro est une valeur valide)", name:
"robustness: POST /ue-modules coeff=0 → 201 (zéro est une valeur valide)",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await seedPromotions([{ id: "P1" }]); await seedPromotions([{ id: "P1" }]);
await seedModules([{ id: "M1", nom: "Mod" }]); await seedModules([{ id: "M1", nom: "Mod" }]);
const [ue] = await seedUes([{ nom: "UE Info" }]); const [ue] = await seedUes([{ nom: "UE Info" }]);
const res = await ueModulesHandler.POST!( const res = await ueModulesHandler.POST!(
makeJsonRequest("/ue-modules", "POST", { idModule: "M1", idUE: ue.id, idPromo: "P1", coeff: 0 }), makeJsonRequest("/ue-modules", "POST", {
idModule: "M1",
idUE: ue.id,
idPromo: "P1",
coeff: 0,
}),
makeEmployeeContext(), makeEmployeeContext(),
); );
// coeff === undefined → false pour 0 → passe ✓ // coeff === undefined → false pour 0 → passe ✓
@@ -392,7 +399,8 @@ Deno.test({
// ============================================================================= // =============================================================================
Deno.test({ Deno.test({
name: "robustness: GET /modules avec SQL injection dans id → 404 (Drizzle paramètre)", name:
"robustness: GET /modules avec SQL injection dans id → 404 (Drizzle paramètre)",
async fn() { async fn() {
await truncateAll(); await truncateAll();
const injectionId = "'; DROP TABLE modules; --"; const injectionId = "'; DROP TABLE modules; --";
@@ -409,7 +417,8 @@ Deno.test({
}); });
Deno.test({ Deno.test({
name: "robustness: POST /modules avec SQL injection dans id → s'insère littéralement (safe)", name:
"robustness: POST /modules avec SQL injection dans id → s'insère littéralement (safe)",
async fn() { async fn() {
await truncateAll(); await truncateAll();
const injectionId = "'; DROP TABLE modules; --"; const injectionId = "'; DROP TABLE modules; --";
@@ -429,52 +438,72 @@ Deno.test({
// ============================================================================= // =============================================================================
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /notes note > 20 → devrait être 400, retourne 201", name: "robustness: POST /notes note > 20 → 400",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await seedPromotions([{ id: "P1" }]); await seedPromotions([{ id: "P1" }]);
const [s] = await seedStudents([{ nom: "Test", prenom: "User", idPromo: "P1" }]); const [s] = await seedStudents([{
nom: "Test",
prenom: "User",
idPromo: "P1",
}]);
await seedModules([{ id: "M1", nom: "Mod" }]); await seedModules([{ id: "M1", nom: "Mod" }]);
const res = await notesHandler.POST!( const res = await notesHandler.POST!(
makeJsonRequest("/notes", "POST", { note: 999, numEtud: s.numEtud, idModule: "M1" }), makeJsonRequest("/notes", "POST", {
note: 999,
numEtud: s.numEtud,
idModule: "M1",
}),
makeEmployeeContext(), makeEmployeeContext(),
); );
// Aucune validation de borne → 999 s'insère → 201 assertEquals(res.status, 400);
assertEquals(res.status, 400); // ← va échouer, expose le manque de validation métier
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
}); });
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /notes note < 0 → devrait être 400, retourne 201", name: "robustness: POST /notes note < 0 → 400",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await seedPromotions([{ id: "P1" }]); await seedPromotions([{ id: "P1" }]);
const [s] = await seedStudents([{ nom: "Test", prenom: "User", idPromo: "P1" }]); const [s] = await seedStudents([{
nom: "Test",
prenom: "User",
idPromo: "P1",
}]);
await seedModules([{ id: "M1", nom: "Mod" }]); await seedModules([{ id: "M1", nom: "Mod" }]);
const res = await notesHandler.POST!( const res = await notesHandler.POST!(
makeJsonRequest("/notes", "POST", { note: -5, numEtud: s.numEtud, idModule: "M1" }), makeJsonRequest("/notes", "POST", {
note: -5,
numEtud: s.numEtud,
idModule: "M1",
}),
makeEmployeeContext(), makeEmployeeContext(),
); );
assertEquals(res.status, 400); // ← va échouer assertEquals(res.status, 400);
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
}); });
Deno.test({ Deno.test({
name: "robustness [BUG]: POST /ue-modules coeff négatif → devrait être 400, retourne 201", name: "robustness: POST /ue-modules coeff négatif → 400",
async fn() { async fn() {
await truncateAll(); await truncateAll();
await seedPromotions([{ id: "P1" }]); await seedPromotions([{ id: "P1" }]);
await seedModules([{ id: "M1", nom: "Mod" }]); await seedModules([{ id: "M1", nom: "Mod" }]);
const [ue] = await seedUes([{ nom: "UE Info" }]); const [ue] = await seedUes([{ nom: "UE Info" }]);
const res = await ueModulesHandler.POST!( const res = await ueModulesHandler.POST!(
makeJsonRequest("/ue-modules", "POST", { idModule: "M1", idUE: ue.id, idPromo: "P1", coeff: -3 }), makeJsonRequest("/ue-modules", "POST", {
idModule: "M1",
idUE: ue.id,
idPromo: "P1",
coeff: -3,
}),
makeEmployeeContext(), makeEmployeeContext(),
); );
assertEquals(res.status, 400); // ← va échouer assertEquals(res.status, 400);
}, },
sanitizeResources: false, sanitizeResources: false,
sanitizeOps: false, sanitizeOps: false,
@@ -491,7 +520,10 @@ Deno.test({
// Ce test crée un module // Ce test crée un module
await truncateAll(); await truncateAll();
await modulesHandler.POST!( await modulesHandler.POST!(
makeJsonRequest("/modules", "POST", { id: "ISOLATION-TEST", nom: "Test" }), makeJsonRequest("/modules", "POST", {
id: "ISOLATION-TEST",
nom: "Test",
}),
makeEmployeeContext(), makeEmployeeContext(),
); );
}, },
@@ -500,7 +532,8 @@ Deno.test({
}); });
Deno.test({ Deno.test({
name: "robustness: isolation — truncateAll efface bien les données du test précédent", name:
"robustness: isolation — truncateAll efface bien les données du test précédent",
async fn() { async fn() {
await truncateAll(); await truncateAll();
// Le module créé dans le test précédent ne doit plus exister // Le module créé dans le test précédent ne doit plus exister