/** * TEST UNITARI PER LA CLASSE InvioNotifiche * * Framework: Jest * Installazione: npm install --save-dev jest * Esecuzione: npm test */ const InvioNotifiche = require('./InvioNotifiche'); // Mock dei servizi esterni const mockEmailService = { sendMail: jest.fn().mockResolvedValue({ messageId: 'mock-email-id' }) }; const mockTelegramBot = { sendMessage: jest.fn().mockResolvedValue({ message_id: 123 }) }; const mockLogger = { info: jest.fn(), warn: jest.fn(), error: jest.fn() }; describe('InvioNotifiche', () => { let notifiche; beforeEach(() => { // Reset dei mock prima di ogni test jest.clearAllMocks(); // Inizializza classe con mock notifiche = new InvioNotifiche({ emailService: mockEmailService, telegramBot: mockTelegramBot, adminTelegramId: '999999999', adminEmail: 'paolo@riso.app', baseUrl: 'https://riso.app', nomeApp: 'RISO', emailTemplates: { verificaEmail: './templates/verifica.pug', richiestaAmmissione: './templates/ammissione.pug', benvenuto: './templates/benvenuto.pug', profiloCompletato: './templates/profilo.pug' }, logger: mockLogger }); // Mock del metodo _getInvitante notifiche._getInvitante = jest.fn().mockResolvedValue({ id: 5, username: 'invitante', email: 'invitante@example.com', name: 'Marco Invitante', teleg_id: 111111111 }); }); // ============================================ // TEST: notificaRegistrazione // ============================================ describe('notificaRegistrazione', () => { test('Invia email di verifica quando verified_email = false', async () => { const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', name: 'Mario Rossi', verified_email: false, invitante_id: 5 }; const result = await notifiche.notificaRegistrazione(utente, 'token123'); // Verifica che l'email sia stata inviata expect(mockEmailService.sendMail).toHaveBeenCalledTimes(2); // utente + admin expect(result.emailVerificaInviata).toBe(true); expect(result.success).toBe(true); // Verifica logging expect(mockLogger.info).toHaveBeenCalledWith( expect.stringContaining('Notifica registrazione') ); }); test('Salta verifica email quando verified_email = true', async () => { const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', name: 'Mario Rossi', verified_email: true, invitante_id: 5 }; const result = await notifiche.notificaRegistrazione(utente, null); // Verifica che NON sia stata inviata email di verifica expect(result.emailVerificaInviata).toBe(false); expect(result.success).toBe(true); // Verifica che sia stata chiamata notificaRichiestaAmmissione expect(notifiche._getInvitante).toHaveBeenCalledWith(5); }); test('Gestisce errori correttamente', async () => { mockEmailService.sendMail.mockRejectedValueOnce(new Error('SMTP Error')); const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', verified_email: false, invitante_id: 5 }; await expect( notifiche.notificaRegistrazione(utente, 'token123') ).rejects.toThrow(); expect(mockLogger.error).toHaveBeenCalled(); }); }); // ============================================ // TEST: notificaRichiestaAmmissione // ============================================ describe('notificaRichiestaAmmissione', () => { test('Invia notifica email e telegram all\'invitante', async () => { const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', name: 'Mario Rossi', invitante_id: 5, created_at: new Date() }; const result = await notifiche.notificaRichiestaAmmissione(utente); // Verifica chiamate expect(notifiche._getInvitante).toHaveBeenCalledWith(5); expect(mockEmailService.sendMail).toHaveBeenCalled(); expect(mockTelegramBot.sendMessage).toHaveBeenCalled(); expect(result.success).toBe(true); }); test('Gestisce invitante non trovato', async () => { notifiche._getInvitante.mockResolvedValueOnce(null); const utente = { id: 1, username: 'mario.rossi', invitante_id: 999 }; await expect( notifiche.notificaRichiestaAmmissione(utente) ).rejects.toThrow('Invitante non trovato'); }); test('Invia notifica anche se Telegram fallisce', async () => { mockTelegramBot.sendMessage.mockRejectedValueOnce(new Error('Telegram Error')); const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', invitante_id: 5, created_at: new Date() }; const result = await notifiche.notificaRichiestaAmmissione(utente); // Email dovrebbe essere comunque inviata expect(mockEmailService.sendMail).toHaveBeenCalled(); expect(mockLogger.error).toHaveBeenCalledWith( expect.stringContaining('Errore invio Telegram'), expect.any(Error) ); }); }); // ============================================ // TEST: notificaUtenteAmmesso // ============================================ describe('notificaUtenteAmmesso', () => { test('Invia email di benvenuto all\'utente', async () => { const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', name: 'Mario Rossi', teleg_id: 0 }; const result = await notifiche.notificaUtenteAmmesso(utente); expect(mockEmailService.sendMail).toHaveBeenCalled(); expect(result.success).toBe(true); // Verifica oggetto email const emailCall = mockEmailService.sendMail.mock.calls[0][0]; expect(emailCall.subject).toContain('Benvenuto'); }); test('Invia anche Telegram se utente ha teleg_id', async () => { const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', name: 'Mario Rossi', teleg_id: 123456789 }; await notifiche.notificaUtenteAmmesso(utente); expect(mockTelegramBot.sendMessage).toHaveBeenCalledWith( 123456789, expect.stringContaining('Benvenuto'), expect.any(Object) ); }); test('Salta Telegram se teleg_id = 0', async () => { const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', teleg_id: 0 }; await notifiche.notificaUtenteAmmesso(utente); // Solo email, no Telegram expect(mockTelegramBot.sendMessage).not.toHaveBeenCalled(); }); }); // ============================================ // TEST: notificaProfiloCompletato // ============================================ describe('notificaProfiloCompletato', () => { test('Invia notifica se Telegram รจ verificato', async () => { const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', name: 'Mario Rossi', teleg_id: 123456789, invitante_id: 5 }; const result = await notifiche.notificaProfiloCompletato(utente); expect(notifiche._getInvitante).toHaveBeenCalledWith(5); expect(mockEmailService.sendMail).toHaveBeenCalled(); expect(mockTelegramBot.sendMessage).toHaveBeenCalled(); expect(result.success).toBe(true); }); test('Non invia se Telegram non verificato', async () => { const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', teleg_id: 0, invitante_id: 5 }; const result = await notifiche.notificaProfiloCompletato(utente); expect(result.success).toBe(false); expect(result.message).toContain('Telegram non ancora verificato'); expect(mockEmailService.sendMail).not.toHaveBeenCalled(); }); }); // ============================================ // TEST: gestisciEvento // ============================================ describe('gestisciEvento', () => { test('Gestisce evento REGISTRAZIONE', async () => { const spy = jest.spyOn(notifiche, 'notificaRegistrazione'); await notifiche.gestisciEvento('REGISTRAZIONE', { utente: { username: 'test' }, tokenVerifica: 'token123' }); expect(spy).toHaveBeenCalled(); }); test('Gestisce evento EMAIL_VERIFICATA', async () => { const spy = jest.spyOn(notifiche, 'notificaRichiestaAmmissione'); await notifiche.gestisciEvento('EMAIL_VERIFICATA', { utente: { username: 'test', invitante_id: 5 } }); expect(spy).toHaveBeenCalled(); }); test('Gestisce evento UTENTE_AMMESSO', async () => { const spy = jest.spyOn(notifiche, 'notificaUtenteAmmesso'); await notifiche.gestisciEvento('UTENTE_AMMESSO', { utente: { username: 'test' } }); expect(spy).toHaveBeenCalled(); }); test('Gestisce evento PROFILO_COMPLETATO solo se Telegram verificato', async () => { const spy = jest.spyOn(notifiche, 'notificaProfiloCompletato'); // Con Telegram verificato await notifiche.gestisciEvento('PROFILO_COMPLETATO', { utente: { username: 'test', teleg_id: 123, invitante_id: 5 } }); expect(spy).toHaveBeenCalled(); spy.mockClear(); // Senza Telegram const result = await notifiche.gestisciEvento('PROFILO_COMPLETATO', { utente: { username: 'test', teleg_id: 0 } }); expect(spy).not.toHaveBeenCalled(); expect(result.success).toBe(false); }); test('Lancia errore per evento non riconosciuto', async () => { await expect( notifiche.gestisciEvento('EVENTO_INESISTENTE', {}) ).rejects.toThrow('Evento non riconosciuto'); }); }); // ============================================ // TEST: isProfiloCompleto // ============================================ describe('isProfiloCompleto', () => { test('Ritorna true se profilo completo', () => { const utente = { name: 'Mario Rossi', email: 'mario@example.com', teleg_id: 123456789 }; expect(notifiche.isProfiloCompleto(utente)).toBe(true); }); test('Ritorna false se manca name', () => { const utente = { email: 'mario@example.com', teleg_id: 123456789 }; expect(notifiche.isProfiloCompleto(utente)).toBe(false); }); test('Ritorna false se manca email', () => { const utente = { name: 'Mario Rossi', teleg_id: 123456789 }; expect(notifiche.isProfiloCompleto(utente)).toBe(false); }); test('Ritorna false se Telegram non verificato', () => { const utente = { name: 'Mario Rossi', email: 'mario@example.com', teleg_id: 0 }; expect(notifiche.isProfiloCompleto(utente)).toBe(false); }); }); // ============================================ // TEST: Metodi Privati // ============================================ describe('Metodi privati', () => { test('_inviaEmail invia email correttamente', async () => { const result = await notifiche._inviaEmail( 'test@example.com', 'Test Subject', '
Test HTML
' ); expect(result.success).toBe(true); expect(mockEmailService.sendMail).toHaveBeenCalledWith( expect.objectContaining({ to: 'test@example.com', subject: 'Test Subject', html: 'Test HTML
' }) ); }); test('_inviaTelegram invia messaggio correttamente', async () => { const result = await notifiche._inviaTelegram( 123456789, 'Test message' ); expect(result.success).toBe(true); expect(mockTelegramBot.sendMessage).toHaveBeenCalledWith( 123456789, 'Test message', expect.any(Object) ); }); test('_inviaTelegram gestisce ID non valido', async () => { const result = await notifiche._inviaTelegram(0, 'Test'); expect(result.success).toBe(false); expect(result.error).toContain('non valido'); expect(mockLogger.warn).toHaveBeenCalled(); }); test('_inviaCopiaCopiaAdmin invia a email e telegram admin', async () => { await notifiche._inviaCopiaCopiaAdmin('Test', 'Message'); expect(mockEmailService.sendMail).toHaveBeenCalledWith( expect.objectContaining({ to: 'admin@riso.app', subject: '[ADMIN] Test' }) ); expect(mockTelegramBot.sendMessage).toHaveBeenCalledWith( '999999999', expect.stringContaining('NOTIFICA ADMIN'), expect.any(Object) ); }); }); }); // ============================================ // TEST: Integrazione // ============================================ describe('Test di Integrazione', () => { let notifiche; beforeEach(() => { notifiche = new InvioNotifiche({ emailService: mockEmailService, telegramBot: mockTelegramBot, adminTelegramId: '999999999', adminEmail: 'admin@riso.app', baseUrl: 'https://riso.app', nomeApp: 'RISO', emailTemplates: {}, logger: mockLogger }); notifiche._getInvitante = jest.fn().mockResolvedValue({ id: 5, username: 'invitante', email: 'invitante@example.com', teleg_id: 111111111 }); }); test('Flusso completo: Registrazione โ Verifica โ Ammissione โ Profilo', async () => { const utente = { id: 1, username: 'mario.rossi', email: 'mario@example.com', name: 'Mario Rossi', verified_email: false, invitante_id: 5, teleg_id: 0, created_at: new Date() }; // 1. Registrazione await notifiche.notificaRegistrazione(utente, 'token123'); expect(mockEmailService.sendMail).toHaveBeenCalled(); // 2. Verifica email utente.verified_email = true; await notifiche.notificaRichiestaAmmissione(utente); expect(notifiche._getInvitante).toHaveBeenCalled(); // 3. Ammissione await notifiche.notificaUtenteAmmesso(utente); expect(mockEmailService.sendMail).toHaveBeenCalled(); // 4. Profilo completato utente.teleg_id = 123456789; await notifiche.notificaProfiloCompletato(utente); expect(mockTelegramBot.sendMessage).toHaveBeenCalled(); // Verifica che tutte le notifiche admin siano state inviate const adminCalls = mockEmailService.sendMail.mock.calls.filter( call => call[0].subject.includes('[ADMIN]') ); expect(adminCalls.length).toBeGreaterThan(0); }); }); // Configurazione package.json per Jest /* { "scripts": { "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage" }, "jest": { "testEnvironment": "node", "coveragePathIgnorePatterns": ["/node_modules/"], "testMatch": ["**/__tests__/**/*.js", "**/?(*.)+(spec|test).js"] } } */