import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { getDb } from '../db'; import { validerPresenceFormateur, getPresencesFormateurBySequence } from '../presenceDb'; import { formateurs, sequences, datesFormation, presences } from '../../drizzle/schema'; import { eq, and, sql } from 'drizzle-orm'; describe('Émargement formateur par QR code', () => { let testFormateurId: number; let testSequenceId: number; let testDateFormationId: number; const timestamp = Date.now(); beforeAll(async () => { const db = await getDb(); if (!db) throw new Error('Database not available'); // Créer un formateur de test const formateurResult = await db.insert(formateurs).values({ nom: `Test Formateur Émargement ${timestamp}`, email: `test.formateur.emargement.${timestamp}@test.com`, }); testFormateurId = Number(formateurResult[0].insertId); // Créer une séquence de test const sequenceResult = await db.insert(sequences).values({ formationId: 1, nom: 'Test Séquence Émargement', lieu: 'Test Lieu', capaciteMax: 10, statut: 'ouverte', publicCible: 'tous', formateurId: testFormateurId, }); testSequenceId = Number(sequenceResult[0].insertId); // Créer une date de formation de test const dateResult = await db.insert(datesFormation).values({ sequenceId: testSequenceId, ordre: 1, dateDebut: new Date(), dateFin: new Date(Date.now() + 3600000), }); testDateFormationId = Number(dateResult[0].insertId); }); afterAll(async () => { const db = await getDb(); if (!db) return; // Nettoyer les données de test await db.delete(presences).where(eq(presences.formateurId, testFormateurId)); await db.delete(datesFormation).where(eq(datesFormation.sequenceId, testSequenceId)); await db.delete(sequences).where(eq(sequences.id, testSequenceId)); await db.delete(formateurs).where(eq(formateurs.id, testFormateurId)); }); it('devrait valider la présence du formateur pour le matin', async () => { const result = await validerPresenceFormateur({ formateurId: testFormateurId, sequenceId: testSequenceId, dateFormationId: testDateFormationId, periode: 'matin', modeValidation: 'qrcode', }); expect(result.success).toBe(true); // Vérifier que la présence a bien été créée const db = await getDb(); if (!db) throw new Error('Database not available'); const presenceCreated = await db .select() .from(presences) .where( and( eq(presences.formateurId, testFormateurId), eq(presences.dateFormationId, testDateFormationId), sql`${presences}.periode = 'matin'`, sql`${presences}.typeUtilisateur = 'formateur'` ) ); expect(presenceCreated.length).toBe(1); expect(presenceCreated[0].typeUtilisateur).toBe('formateur'); expect(presenceCreated[0].modeValidation).toBe('qrcode'); }); it('devrait valider la présence du formateur pour l\'après-midi', async () => { const result = await validerPresenceFormateur({ formateurId: testFormateurId, sequenceId: testSequenceId, dateFormationId: testDateFormationId, periode: 'apres_midi', modeValidation: 'qrcode', }); expect(result.success).toBe(true); }); it('devrait empêcher la double validation pour la même période', async () => { await expect( validerPresenceFormateur({ formateurId: testFormateurId, sequenceId: testSequenceId, dateFormationId: testDateFormationId, periode: 'matin', modeValidation: 'qrcode', }) ).rejects.toThrow('Présence déjà validée'); }); it('devrait récupérer les présences du formateur pour une séquence', async () => { const presencesFormateur = await getPresencesFormateurBySequence(testSequenceId); expect(presencesFormateur.length).toBeGreaterThanOrEqual(2); // Matin + Après-midi expect(presencesFormateur.every(p => p.formateurId === testFormateurId)).toBe(true); }); it('devrait stocker la signature tactile du formateur', async () => { const db = await getDb(); if (!db) throw new Error('Database not available'); // Créer une nouvelle date pour ce test const dateResult = await db.insert(datesFormation).values({ sequenceId: testSequenceId, ordre: 2, dateDebut: new Date(), dateFin: new Date(Date.now() + 3600000), }); const newDateId = Number(dateResult[0].insertId); const signatureUrl = '/uploads/signatures/test-formateur-signature.png'; const result = await validerPresenceFormateur({ formateurId: testFormateurId, sequenceId: testSequenceId, dateFormationId: newDateId, periode: 'matin', modeValidation: 'qrcode', signatureUrl, signatureS3Key: 'signatures/test-formateur-signature.png', }); expect(result.success).toBe(true); // Vérifier que la signature a été stockée const presenceCreated = await db .select() .from(presences) .where( and( eq(presences.formateurId, testFormateurId), eq(presences.dateFormationId, newDateId), sql`${presences}.periode = 'matin'` ) ); expect(presenceCreated.length).toBe(1); expect(presenceCreated[0].signatureUrl).toBe(signatureUrl); // Nettoyer await db.delete(datesFormation).where(eq(datesFormation.id, newDateId)); }); });