Update dependencies in package.json and package-lock.json; add testing scripts for Vitest, and include new packages such as supertest and vitest. Refactor Navigation component to improve event handling and cleanup, ensuring better performance and user experience. Enhance error handling in various API endpoints for PDF uploads and CSV saves, ensuring robust error propagation. Update nodemailer transport configuration for consistency across API handlers.

This commit is contained in:
Torsten Schulz (local)
2025-11-10 13:08:50 +01:00
parent 95d7a3dfe8
commit bde1d32b14
15 changed files with 2055 additions and 15 deletions

View File

@@ -0,0 +1,138 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createEvent, mockSuccessReadBody } from './setup'
vi.mock('../server/utils/auth.js', () => ({
getUserFromToken: vi.fn(),
readUsers: vi.fn(),
writeUsers: vi.fn()
}))
vi.mock('nodemailer', () => {
const sendMail = vi.fn().mockResolvedValue(true)
const createTransport = vi.fn(() => ({ sendMail }))
return {
default: { createTransport },
createTransport
}
})
const authUtils = await import('../server/utils/auth.js')
const nodemailer = await import('nodemailer')
import usersListHandler from '../server/api/cms/users/list.get.js'
import usersApproveHandler from '../server/api/cms/users/approve.post.js'
import usersDeactivateHandler from '../server/api/cms/users/deactivate.post.js'
import usersRejectHandler from '../server/api/cms/users/reject.post.js'
import usersUpdateRoleHandler from '../server/api/cms/users/update-role.post.js'
describe('CMS User Management Endpoints', () => {
beforeEach(() => {
vi.clearAllMocks()
})
const adminEvent = () => {
const event = createEvent({ cookies: { auth_token: 'token' } })
authUtils.getUserFromToken.mockResolvedValue({ id: 'admin', role: 'admin' })
return event
}
describe('GET /api/cms/users/list', () => {
it('verweigert Zugriff für Nicht-Admins', async () => {
const event = createEvent({ cookies: { auth_token: 'token' } })
authUtils.getUserFromToken.mockResolvedValue({ id: 'user', role: 'mitglied' })
await expect(usersListHandler(event)).rejects.toMatchObject({ statusCode: 403 })
})
it('liefert Benutzerliste ohne Passwörter', async () => {
const event = adminEvent()
authUtils.readUsers.mockResolvedValue([{ id: '1', email: 'a@b.de', name: 'Anna', role: 'mitglied', phone: '1', active: true, created: 'now', lastLogin: null, password: 'secret' }])
const response = await usersListHandler(event)
expect(response.users[0]).not.toHaveProperty('password')
expect(response.users).toHaveLength(1)
})
})
describe('POST /api/cms/users/approve', () => {
it('erfordert administrative Rolle', async () => {
const event = createEvent({ cookies: { auth_token: 'token' } })
authUtils.getUserFromToken.mockResolvedValue({ id: 'user', role: 'mitglied' })
mockSuccessReadBody({ userId: '1' })
await expect(usersApproveHandler(event)).rejects.toMatchObject({ statusCode: 403 })
})
it('meldet 404 bei unbekanntem Benutzer', async () => {
const event = adminEvent()
mockSuccessReadBody({ userId: '1' })
authUtils.readUsers.mockResolvedValue([])
await expect(usersApproveHandler(event)).rejects.toMatchObject({ statusCode: 404 })
})
it('aktiviert Benutzer und sendet Mail', async () => {
const event = adminEvent()
mockSuccessReadBody({ userId: '1', role: 'vorstand' })
authUtils.readUsers.mockResolvedValue([{ id: '1', email: 'user@test.de', name: 'Udo', active: false }])
authUtils.writeUsers.mockResolvedValue(true)
const response = await usersApproveHandler(event)
expect(response.success).toBe(true)
expect(authUtils.writeUsers).toHaveBeenCalled()
expect(nodemailer.default.createTransport).toHaveBeenCalled()
})
})
describe('POST /api/cms/users/deactivate', () => {
it('verhindert Selbst-Deaktivierung', async () => {
const event = adminEvent()
mockSuccessReadBody({ userId: 'admin' })
await expect(usersDeactivateHandler(event)).rejects.toMatchObject({ statusCode: 400 })
})
it('deaktiviert Benutzer', async () => {
const event = adminEvent()
mockSuccessReadBody({ userId: '1' })
authUtils.readUsers.mockResolvedValue([{ id: '1', active: true }])
authUtils.writeUsers.mockResolvedValue(true)
const response = await usersDeactivateHandler(event)
expect(response.success).toBe(true)
expect(authUtils.writeUsers).toHaveBeenCalled()
})
})
describe('POST /api/cms/users/reject', () => {
it('löscht Benutzer aus der Liste', async () => {
const event = adminEvent()
mockSuccessReadBody({ userId: '2' })
authUtils.readUsers.mockResolvedValue([{ id: '1' }, { id: '2' }])
authUtils.writeUsers.mockResolvedValue(true)
const response = await usersRejectHandler(event)
expect(response.success).toBe(true)
expect(authUtils.writeUsers).toHaveBeenCalledWith([{ id: '1' }])
})
})
describe('POST /api/cms/users/update-role', () => {
it('validiert Rolle', async () => {
const event = adminEvent()
mockSuccessReadBody({ userId: '1', role: 'invalid' })
await expect(usersUpdateRoleHandler(event)).rejects.toMatchObject({ statusCode: 400 })
})
it('aktualisiert Rolle', async () => {
const event = adminEvent()
mockSuccessReadBody({ userId: '1', role: 'vorstand' })
authUtils.readUsers.mockResolvedValue([{ id: '1', role: 'mitglied' }])
authUtils.writeUsers.mockResolvedValue(true)
const response = await usersUpdateRoleHandler(event)
expect(response.success).toBe(true)
expect(authUtils.writeUsers).toHaveBeenCalled()
})
})
})