150 lines
5.6 KiB
TypeScript
150 lines
5.6 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||
import { createEvent, mockSuccessReadBody } from './setup'
|
||
|
||
vi.mock('../server/utils/auth.js', () => ({
|
||
verifyToken: vi.fn(),
|
||
getUserById: vi.fn(),
|
||
hasAnyRole: vi.fn((user, ...roles) => {
|
||
if (!user) return false
|
||
const userRoles = Array.isArray(user.roles) ? user.roles : (user.role ? [user.role] : [])
|
||
return roles.some(r => userRoles.includes(r))
|
||
})
|
||
}))
|
||
|
||
vi.mock('../server/utils/termine.js', () => ({
|
||
readTermine: vi.fn(),
|
||
saveTermin: vi.fn(),
|
||
deleteTermin: vi.fn()
|
||
}))
|
||
|
||
const authUtils = await import('../server/utils/auth.js')
|
||
const termineUtils = await import('../server/utils/termine.js')
|
||
|
||
import termineGetHandler from '../server/api/termine-manage.get.js'
|
||
import terminePostHandler from '../server/api/termine-manage.post.js'
|
||
import termineDeleteHandler from '../server/api/termine-manage.delete.js'
|
||
|
||
describe('Termine-Manage API Endpoints', () => {
|
||
beforeEach(() => {
|
||
vi.clearAllMocks()
|
||
})
|
||
|
||
const adminEvent = () => {
|
||
const event = createEvent({ cookies: { auth_token: 'token' } })
|
||
authUtils.verifyToken.mockReturnValue({ id: '1' })
|
||
authUtils.getUserById.mockResolvedValue({ id: '1', roles: ['admin'] })
|
||
authUtils.hasAnyRole.mockReturnValue(true)
|
||
return event
|
||
}
|
||
|
||
describe('GET /api/termine-manage', () => {
|
||
it('verlangt Authentifizierung', async () => {
|
||
const event = createEvent()
|
||
await expect(termineGetHandler(event)).rejects.toMatchObject({ statusCode: 401 })
|
||
})
|
||
|
||
it('lehnt ungültiges Token ab', async () => {
|
||
const event = createEvent({ cookies: { auth_token: 'bad' } })
|
||
authUtils.verifyToken.mockReturnValue(null)
|
||
await expect(termineGetHandler(event)).rejects.toMatchObject({ statusCode: 401 })
|
||
})
|
||
|
||
it('verlangt Admin- oder Vorstand-Rolle', async () => {
|
||
const event = createEvent({ cookies: { auth_token: 'token' } })
|
||
authUtils.verifyToken.mockReturnValue({ id: '1' })
|
||
authUtils.getUserById.mockResolvedValue({ id: '1', roles: ['mitglied'] })
|
||
authUtils.hasAnyRole.mockReturnValue(false)
|
||
await expect(termineGetHandler(event)).rejects.toMatchObject({ statusCode: 403 })
|
||
})
|
||
|
||
it('liefert Terminliste', async () => {
|
||
const event = adminEvent()
|
||
termineUtils.readTermine.mockResolvedValue([
|
||
{ datum: '2025-06-01', titel: 'Hauptversammlung', kategorie: 'Verein' }
|
||
])
|
||
|
||
const result = await termineGetHandler(event)
|
||
|
||
expect(result.success).toBe(true)
|
||
expect(result.termine).toHaveLength(1)
|
||
expect(result.termine[0].titel).toBe('Hauptversammlung')
|
||
})
|
||
})
|
||
|
||
describe('POST /api/termine-manage', () => {
|
||
it('verlangt Authentifizierung', async () => {
|
||
const event = createEvent()
|
||
mockSuccessReadBody({})
|
||
await expect(terminePostHandler(event)).rejects.toMatchObject({ statusCode: 401 })
|
||
})
|
||
|
||
it('verlangt Admin- oder Vorstand-Rolle', async () => {
|
||
const event = createEvent({ cookies: { auth_token: 'token' } })
|
||
authUtils.verifyToken.mockReturnValue({ id: '1' })
|
||
authUtils.getUserById.mockResolvedValue({ id: '1', roles: ['mitglied'] })
|
||
authUtils.hasAnyRole.mockReturnValue(false)
|
||
mockSuccessReadBody({ datum: '2025-06-01', titel: 'Test' })
|
||
await expect(terminePostHandler(event)).rejects.toMatchObject({ statusCode: 403 })
|
||
})
|
||
|
||
it('validiert Pflichtfelder – kein Titel', async () => {
|
||
const event = adminEvent()
|
||
mockSuccessReadBody({ datum: '2025-06-01' })
|
||
await expect(terminePostHandler(event)).rejects.toMatchObject({ statusCode: 400 })
|
||
})
|
||
|
||
it('validiert Pflichtfelder – kein Datum', async () => {
|
||
const event = adminEvent()
|
||
mockSuccessReadBody({ titel: 'Training' })
|
||
await expect(terminePostHandler(event)).rejects.toMatchObject({ statusCode: 400 })
|
||
})
|
||
|
||
it('speichert Termin erfolgreich', async () => {
|
||
const event = adminEvent()
|
||
termineUtils.saveTermin.mockResolvedValue(undefined)
|
||
mockSuccessReadBody({ datum: '2025-06-01', titel: 'Hauptversammlung', kategorie: 'Verein', uhrzeit: '19:00' })
|
||
|
||
const result = await terminePostHandler(event)
|
||
|
||
expect(result.success).toBe(true)
|
||
expect(termineUtils.saveTermin).toHaveBeenCalledWith(
|
||
expect.objectContaining({ datum: '2025-06-01', titel: 'Hauptversammlung' })
|
||
)
|
||
})
|
||
})
|
||
|
||
describe('DELETE /api/termine-manage', () => {
|
||
it('verlangt Authentifizierung', async () => {
|
||
const event = createEvent()
|
||
await expect(termineDeleteHandler(event)).rejects.toMatchObject({ statusCode: 401 })
|
||
})
|
||
|
||
it('verlangt Admin- oder Vorstand-Rolle', async () => {
|
||
const event = createEvent({ cookies: { auth_token: 'token' } })
|
||
authUtils.verifyToken.mockReturnValue({ id: '1' })
|
||
authUtils.getUserById.mockResolvedValue({ id: '1', roles: ['mitglied'] })
|
||
authUtils.hasAnyRole.mockReturnValue(false)
|
||
await expect(termineDeleteHandler(event)).rejects.toMatchObject({ statusCode: 403 })
|
||
})
|
||
|
||
it('validiert Pflichtfelder – datum und titel fehlen', async () => {
|
||
const event = adminEvent()
|
||
// __query ist leer → keine datum/titel
|
||
await expect(termineDeleteHandler(event)).rejects.toMatchObject({ statusCode: 400 })
|
||
})
|
||
|
||
it('löscht Termin erfolgreich', async () => {
|
||
const event = adminEvent()
|
||
event.__query = { datum: '2025-06-01', titel: 'Hauptversammlung', kategorie: 'Verein' }
|
||
termineUtils.deleteTermin.mockResolvedValue(undefined)
|
||
|
||
const result = await termineDeleteHandler(event)
|
||
|
||
expect(result.success).toBe(true)
|
||
expect(termineUtils.deleteTermin).toHaveBeenCalledWith(
|
||
expect.objectContaining({ datum: '2025-06-01', titel: 'Hauptversammlung' })
|
||
)
|
||
})
|
||
})
|
||
})
|