// Mock de la couche Drizzle pour les tests unitaires/intégration // Permet de tester les handlers sans connexion PostgreSQL export interface MockQueryResult { rows: T[]; } export interface MockDbConfig { // Table name → array of rows // deno-lint-ignore no-explicit-any tables: Record[]>; } /** * Crée un mock de la DB Drizzle. * Simule select/insert/update/delete avec un store en mémoire. * * Usage : * ```ts * const db = createMockDb({ * tables: { * students: [{ numEtud: 21212006, nom: "Dupont", ... }], * notes: [], * } * }); * * // Lire toutes les lignes d'une table * const rows = db.getTable("students"); * * // Insérer * db.insert("students", { numEtud: 21212009, nom: "Test", ... }); * * // Trouver par clé * const student = db.findOne("students", (r) => r.numEtud === 21212006); * * // Supprimer * db.deleteWhere("students", (r) => r.numEtud === 21212006); * ``` */ export function createMockDb(config: MockDbConfig) { // Deep clone pour éviter les mutations entre tests // deno-lint-ignore no-explicit-any const tables: Record[]> = {}; for (const [name, rows] of Object.entries(config.tables)) { tables[name] = rows.map((r) => ({ ...r })); } return { /** Retourne toutes les lignes d'une table */ getTable>(name: string): T[] { return (tables[name] ?? []) as T[]; }, /** Retourne les lignes qui matchent le filtre */ findMany>( name: string, predicate: (row: T) => boolean, ): T[] { return (this.getTable(name)).filter(predicate); }, /** Retourne la première ligne qui matche, ou undefined */ findOne>( name: string, predicate: (row: T) => boolean, ): T | undefined { return (this.getTable(name)).find(predicate); }, /** Insère une ligne dans la table */ insert>(name: string, row: T): T { if (!tables[name]) tables[name] = []; const copy = { ...row } as T; // deno-lint-ignore no-explicit-any tables[name].push(copy as any); return copy; }, /** Met à jour les lignes qui matchent le prédicat */ updateWhere>( name: string, predicate: (row: T) => boolean, updates: Partial, ): number { const rows = this.getTable(name); let count = 0; for (const row of rows) { if (predicate(row)) { Object.assign(row as Record, updates); count++; } } return count; }, /** Supprime les lignes qui matchent le prédicat */ deleteWhere>( name: string, predicate: (row: T) => boolean, ): number { const before = (tables[name] ?? []).length; tables[name] = (tables[name] ?? []).filter( (r) => !predicate(r as unknown as T), ); return before - tables[name].length; }, /** Vide une table */ clear(name: string): void { tables[name] = []; }, /** Vide toutes les tables */ reset(): void { for (const name of Object.keys(tables)) { tables[name] = []; } }, }; } export type MockDb = ReturnType;