143 lines
4.9 KiB
TypeScript
143 lines
4.9 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { createEvent, mockSuccessReadBody } from './setup'
|
|
import fsPromises from 'fs/promises'
|
|
import { promises as fs } from 'fs'
|
|
|
|
vi.mock('nodemailer', () => {
|
|
const sendMail = vi.fn().mockResolvedValue(true)
|
|
const createTransport = vi.fn(() => ({ sendMail }))
|
|
return {
|
|
default: { createTransport },
|
|
createTransport
|
|
}
|
|
})
|
|
|
|
vi.mock('../server/utils/news.js', () => ({
|
|
readNews: vi.fn()
|
|
}))
|
|
|
|
const nodemailer = await import('nodemailer')
|
|
const newsUtils = await import('../server/utils/news.js')
|
|
|
|
import contactHandler from '../server/api/contact.post.js'
|
|
import galerieHandler from '../server/api/galerie.get.js'
|
|
import newsPublicHandler from '../server/api/news-public.get.js'
|
|
import termineHandler from '../server/api/termine.get.js'
|
|
import spielplaeneHandler from '../server/api/spielplaene.get.js'
|
|
|
|
describe('Öffentliche API-Endpunkte', () => {
|
|
beforeEach(() => {
|
|
vi.restoreAllMocks()
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
describe('POST /api/contact', () => {
|
|
it('validiert Pflichtfelder', async () => {
|
|
const event = createEvent()
|
|
mockSuccessReadBody({})
|
|
|
|
await expect(contactHandler(event)).rejects.toMatchObject({ statusCode: 400 })
|
|
})
|
|
|
|
it('validiert E-Mail-Adresse', async () => {
|
|
const event = createEvent()
|
|
mockSuccessReadBody({ name: 'Max', email: 'invalid', subject: 'Hi', message: 'Test' })
|
|
|
|
await expect(contactHandler(event)).rejects.toMatchObject({ statusCode: 400 })
|
|
})
|
|
|
|
it('sendet E-Mail bei gültigen Daten', async () => {
|
|
const event = createEvent()
|
|
mockSuccessReadBody({ name: 'Max', email: 'max@example.com', subject: 'Frage', message: 'Hallo' })
|
|
|
|
const response = await contactHandler(event)
|
|
|
|
expect(response.success).toBe(true)
|
|
expect(nodemailer.default.createTransport).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
describe('GET /api/galerie', () => {
|
|
it('liefert leeres Array, wenn Verzeichnis fehlt', async () => {
|
|
vi.spyOn(fs, 'access').mockRejectedValue(new Error('not found'))
|
|
|
|
const result = await galerieHandler(createEvent())
|
|
expect(result).toEqual([])
|
|
})
|
|
|
|
it('filtert nur Bilddateien', async () => {
|
|
vi.spyOn(fs, 'access').mockResolvedValue(undefined)
|
|
vi.spyOn(fs, 'readdir').mockResolvedValue(['foto-1.jpg', 'readme.md'])
|
|
|
|
const result = await galerieHandler(createEvent())
|
|
expect(result).toHaveLength(1)
|
|
expect(result[0].filename).toBe('foto-1.jpg')
|
|
})
|
|
})
|
|
|
|
describe('GET /api/news-public', () => {
|
|
it('filtert nicht öffentliche News', async () => {
|
|
const now = new Date()
|
|
newsUtils.readNews.mockResolvedValue([
|
|
{ id: 1, isPublic: true, isHidden: false, created: now.toISOString(), title: 'ok' },
|
|
{ id: 2, isPublic: false, isHidden: false, created: now.toISOString() },
|
|
{ id: 3, isPublic: true, isHidden: true, created: now.toISOString() }
|
|
])
|
|
|
|
const response = await newsPublicHandler(createEvent())
|
|
expect(response.success).toBe(true)
|
|
expect(response.news).toHaveLength(1)
|
|
expect(response.news[0].id).toBe(1)
|
|
})
|
|
|
|
it('begrenzt Ergebnis auf drei Einträge', async () => {
|
|
const now = Date.now()
|
|
newsUtils.readNews.mockResolvedValue(
|
|
Array.from({ length: 5 }).map((_, index) => ({
|
|
id: index + 1,
|
|
isPublic: true,
|
|
isHidden: false,
|
|
created: new Date(now - index * 1000).toISOString()
|
|
}))
|
|
)
|
|
|
|
const response = await newsPublicHandler(createEvent())
|
|
expect(response.news).toHaveLength(3)
|
|
expect(response.news[0].id).toBe(1)
|
|
})
|
|
})
|
|
|
|
describe('GET /api/termine', () => {
|
|
it('parst CSV-Dateien', async () => {
|
|
const csv = 'Datum,Uhrzeit,Titel,Beschreibung,Kategorie\n2025-01-01,19:00,Training,Beschreibung,Sport'
|
|
vi.spyOn(fsPromises, 'readFile').mockResolvedValue(csv)
|
|
|
|
const response = await termineHandler(createEvent())
|
|
expect(response.success).toBe(true)
|
|
expect(response.termine[0]).toMatchObject({ titel: 'Training', kategorie: 'Sport' })
|
|
})
|
|
|
|
it('gibt leeres Array bei Fehlern zurück', async () => {
|
|
vi.spyOn(fsPromises, 'readFile').mockRejectedValue(new Error('kaputt'))
|
|
const response = await termineHandler(createEvent())
|
|
expect(response.termine).toEqual([])
|
|
})
|
|
})
|
|
|
|
describe('GET /api/spielplaene', () => {
|
|
it('filtert nur erlaubte Dateitypen', async () => {
|
|
vi.spyOn(fs, 'access').mockResolvedValue(undefined)
|
|
vi.spyOn(fs, 'readdir').mockResolvedValue(['plan.pdf', 'notizen.txt'])
|
|
|
|
const result = await spielplaeneHandler(createEvent())
|
|
expect(result).toEqual(['plan.pdf'])
|
|
})
|
|
|
|
it('gibt leeres Array zurück, wenn Verzeichnis fehlt', async () => {
|
|
vi.spyOn(fs, 'access').mockRejectedValue(new Error('not found'))
|
|
const result = await spielplaeneHandler(createEvent())
|
|
expect(result).toEqual([])
|
|
})
|
|
})
|
|
})
|