Files
harheimertc/tests/email-service.spec.ts
Torsten Schulz (local) 77aabef4a9
Some checks failed
Code Analysis and Production Deploy / analyze (push) Failing after 7m53s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Has been skipped
Benachrichtigungen erweitert
Emails korrigiert
2026-06-14 01:05:19 +02:00

117 lines
3.8 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import fs from 'fs/promises'
vi.mock('nodemailer', () => {
const sendMail = vi.fn().mockResolvedValue({ messageId: 'test-message' })
const createTransport = vi.fn(() => ({ sendMail }))
return {
default: { createTransport },
createTransport
}
})
vi.mock('../server/utils/auth.js', () => ({
readUsers: vi.fn(),
migrateUserRoles: vi.fn((user) => {
if (!user) return user
if (Array.isArray(user.roles)) return user
if (user.role) {
user.roles = [user.role]
delete user.role
} else {
user.roles = ['mitglied']
}
return user
}),
isHiddenUser: vi.fn(user => user?.hidden === true || user?.invisible === true || user?.isHidden === true || user?.systemAccount === true || user?.accountType === 'playstore_review')
}))
const nodemailer = await import('nodemailer')
const authUtils = await import('../server/utils/auth.js')
const emailService = await import('../server/utils/email-service.js')
describe('Email service recipients', () => {
beforeEach(() => {
vi.restoreAllMocks()
vi.clearAllMocks()
process.env.SMTP_USER = 'smtp@example.com'
process.env.SMTP_PASS = 'smtp-password'
authUtils.readUsers.mockResolvedValue([])
})
afterEach(() => {
delete process.env.SMTP_USER
delete process.env.SMTP_PASS
delete process.env.NODE_ENV
delete process.env.APP_ENV
delete process.env.DEBUG
})
it('sendet bei DEBUG=FALSE in production an Vorstand statt Entwickleradresse', async () => {
process.env.NODE_ENV = 'production'
process.env.APP_ENV = 'test'
process.env.DEBUG = 'FALSE'
vi.spyOn(fs, 'readFile').mockResolvedValue(JSON.stringify({
vorstand: {
vorsitzender: { email: 'vorstand@example.com' }
}
}))
await emailService.sendRegistrationNotification({
name: 'Max Muster',
email: 'max@example.com',
phone: '069123456'
})
const transporter = nodemailer.default.createTransport.mock.results[0].value
expect(transporter.sendMail).toHaveBeenCalledWith(expect.objectContaining({
to: 'vorstand@example.com'
}))
expect(transporter.sendMail.mock.calls[0][0].to).not.toContain('tsschulz@tsschulz.de')
})
it('bevorzugt aktive Vorstand-Benutzer vor config.json', async () => {
process.env.NODE_ENV = 'production'
process.env.DEBUG = 'FALSE'
authUtils.readUsers.mockResolvedValue([
{ id: '1', email: 'rolle-vorstand@example.com', roles: ['vorstand'], active: true },
{ id: '2', email: 'inaktiv@example.com', roles: ['vorstand'], active: false },
{ id: '3', email: 'mitglied@example.com', roles: ['mitglied'], active: true }
])
vi.spyOn(fs, 'readFile').mockResolvedValue(JSON.stringify({
vorstand: {
vorsitzender: { email: 'config-vorstand@example.com' }
}
}))
await emailService.sendRegistrationNotification({
name: 'Max Muster',
email: 'max@example.com'
})
const transporter = nodemailer.default.createTransport.mock.results[0].value
const to = transporter.sendMail.mock.calls[0][0].to
expect(to).toBe('rolle-vorstand@example.com')
expect(to).not.toContain('config-vorstand@example.com')
expect(to).not.toContain('inaktiv@example.com')
})
it('sendet nur bei explizitem DEBUG=true an die Entwickleradresse', async () => {
process.env.NODE_ENV = 'production'
process.env.DEBUG = 'true'
vi.spyOn(fs, 'readFile').mockResolvedValue(JSON.stringify({
vorstand: {
vorsitzender: { email: 'vorstand@example.com' }
}
}))
await emailService.sendRegistrationNotification({
name: 'Max Muster',
email: 'max@example.com'
})
const transporter = nodemailer.default.createTransport.mock.results[0].value
expect(transporter.sendMail.mock.calls[0][0].to).toBe('tsschulz@tsschulz.de')
})
})