Files
harheimertc/tests/galerie-endpoints.spec.ts

164 lines
6.1 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createEvent, mockSuccessReadBody } from './setup'
import fs from 'fs/promises'
import sharp from 'sharp'
vi.mock('../server/utils/auth.js', () => ({
getUserFromToken: vi.fn(),
verifyToken: vi.fn(),
readUsers: vi.fn(),
writeUsers: vi.fn()
}))
vi.mock('sharp', () => ({
default: vi.fn(() => ({
resize: vi.fn().mockReturnThis(),
toFile: vi.fn().mockResolvedValue({})
}))
}))
vi.mock('multer', () => {
const single = vi.fn((field) => (req, _res, cb) => {
if (req.__mockMulterError) {
cb(req.__mockMulterError)
return
}
req.file = req.__mockFile || null
req.body = req.body || {}
cb(null)
})
const multerFn = vi.fn(() => ({ single }))
const diskStorage = vi.fn(() => ({}))
multerFn.diskStorage = diskStorage
return {
default: multerFn,
diskStorage
}
})
const authUtils = await import('../server/utils/auth.js')
import uploadHandler from '../server/api/galerie/upload.post.js'
import listHandler from '../server/api/galerie/list.get.js'
import imageHandler from '../server/api/galerie/[id].get.js'
describe('Galerie API Endpoints', () => {
beforeEach(() => {
vi.clearAllMocks()
vi.spyOn(fs, 'readFile').mockResolvedValue('[]')
vi.spyOn(fs, 'writeFile').mockResolvedValue(undefined)
vi.spyOn(fs, 'mkdir').mockResolvedValue(undefined)
vi.spyOn(fs, 'access').mockResolvedValue(undefined)
})
describe('POST /api/galerie/upload', () => {
it('erfordert Authentifizierung', async () => {
const event = createEvent({ method: 'POST' })
event.node.req.__mockFile = { filename: 'test.jpg', path: 'tmp/test.jpg', originalname: 'test.jpg', mimetype: 'image/jpeg' }
event.node.req.body = { title: 'Test', isPublic: 'true' }
await expect(uploadHandler(event)).rejects.toMatchObject({ statusCode: 401 })
})
it('erfordert Admin- oder Vorstand-Rolle', async () => {
const event = createEvent({ method: 'POST', cookies: { auth_token: 'token' } })
event.node.req.__mockFile = { filename: 'test.jpg', path: 'tmp/test.jpg', originalname: 'test.jpg', mimetype: 'image/jpeg' }
event.node.req.body = { title: 'Test', isPublic: 'true' }
authUtils.verifyToken.mockReturnValue({ id: '1' })
authUtils.getUserFromToken.mockResolvedValue({ id: '1', role: 'mitglied', active: true })
await expect(uploadHandler(event)).rejects.toMatchObject({ statusCode: 403 })
})
it('lädt Bild hoch und erstellt Thumbnail', async () => {
const event = createEvent({ method: 'POST', cookies: { auth_token: 'token' } })
event.node.req.__mockFile = { filename: 'test.jpg', path: 'tmp/test.jpg', originalname: 'test.jpg', mimetype: 'image/jpeg' }
event.node.req.body = { title: 'Test Bild', description: 'Beschreibung', isPublic: 'true' }
authUtils.verifyToken.mockReturnValue({ id: '1' })
authUtils.getUserFromToken.mockResolvedValue({ id: '1', role: 'admin', active: true })
const response = await uploadHandler(event)
expect(response.success).toBe(true)
expect(sharp).toHaveBeenCalled()
expect(fs.writeFile).toHaveBeenCalled()
})
})
describe('GET /api/galerie/list', () => {
it('zeigt öffentliche Bilder für alle', async () => {
const event = createEvent()
vi.spyOn(fs, 'readFile').mockResolvedValue(JSON.stringify([
{ id: '1', title: 'Öffentlich', isPublic: true, previewFilename: 'preview_1.jpg', uploadedAt: '2025-01-01' },
{ id: '2', title: 'Privat', isPublic: false, previewFilename: 'preview_2.jpg', uploadedAt: '2025-01-02' }
]))
const response = await listHandler(event)
expect(response.success).toBe(true)
expect(response.images).toHaveLength(1)
expect(response.images[0].id).toBe('1')
})
it('zeigt alle Bilder für eingeloggte Mitglieder', async () => {
const event = createEvent({ cookies: { auth_token: 'token' } })
vi.spyOn(fs, 'readFile').mockResolvedValue(JSON.stringify([
{ id: '1', title: 'Öffentlich', isPublic: true, previewFilename: 'preview_1.jpg', uploadedAt: '2025-01-01' },
{ id: '2', title: 'Privat', isPublic: false, previewFilename: 'preview_2.jpg', uploadedAt: '2025-01-02' }
]))
authUtils.verifyToken.mockReturnValue({ id: '1' })
authUtils.getUserFromToken.mockResolvedValue({ id: '1', active: true })
const response = await listHandler(event)
expect(response.images).toHaveLength(2)
})
})
describe('GET /api/galerie/[id]', () => {
it('verweigert Zugriff auf private Bilder für nicht eingeloggte Benutzer', async () => {
const event = createEvent()
event.context.params = { id: '1' }
vi.spyOn(fs, 'readFile')
.mockResolvedValueOnce(JSON.stringify([
{ id: '1', filename: 'test.jpg', previewFilename: 'preview_test.jpg', isPublic: false }
]))
await expect(imageHandler(event)).rejects.toMatchObject({ statusCode: 403 })
})
it('liefert Bild für eingeloggte Mitglieder', async () => {
const event = createEvent({ cookies: { auth_token: 'token' } })
event.context.params = { id: '1' }
vi.spyOn(fs, 'readFile')
.mockResolvedValueOnce(JSON.stringify([
{ id: '1', filename: 'test.jpg', previewFilename: 'preview_test.jpg', isPublic: false }
]))
.mockResolvedValueOnce(Buffer.from('image data'))
authUtils.verifyToken.mockReturnValue({ id: '1' })
authUtils.getUserFromToken.mockResolvedValue({ id: '1', active: true })
const response = await imageHandler(event)
expect(response).toBeInstanceOf(Buffer)
})
it('liefert Preview-Bild bei preview=true', async () => {
const event = createEvent({ query: { preview: 'true' } })
event.context.params = { id: '1' }
vi.spyOn(fs, 'readFile')
.mockResolvedValueOnce(JSON.stringify([
{ id: '1', filename: 'test.jpg', previewFilename: 'preview_test.jpg', isPublic: true }
]))
.mockResolvedValueOnce(Buffer.from('preview data'))
const response = await imageHandler(event)
expect(response).toBeInstanceOf(Buffer)
})
})
})