2f4d8db1bf
- Unit tests (mock DB + API) for all missing endpoints - Integration tests (Drizzle direct) for all missing entities - E2E tests (handler + real DB) for all missing endpoints - Robustness tests: invalid inputs, SQL injection, type errors, business rule violations - Seed helpers: seedNotes, seedUeModules, seedEnseignements, seedAjustements - Add test:coverage and test:coverage:html tasks to deno.json Tests expose known handler bugs (marked [BUG] in test names): - ajustements PUT/DELETE: .where() without and() modifies all rows for student - Missing try/catch in modules, users, enseignements handlers - Whitespace accepted as valid string values - No type or business rule validation (note bounds, coeff >= 0)
114 lines
3.7 KiB
TypeScript
114 lines
3.7 KiB
TypeScript
// Helper pour les tests d'intégration avec PostgreSQL
|
|
// Nécessite les variables d'environnement POSTGRES_* (ou TEST_DATABASE_URL)
|
|
|
|
import { drizzle } from "npm:drizzle-orm@0.45.2/node-postgres";
|
|
import pg from "npm:pg@8.20.0";
|
|
import * as schema from "$root/databases/schema.ts";
|
|
|
|
const { Pool } = pg;
|
|
|
|
function createTestPool(): pg.Pool {
|
|
const url = Deno.env.get("TEST_DATABASE_URL");
|
|
if (url) {
|
|
return new Pool({ connectionString: url });
|
|
}
|
|
return new Pool({
|
|
host: Deno.env.get("POSTGRES_HOST") ?? "localhost",
|
|
port: Number(Deno.env.get("POSTGRES_PORT") ?? 5432),
|
|
user: Deno.env.get("POSTGRES_USER") ?? "test",
|
|
password: Deno.env.get("POSTGRES_PASS") ?? "test",
|
|
database: Deno.env.get("POSTGRES_DB") ?? "polympr_test",
|
|
ssl: false,
|
|
});
|
|
}
|
|
|
|
export const testPool = createTestPool();
|
|
export const testDb = drizzle(testPool, { schema });
|
|
|
|
const ALL_TABLES =
|
|
'"mobility","ajustements","notes","ue_modules","enseignements","role_permissions","students","users","modules","ues","promotions","permissions","roles"';
|
|
|
|
/**
|
|
* Vide toutes les tables dans le bon ordre.
|
|
* À appeler dans beforeEach de chaque test d'intégration.
|
|
*/
|
|
export async function truncateAll(): Promise<void> {
|
|
const client = await testPool.connect();
|
|
try {
|
|
await client.query(
|
|
`TRUNCATE TABLE ${ALL_TABLES} RESTART IDENTITY CASCADE`,
|
|
);
|
|
} finally {
|
|
client.release();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ferme le pool à la fin de la suite de tests.
|
|
*/
|
|
export async function closeTestPool(): Promise<void> {
|
|
await testPool.end();
|
|
}
|
|
|
|
// --- Helpers d'insertion de fixtures ---
|
|
|
|
export async function seedRoles(
|
|
rows: { nom: string }[],
|
|
): Promise<typeof schema.roles.$inferSelect[]> {
|
|
return await testDb.insert(schema.roles).values(rows).returning();
|
|
}
|
|
|
|
export async function seedPromotions(
|
|
rows: { id: string; annee?: string }[],
|
|
): Promise<typeof schema.promotions.$inferSelect[]> {
|
|
return await testDb.insert(schema.promotions).values(rows).returning();
|
|
}
|
|
|
|
export async function seedStudents(
|
|
rows: { nom: string; prenom: string; idPromo?: string }[],
|
|
): Promise<typeof schema.students.$inferSelect[]> {
|
|
return await testDb.insert(schema.students).values(rows).returning();
|
|
}
|
|
|
|
export async function seedModules(
|
|
rows: { id: string; nom: string }[],
|
|
): Promise<typeof schema.modules.$inferSelect[]> {
|
|
return await testDb.insert(schema.modules).values(rows).returning();
|
|
}
|
|
|
|
export async function seedUes(
|
|
rows: { nom: string }[],
|
|
): Promise<typeof schema.ues.$inferSelect[]> {
|
|
return await testDb.insert(schema.ues).values(rows).returning();
|
|
}
|
|
|
|
export async function seedUsers(
|
|
rows: { id: string; nom: string; prenom: string; idRole?: number }[],
|
|
): Promise<typeof schema.users.$inferSelect[]> {
|
|
return await testDb.insert(schema.users).values(rows).returning();
|
|
}
|
|
|
|
export async function seedNotes(
|
|
rows: { numEtud: number; idModule: string; note: number }[],
|
|
): Promise<typeof schema.notes.$inferSelect[]> {
|
|
return await testDb.insert(schema.notes).values(rows).returning();
|
|
}
|
|
|
|
export async function seedUeModules(
|
|
rows: { idModule: string; idUE: number; idPromo: string; coeff: number }[],
|
|
): Promise<typeof schema.ueModules.$inferSelect[]> {
|
|
return await testDb.insert(schema.ueModules).values(rows).returning();
|
|
}
|
|
|
|
export async function seedEnseignements(
|
|
rows: { idProf: string; idModule: string; idPromo: string }[],
|
|
): Promise<typeof schema.enseignements.$inferSelect[]> {
|
|
return await testDb.insert(schema.enseignements).values(rows).returning();
|
|
}
|
|
|
|
export async function seedAjustements(
|
|
rows: { numEtud: number; idUE: number; valeur: number }[],
|
|
): Promise<typeof schema.ajustements.$inferSelect[]> {
|
|
return await testDb.insert(schema.ajustements).values(rows).returning();
|
|
}
|