test : changed test format + added playwright support
Check Deno code / Check Deno code (pull_request) Has been cancelled
Tests / Unit tests (pull_request) Has been cancelled
Tests / Integration tests (pull_request) Has been cancelled
Check Deno code / Check Deno code (push) Has been cancelled
Tests / Unit tests (push) Has been cancelled
Tests / Integration tests (push) Has been cancelled

This commit was merged in pull request #153.
This commit is contained in:
2026-05-03 21:52:02 +02:00
parent ed2fe69f54
commit 951c9c1fea
52 changed files with 3576 additions and 5212 deletions
View File
+160
View File
@@ -0,0 +1,160 @@
// Integration tests for /ajustements — Drizzle ORM direct on real DB
import { assertEquals, assertExists, assertRejects } from "@std/assert";
import {
seedAjustements,
seedPromotions,
seedStudents,
seedUes,
testDb,
truncateAll,
} from "../helpers/db_integration.ts";
import { ajustements } from "$root/databases/schema.ts";
import { and, eq } from "npm:drizzle-orm@0.45.2";
Deno.test({
name: "integration ajustements: list all ajustements",
async fn() {
await truncateAll();
await seedPromotions([{ id: "P1" }]);
const [s] = await seedStudents([{
nom: "Dupont",
prenom: "Jean",
idPromo: "P1",
}]);
const [ue] = await seedUes([{ nom: "UE Info" }]);
await seedAjustements([{ numEtud: s.numEtud, idUE: ue.id, valeur: 13.0 }]);
const rows = await testDb.select().from(ajustements);
assertEquals(rows.length, 1);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ajustements: create and retrieve by composite key",
async fn() {
await truncateAll();
await seedPromotions([{ id: "P1" }]);
const [s] = await seedStudents([{
nom: "Martin",
prenom: "Alice",
idPromo: "P1",
}]);
const [ue] = await seedUes([{ nom: "UE Maths" }]);
const [created] = await testDb
.insert(ajustements)
.values({ numEtud: s.numEtud, idUE: ue.id, valeur: 15.5 })
.returning();
assertExists(created);
assertEquals(created.valeur, 15.5);
const row = await testDb
.select()
.from(ajustements)
.where(
and(eq(ajustements.numEtud, s.numEtud), eq(ajustements.idUE, ue.id)),
)
.then((r) => r[0] ?? null);
assertExists(row);
assertEquals(row.valeur, 15.5);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name:
"integration ajustements: get by composite key returns null when not found",
async fn() {
await truncateAll();
const row = await testDb
.select()
.from(ajustements)
.where(and(eq(ajustements.numEtud, 99999), eq(ajustements.idUE, 99)))
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ajustements: duplicate composite key insert fails",
async fn() {
await truncateAll();
await seedPromotions([{ id: "P1" }]);
const [s] = await seedStudents([{
nom: "Durand",
prenom: "Claire",
idPromo: "P1",
}]);
const [ue] = await seedUes([{ nom: "UE Info" }]);
await seedAjustements([{ numEtud: s.numEtud, idUE: ue.id, valeur: 12.0 }]);
await assertRejects(() =>
testDb.insert(ajustements).values({
numEtud: s.numEtud,
idUE: ue.id,
valeur: 13.0,
})
);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ajustements: update valeur",
async fn() {
await truncateAll();
await seedPromotions([{ id: "P1" }]);
const [s] = await seedStudents([{
nom: "Bernard",
prenom: "Lucie",
idPromo: "P1",
}]);
const [ue] = await seedUes([{ nom: "UE Physique" }]);
await seedAjustements([{ numEtud: s.numEtud, idUE: ue.id, valeur: 10.0 }]);
const [updated] = await testDb
.update(ajustements)
.set({ valeur: 18.0 })
.where(
and(eq(ajustements.numEtud, s.numEtud), eq(ajustements.idUE, ue.id)),
)
.returning();
assertEquals(updated.valeur, 18.0);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ajustements: delete removes the ajustement",
async fn() {
await truncateAll();
await seedPromotions([{ id: "P1" }]);
const [s] = await seedStudents([{
nom: "Thomas",
prenom: "Eva",
idPromo: "P1",
}]);
const [ue] = await seedUes([{ nom: "UE Chimie" }]);
await seedAjustements([{ numEtud: s.numEtud, idUE: ue.id, valeur: 11.0 }]);
await testDb.delete(ajustements).where(
and(eq(ajustements.numEtud, s.numEtud), eq(ajustements.idUE, ue.id)),
);
const row = await testDb
.select()
.from(ajustements)
.where(
and(eq(ajustements.numEtud, s.numEtud), eq(ajustements.idUE, ue.id)),
)
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
+148
View File
@@ -0,0 +1,148 @@
// Integration tests for /enseignements — Drizzle ORM direct on real DB
import { assertEquals, assertExists, assertRejects } from "@std/assert";
import {
seedEnseignements,
seedModules,
seedPromotions,
seedUsers,
testDb,
truncateAll,
} from "../helpers/db_integration.ts";
import { enseignements } from "$root/databases/schema.ts";
import { and, eq } from "npm:drizzle-orm@0.45.2";
Deno.test({
name: "integration enseignements: list all enseignements",
async fn() {
await truncateAll();
await seedUsers([{ id: "prof.dupont", nom: "Dupont", prenom: "Jean" }]);
await seedModules([{ id: "M1", nom: "Mod A" }, { id: "M2", nom: "Mod B" }]);
await seedPromotions([{ id: "P1" }]);
await seedEnseignements([
{ idProf: "prof.dupont", idModule: "M1", idPromo: "P1" },
{ idProf: "prof.dupont", idModule: "M2", idPromo: "P1" },
]);
const rows = await testDb.select().from(enseignements);
assertEquals(rows.length, 2);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration enseignements: create and retrieve by composite key",
async fn() {
await truncateAll();
await seedUsers([{ id: "prof.moreau", nom: "Moreau", prenom: "Sophie" }]);
await seedModules([{ id: "M1", nom: "Mod A" }]);
await seedPromotions([{ id: "P1" }]);
const [created] = await testDb
.insert(enseignements)
.values({ idProf: "prof.moreau", idModule: "M1", idPromo: "P1" })
.returning();
assertExists(created);
assertEquals(created.idProf, "prof.moreau");
const row = await testDb
.select()
.from(enseignements)
.where(
and(
eq(enseignements.idProf, "prof.moreau"),
eq(enseignements.idModule, "M1"),
eq(enseignements.idPromo, "P1"),
),
)
.then((r) => r[0] ?? null);
assertExists(row);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name:
"integration enseignements: get by composite key returns null when not found",
async fn() {
await truncateAll();
const row = await testDb
.select()
.from(enseignements)
.where(
and(
eq(enseignements.idProf, "ghost"),
eq(enseignements.idModule, "GHOST"),
eq(enseignements.idPromo, "GHOST"),
),
)
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration enseignements: duplicate composite key insert fails",
async fn() {
await truncateAll();
await seedUsers([{ id: "prof.dupont", nom: "Dupont", prenom: "Jean" }]);
await seedModules([{ id: "M1", nom: "Mod A" }]);
await seedPromotions([{ id: "P1" }]);
await seedEnseignements([{
idProf: "prof.dupont",
idModule: "M1",
idPromo: "P1",
}]);
await assertRejects(() =>
testDb.insert(enseignements).values({
idProf: "prof.dupont",
idModule: "M1",
idPromo: "P1",
})
);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration enseignements: delete removes the enseignement",
async fn() {
await truncateAll();
await seedUsers([{ id: "prof.dupont", nom: "Dupont", prenom: "Jean" }]);
await seedModules([{ id: "M1", nom: "Mod A" }]);
await seedPromotions([{ id: "P1" }]);
await seedEnseignements([{
idProf: "prof.dupont",
idModule: "M1",
idPromo: "P1",
}]);
await testDb
.delete(enseignements)
.where(
and(
eq(enseignements.idProf, "prof.dupont"),
eq(enseignements.idModule, "M1"),
eq(enseignements.idPromo, "P1"),
),
);
const row = await testDb
.select()
.from(enseignements)
.where(
and(
eq(enseignements.idProf, "prof.dupont"),
eq(enseignements.idModule, "M1"),
eq(enseignements.idPromo, "P1"),
),
)
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
+104
View File
@@ -0,0 +1,104 @@
// #113 - Integration tests for /modules endpoints
import { assertEquals, assertExists, assertRejects } from "@std/assert";
import { seedModules, testDb, truncateAll } from "../helpers/db_integration.ts";
import { modules } from "$root/databases/schema.ts";
import { eq } from "npm:drizzle-orm@0.45.2";
Deno.test({
name: "integration modules: list all modules",
async fn() {
await truncateAll();
await seedModules([{ id: "MATH101", nom: "Mathématiques" }, {
id: "INFO101",
nom: "Informatique",
}]);
const rows = await testDb.select().from(modules);
assertEquals(rows.length, 2);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration modules: create and retrieve by id",
async fn() {
await truncateAll();
const [created] = await testDb.insert(modules).values({
id: "PHYS101",
nom: "Physique",
}).returning();
assertExists(created);
assertEquals(created.id, "PHYS101");
const row = await testDb
.select()
.from(modules)
.where(eq(modules.id, "PHYS101"))
.then((r) => r[0] ?? null);
assertExists(row);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration modules: get by id returns null when not found",
async fn() {
await truncateAll();
const row = await testDb
.select()
.from(modules)
.where(eq(modules.id, "NONEXISTENT"))
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration modules: duplicate id insert fails",
async fn() {
await truncateAll();
await seedModules([{ id: "MATH101", nom: "Mathématiques" }]);
await assertRejects(() =>
testDb.insert(modules).values({ id: "MATH101", nom: "Doublon" })
);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration modules: update nom",
async fn() {
await truncateAll();
await seedModules([{ id: "ELEC201", nom: "Électronique" }]);
const [updated] = await testDb
.update(modules)
.set({ nom: "Électronique numérique" })
.where(eq(modules.id, "ELEC201"))
.returning();
assertEquals(updated.nom, "Électronique numérique");
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration modules: delete removes the module",
async fn() {
await truncateAll();
await seedModules([{ id: "BIO101", nom: "Biologie" }]);
await testDb.delete(modules).where(eq(modules.id, "BIO101"));
const row = await testDb
.select()
.from(modules)
.where(eq(modules.id, "BIO101"))
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
+154
View File
@@ -0,0 +1,154 @@
// Integration tests for /notes — Drizzle ORM direct on real DB
import { assertEquals, assertExists, assertRejects } from "@std/assert";
import {
seedModules,
seedNotes,
seedPromotions,
seedStudents,
testDb,
truncateAll,
} from "../helpers/db_integration.ts";
import { notes } from "$root/databases/schema.ts";
import { and, eq } from "npm:drizzle-orm@0.45.2";
Deno.test({
name: "integration notes: list all notes",
async fn() {
await truncateAll();
await seedPromotions([{ id: "PROMO-2024" }]);
const [s] = await seedStudents([{
nom: "Dupont",
prenom: "Jean",
idPromo: "PROMO-2024",
}]);
await seedModules([{ id: "MOD101", nom: "Module A" }]);
await seedNotes([{ numEtud: s.numEtud, idModule: "MOD101", note: 15.5 }]);
const rows = await testDb.select().from(notes);
assertEquals(rows.length, 1);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration notes: create and retrieve by composite key",
async fn() {
await truncateAll();
await seedPromotions([{ id: "PROMO-2024" }]);
const [s] = await seedStudents([{
nom: "Martin",
prenom: "Alice",
idPromo: "PROMO-2024",
}]);
await seedModules([{ id: "MOD102", nom: "Module B" }]);
const [created] = await testDb.insert(notes).values({
numEtud: s.numEtud,
idModule: "MOD102",
note: 12.0,
}).returning();
assertExists(created);
assertEquals(created.note, 12.0);
const row = await testDb
.select()
.from(notes)
.where(and(eq(notes.numEtud, s.numEtud), eq(notes.idModule, "MOD102")))
.then((r) => r[0] ?? null);
assertExists(row);
assertEquals(row.note, 12.0);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration notes: get by composite key returns null when not found",
async fn() {
await truncateAll();
const row = await testDb
.select()
.from(notes)
.where(and(eq(notes.numEtud, 99999), eq(notes.idModule, "GHOST")))
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration notes: duplicate composite key insert fails",
async fn() {
await truncateAll();
await seedPromotions([{ id: "PROMO-2024" }]);
const [s] = await seedStudents([{
nom: "Durand",
prenom: "Claire",
idPromo: "PROMO-2024",
}]);
await seedModules([{ id: "MOD103", nom: "Module C" }]);
await seedNotes([{ numEtud: s.numEtud, idModule: "MOD103", note: 10.0 }]);
await assertRejects(() =>
testDb.insert(notes).values({
numEtud: s.numEtud,
idModule: "MOD103",
note: 11.0,
})
);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration notes: update note value",
async fn() {
await truncateAll();
await seedPromotions([{ id: "PROMO-2024" }]);
const [s] = await seedStudents([{
nom: "Bernard",
prenom: "Lucie",
idPromo: "PROMO-2024",
}]);
await seedModules([{ id: "MOD104", nom: "Module D" }]);
await seedNotes([{ numEtud: s.numEtud, idModule: "MOD104", note: 8.0 }]);
const [updated] = await testDb
.update(notes)
.set({ note: 16.0 })
.where(and(eq(notes.numEtud, s.numEtud), eq(notes.idModule, "MOD104")))
.returning();
assertEquals(updated.note, 16.0);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration notes: delete removes the note",
async fn() {
await truncateAll();
await seedPromotions([{ id: "PROMO-2024" }]);
const [s] = await seedStudents([{
nom: "Thomas",
prenom: "Eva",
idPromo: "PROMO-2024",
}]);
await seedModules([{ id: "MOD105", nom: "Module E" }]);
await seedNotes([{ numEtud: s.numEtud, idModule: "MOD105", note: 14.0 }]);
await testDb.delete(notes).where(
and(eq(notes.numEtud, s.numEtud), eq(notes.idModule, "MOD105")),
);
const row = await testDb
.select()
.from(notes)
.where(and(eq(notes.numEtud, s.numEtud), eq(notes.idModule, "MOD105")))
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
+112
View File
@@ -0,0 +1,112 @@
// #110 - Integration tests for /promotions endpoints
import { assertEquals, assertExists } from "@std/assert";
import {
seedPromotions,
testDb,
truncateAll,
} from "../helpers/db_integration.ts";
import { promotions } from "$root/databases/schema.ts";
import { eq } from "npm:drizzle-orm@0.45.2";
Deno.test({
name: "integration promotions: list all",
async fn() {
await truncateAll();
await seedPromotions([
{ id: "PEIP1-2024", annee: "2024" },
{ id: "PEIP2-2024", annee: "2024" },
]);
const rows = await testDb.select().from(promotions);
assertEquals(rows.length, 2);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration promotions: create and retrieve by id",
async fn() {
await truncateAll();
const [created] = await testDb
.insert(promotions)
.values({ id: "INFO3-2025", annee: "2025" })
.returning();
assertExists(created);
assertEquals(created.id, "INFO3-2025");
assertEquals(created.annee, "2025");
const row = await testDb
.select()
.from(promotions)
.where(eq(promotions.id, "INFO3-2025"))
.then((r) => r[0] ?? null);
assertExists(row);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration promotions: get by id returns null when not found",
async fn() {
await truncateAll();
const row = await testDb
.select()
.from(promotions)
.where(eq(promotions.id, "NONEXISTENT"))
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration promotions: update annee",
async fn() {
await truncateAll();
await seedPromotions([{ id: "INFO3-2023", annee: "2023" }]);
const [updated] = await testDb
.update(promotions)
.set({ annee: "2024" })
.where(eq(promotions.id, "INFO3-2023"))
.returning();
assertExists(updated);
assertEquals(updated.annee, "2024");
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration promotions: delete removes the row",
async fn() {
await truncateAll();
await seedPromotions([{ id: "INFO3-2022", annee: "2022" }]);
await testDb.delete(promotions).where(eq(promotions.id, "INFO3-2022"));
const row = await testDb
.select()
.from(promotions)
.where(eq(promotions.id, "INFO3-2022"))
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration promotions: update non-existent returns empty",
async fn() {
await truncateAll();
const result = await testDb
.update(promotions)
.set({ annee: "2099" })
.where(eq(promotions.id, "GHOST"))
.returning();
assertEquals(result.length, 0);
},
sanitizeResources: false,
sanitizeOps: false,
});
+123
View File
@@ -0,0 +1,123 @@
// #112 - Integration tests for /roles endpoints
import { assertEquals, assertExists } from "@std/assert";
import { seedRoles, testDb, truncateAll } from "../helpers/db_integration.ts";
import { permissions, rolePermissions, roles } from "$root/databases/schema.ts";
import { eq } from "npm:drizzle-orm@0.45.2";
Deno.test({
name: "integration roles: list all roles",
async fn() {
await truncateAll();
await seedRoles([{ nom: "admin" }, { nom: "employee" }]);
const rows = await testDb.select().from(roles);
assertEquals(rows.length, 2);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration roles: create and retrieve by id",
async fn() {
await truncateAll();
const [created] = await testDb.insert(roles).values({ nom: "viewer" })
.returning();
assertExists(created.id);
assertEquals(created.nom, "viewer");
const row = await testDb
.select()
.from(roles)
.where(eq(roles.id, created.id))
.then((r) => r[0] ?? null);
assertExists(row);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration roles: assign and retrieve permissions",
async fn() {
await truncateAll();
const [role] = await seedRoles([{ nom: "admin" }]);
await testDb.insert(permissions).values([
{ id: "student_read", nom: "Consulter les élèves" },
{ id: "student_write", nom: "Gérer les élèves" },
]);
await testDb.insert(rolePermissions).values([
{ idRole: role.id, idPermission: "student_read" },
{ idRole: role.id, idPermission: "student_write" },
]);
const perms = await testDb
.select()
.from(rolePermissions)
.where(eq(rolePermissions.idRole, role.id));
assertEquals(perms.length, 2);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration roles: update role nom",
async fn() {
await truncateAll();
const [role] = await seedRoles([{ nom: "employee" }]);
const [updated] = await testDb
.update(roles)
.set({ nom: "teacher" })
.where(eq(roles.id, role.id))
.returning();
assertEquals(updated.nom, "teacher");
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration roles: reset permissions on update",
async fn() {
await truncateAll();
const [role] = await seedRoles([{ nom: "admin" }]);
await testDb.insert(permissions).values([
{ id: "note_read", nom: "Consulter les notes" },
{ id: "note_write", nom: "Gérer les notes" },
]);
await testDb.insert(rolePermissions).values([
{ idRole: role.id, idPermission: "note_read" },
]);
// reset
await testDb.delete(rolePermissions).where(
eq(rolePermissions.idRole, role.id),
);
await testDb.insert(rolePermissions).values([
{ idRole: role.id, idPermission: "note_write" },
]);
const perms = await testDb
.select()
.from(rolePermissions)
.where(eq(rolePermissions.idRole, role.id));
assertEquals(perms.length, 1);
assertEquals(perms[0].idPermission, "note_write");
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration roles: delete role removes it",
async fn() {
await truncateAll();
const [role] = await seedRoles([{ nom: "moderator" }]);
await testDb.delete(roles).where(eq(roles.id, role.id));
const row = await testDb
.select()
.from(roles)
.where(eq(roles.id, role.id))
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
+173
View File
@@ -0,0 +1,173 @@
// #109 - Integration tests for /students endpoints
// Teste les opérations DB directement avec une vraie base de données
import { assertEquals, assertExists } from "@std/assert";
import {
seedPromotions,
seedStudents,
testDb,
truncateAll,
} from "../helpers/db_integration.ts";
import { students } from "$root/databases/schema.ts";
import { eq } from "npm:drizzle-orm@0.45.2";
Deno.test({
name: "integration students: list all students",
async fn() {
await truncateAll();
await seedPromotions([{ id: "PEIP1-2024" }]);
await seedStudents([
{ nom: "Dupont", prenom: "Jean", idPromo: "PEIP1-2024" },
{ nom: "Martin", prenom: "Alice", idPromo: "PEIP1-2024" },
]);
const rows = await testDb.select().from(students);
assertEquals(rows.length, 2);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration students: filter by idPromo",
async fn() {
await truncateAll();
await seedPromotions([{ id: "PEIP1-2024" }, { id: "PEIP2-2024" }]);
await seedStudents([
{ nom: "Dupont", prenom: "Jean", idPromo: "PEIP1-2024" },
{ nom: "Martin", prenom: "Alice", idPromo: "PEIP1-2024" },
{ nom: "Durand", prenom: "Claire", idPromo: "PEIP2-2024" },
]);
const rows = await testDb
.select()
.from(students)
.where(eq(students.idPromo, "PEIP1-2024"));
assertEquals(rows.length, 2);
assertEquals(rows.every((s) => s.idPromo === "PEIP1-2024"), true);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration students: create and retrieve by numEtud",
async fn() {
await truncateAll();
await seedPromotions([{ id: "INFO3-2024" }]);
const [created] = await testDb
.insert(students)
.values({ nom: "Leroy", prenom: "Paul", idPromo: "INFO3-2024" })
.returning();
assertExists(created.numEtud);
const row = await testDb
.select()
.from(students)
.where(eq(students.numEtud, created.numEtud))
.then((r) => r[0] ?? null);
assertExists(row);
assertEquals(row.nom, "Leroy");
assertEquals(row.idPromo, "INFO3-2024");
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration students: get by numEtud returns null when not found",
async fn() {
await truncateAll();
const row = await testDb
.select()
.from(students)
.where(eq(students.numEtud, 999999))
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration students: update student fields",
async fn() {
await truncateAll();
await seedPromotions([{ id: "INFO3-2024" }, { id: "INFO4-2024" }]);
const [s] = await seedStudents([
{ nom: "Petit", prenom: "Hugo", idPromo: "INFO3-2024" },
]);
const [updated] = await testDb
.update(students)
.set({ nom: "Grand", idPromo: "INFO4-2024" })
.where(eq(students.numEtud, s.numEtud))
.returning();
assertEquals(updated.nom, "Grand");
assertEquals(updated.idPromo, "INFO4-2024");
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration students: delete student",
async fn() {
await truncateAll();
await seedPromotions([{ id: "INFO3-2024" }]);
const [s] = await seedStudents([
{ nom: "Thomas", prenom: "Eva", idPromo: "INFO3-2024" },
]);
await testDb.delete(students).where(eq(students.numEtud, s.numEtud));
const row = await testDb
.select()
.from(students)
.where(eq(students.numEtud, s.numEtud))
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration students: update non-existent student returns empty",
async fn() {
await truncateAll();
const result = await testDb
.update(students)
.set({ nom: "Ghost" })
.where(eq(students.numEtud, 999999))
.returning();
assertEquals(result.length, 0);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration students: delete non-existent student returns empty",
async fn() {
await truncateAll();
const result = await testDb
.delete(students)
.where(eq(students.numEtud, 999999))
.returning();
assertEquals(result.length, 0);
},
sanitizeResources: false,
sanitizeOps: false,
});
+183
View File
@@ -0,0 +1,183 @@
// Integration tests for /ue-modules — Drizzle ORM direct on real DB
import { assertEquals, assertExists, assertRejects } from "@std/assert";
import {
seedModules,
seedPromotions,
seedUeModules,
seedUes,
testDb,
truncateAll,
} from "../helpers/db_integration.ts";
import { ueModules } from "$root/databases/schema.ts";
import { and, eq } from "npm:drizzle-orm@0.45.2";
Deno.test({
name: "integration ue_modules: list all associations",
async fn() {
await truncateAll();
await seedPromotions([{ id: "P1" }]);
await seedModules([{ id: "M1", nom: "Mod A" }, { id: "M2", nom: "Mod B" }]);
const [ue] = await seedUes([{ nom: "UE Info" }]);
await seedUeModules([
{ idModule: "M1", idUE: ue.id, idPromo: "P1", coeff: 2.0 },
{ idModule: "M2", idUE: ue.id, idPromo: "P1", coeff: 3.0 },
]);
const rows = await testDb.select().from(ueModules);
assertEquals(rows.length, 2);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ue_modules: create and retrieve by composite key",
async fn() {
await truncateAll();
await seedPromotions([{ id: "P1" }]);
await seedModules([{ id: "M1", nom: "Mod A" }]);
const [ue] = await seedUes([{ nom: "UE Maths" }]);
const [created] = await testDb
.insert(ueModules)
.values({ idModule: "M1", idUE: ue.id, idPromo: "P1", coeff: 4.0 })
.returning();
assertExists(created);
assertEquals(created.coeff, 4.0);
const row = await testDb
.select()
.from(ueModules)
.where(
and(
eq(ueModules.idModule, "M1"),
eq(ueModules.idUE, ue.id),
eq(ueModules.idPromo, "P1"),
),
)
.then((r) => r[0] ?? null);
assertExists(row);
assertEquals(row.coeff, 4.0);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name:
"integration ue_modules: get by composite key returns null when not found",
async fn() {
await truncateAll();
const row = await testDb
.select()
.from(ueModules)
.where(
and(
eq(ueModules.idModule, "GHOST"),
eq(ueModules.idUE, 99),
eq(ueModules.idPromo, "GHOST"),
),
)
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ue_modules: duplicate composite key insert fails",
async fn() {
await truncateAll();
await seedPromotions([{ id: "P1" }]);
await seedModules([{ id: "M1", nom: "Mod A" }]);
const [ue] = await seedUes([{ nom: "UE Info" }]);
await seedUeModules([{
idModule: "M1",
idUE: ue.id,
idPromo: "P1",
coeff: 2.0,
}]);
await assertRejects(() =>
testDb.insert(ueModules).values({
idModule: "M1",
idUE: ue.id,
idPromo: "P1",
coeff: 5.0,
})
);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ue_modules: update coeff",
async fn() {
await truncateAll();
await seedPromotions([{ id: "P1" }]);
await seedModules([{ id: "M1", nom: "Mod A" }]);
const [ue] = await seedUes([{ nom: "UE Info" }]);
await seedUeModules([{
idModule: "M1",
idUE: ue.id,
idPromo: "P1",
coeff: 2.0,
}]);
const [updated] = await testDb
.update(ueModules)
.set({ coeff: 6.0 })
.where(
and(
eq(ueModules.idModule, "M1"),
eq(ueModules.idUE, ue.id),
eq(ueModules.idPromo, "P1"),
),
)
.returning();
assertEquals(updated.coeff, 6.0);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ue_modules: delete removes the association",
async fn() {
await truncateAll();
await seedPromotions([{ id: "P1" }]);
await seedModules([{ id: "M1", nom: "Mod A" }]);
const [ue] = await seedUes([{ nom: "UE Info" }]);
await seedUeModules([{
idModule: "M1",
idUE: ue.id,
idPromo: "P1",
coeff: 2.0,
}]);
await testDb
.delete(ueModules)
.where(
and(
eq(ueModules.idModule, "M1"),
eq(ueModules.idUE, ue.id),
eq(ueModules.idPromo, "P1"),
),
);
const row = await testDb
.select()
.from(ueModules)
.where(
and(
eq(ueModules.idModule, "M1"),
eq(ueModules.idUE, ue.id),
eq(ueModules.idPromo, "P1"),
),
)
.then((r) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
+90
View File
@@ -0,0 +1,90 @@
// Integration tests for /ues — Drizzle ORM direct on real DB
import { assertEquals, assertExists, assertRejects } from "@std/assert";
import { seedUes, testDb, truncateAll } from "../helpers/db_integration.ts";
import { ues } from "$root/databases/schema.ts";
import { eq } from "npm:drizzle-orm@0.45.2";
Deno.test({
name: "integration ues: list all UEs",
async fn() {
await truncateAll();
await seedUes([{ nom: "UE Informatique" }, { nom: "UE Mathématiques" }]);
const rows = await testDb.select().from(ues);
assertEquals(rows.length, 2);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ues: create and retrieve by id",
async fn() {
await truncateAll();
const [created] = await testDb.insert(ues).values({ nom: "UE Physique" })
.returning();
assertExists(created);
assertExists(created.id);
assertEquals(created.nom, "UE Physique");
const row = await testDb.select().from(ues).where(eq(ues.id, created.id))
.then((r) => r[0] ?? null);
assertExists(row);
assertEquals(row.nom, "UE Physique");
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ues: get by id returns null when not found",
async fn() {
await truncateAll();
const row = await testDb.select().from(ues).where(eq(ues.id, 99999)).then((
r,
) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ues: update nom",
async fn() {
await truncateAll();
const [ue] = await seedUes([{ nom: "UE Chimie" }]);
const [updated] = await testDb.update(ues).set({
nom: "UE Chimie organique",
}).where(eq(ues.id, ue.id)).returning();
assertEquals(updated.nom, "UE Chimie organique");
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ues: delete removes the UE",
async fn() {
await truncateAll();
const [ue] = await seedUes([{ nom: "UE à supprimer" }]);
await testDb.delete(ues).where(eq(ues.id, ue.id));
const row = await testDb.select().from(ues).where(eq(ues.id, ue.id)).then((
r,
) => r[0] ?? null);
assertEquals(row, null);
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration ues: nom is required (not null)",
async fn() {
await truncateAll();
// deno-lint-ignore no-explicit-any
await assertRejects(() => testDb.insert(ues).values({ nom: null as any }));
},
sanitizeResources: false,
sanitizeOps: false,
});
+58
View File
@@ -0,0 +1,58 @@
import { assertEquals, assertExists } from "@std/assert";
import {
closeTestPool,
seedRoles,
seedUsers,
testDb,
truncateAll,
} from "../helpers/db_integration.ts";
import { users } from "$root/databases/schema.ts";
Deno.test({
name: "integration: GET /users - DB round trip",
async fn() {
await truncateAll();
const [role] = await seedRoles([{ nom: "employee" }]);
await seedUsers([
{ id: "dupont.jean", nom: "Dupont", prenom: "Jean", idRole: role.id },
{ id: "martin.alice", nom: "Martin", prenom: "Alice", idRole: role.id },
]);
const rows = await testDb.select().from(users);
assertEquals(rows.length, 2);
assertExists(rows.find((u) => u.id === "dupont.jean"));
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration: INSERT user and retrieve by id",
async fn() {
await truncateAll();
const [role] = await seedRoles([{ nom: "admin" }]);
const [created] = await testDb.insert(users).values({
id: "durand.claire",
nom: "Durand",
prenom: "Claire",
idRole: role.id,
}).returning();
assertExists(created);
assertEquals(created.id, "durand.claire");
assertEquals(created.nom, "Durand");
},
sanitizeResources: false,
sanitizeOps: false,
});
Deno.test({
name: "integration: cleanup - close pool",
async fn() {
await closeTestPool();
},
sanitizeResources: false,
sanitizeOps: false,
});