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:
168
tests/auth-endpoints.spec.ts
Normal file
168
tests/auth-endpoints.spec.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { createEvent, mockSuccessReadBody } from './setup'
|
||||
|
||||
vi.mock('../server/utils/auth.js', () => {
|
||||
return {
|
||||
readUsers: vi.fn(),
|
||||
writeUsers: vi.fn(),
|
||||
verifyPassword: vi.fn(),
|
||||
generateToken: vi.fn(),
|
||||
createSession: vi.fn(),
|
||||
hashPassword: vi.fn(),
|
||||
verifyToken: vi.fn(),
|
||||
deleteSession: vi.fn(),
|
||||
getUserFromToken: vi.fn(),
|
||||
readSessions: vi.fn(),
|
||||
writeSessions: 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 loginHandler from '../server/api/auth/login.post.js'
|
||||
import logoutHandler from '../server/api/auth/logout.post.js'
|
||||
import registerHandler from '../server/api/auth/register.post.js'
|
||||
import resetPasswordHandler from '../server/api/auth/reset-password.post.js'
|
||||
import statusHandler from '../server/api/auth/status.get.js'
|
||||
|
||||
describe('Auth API Endpoints', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('POST /api/auth/login', () => {
|
||||
it('wirft 400 bei fehlenden Feldern', async () => {
|
||||
const event = createEvent()
|
||||
mockSuccessReadBody({})
|
||||
|
||||
await expect(loginHandler(event)).rejects.toMatchObject({ statusCode: 400 })
|
||||
})
|
||||
|
||||
it('wirft 401 bei unbekanntem Benutzer', async () => {
|
||||
const event = createEvent()
|
||||
mockSuccessReadBody({ email: 'test@example.com', password: 'password' })
|
||||
authUtils.readUsers.mockResolvedValue([])
|
||||
|
||||
await expect(loginHandler(event)).rejects.toMatchObject({ statusCode: 401 })
|
||||
})
|
||||
|
||||
it('gibt Token und Cookie bei Erfolg zurück', async () => {
|
||||
const event = createEvent()
|
||||
const user = { id: '1', email: 'test@example.com', password: 'hash', role: 'mitglied', active: true, lastLogin: null }
|
||||
mockSuccessReadBody({ email: user.email, password: 'plain' })
|
||||
authUtils.readUsers.mockResolvedValue([user])
|
||||
authUtils.verifyPassword.mockResolvedValue(true)
|
||||
authUtils.generateToken.mockReturnValue('jwt-token')
|
||||
authUtils.createSession.mockResolvedValue({})
|
||||
authUtils.writeUsers.mockResolvedValue(true)
|
||||
|
||||
const response = await loginHandler(event)
|
||||
|
||||
expect(response.success).toBe(true)
|
||||
expect(response.token).toBe('jwt-token')
|
||||
expect(response.user).toMatchObject({ id: '1', email: user.email })
|
||||
expect(authUtils.createSession).toHaveBeenCalledWith('1', 'jwt-token')
|
||||
expect(authUtils.writeUsers).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('POST /api/auth/logout', () => {
|
||||
it('löscht Session und Cookie, wenn Token vorhanden ist', async () => {
|
||||
const event = createEvent({ cookies: { auth_token: 'token' } })
|
||||
authUtils.deleteSession.mockResolvedValue()
|
||||
|
||||
const response = await logoutHandler(event)
|
||||
|
||||
expect(response.success).toBe(true)
|
||||
expect(authUtils.deleteSession).toHaveBeenCalledWith('token')
|
||||
})
|
||||
|
||||
it('wirft 500 bei Fehlern', async () => {
|
||||
const event = createEvent({ cookies: { auth_token: 'token' } })
|
||||
authUtils.deleteSession.mockRejectedValue(new Error('boom'))
|
||||
|
||||
await expect(logoutHandler(event)).rejects.toMatchObject({ statusCode: 500 })
|
||||
})
|
||||
})
|
||||
|
||||
describe('POST /api/auth/register', () => {
|
||||
it('prüft Pflichtfelder', async () => {
|
||||
const event = createEvent()
|
||||
mockSuccessReadBody({})
|
||||
|
||||
await expect(registerHandler(event)).rejects.toMatchObject({ statusCode: 400 })
|
||||
})
|
||||
|
||||
it('verhindert doppelte Benutzer', async () => {
|
||||
const event = createEvent()
|
||||
mockSuccessReadBody({ name: 'Max', email: 'max@example.com', password: '12345678' })
|
||||
authUtils.readUsers.mockResolvedValue([{ email: 'max@example.com' }])
|
||||
|
||||
await expect(registerHandler(event)).rejects.toMatchObject({ statusCode: 409 })
|
||||
})
|
||||
|
||||
it('legt Benutzer an und versendet E-Mails', async () => {
|
||||
const event = createEvent()
|
||||
mockSuccessReadBody({ name: 'Max', email: 'max@example.com', password: '12345678', phone: '123' })
|
||||
authUtils.readUsers.mockResolvedValue([])
|
||||
authUtils.hashPassword.mockResolvedValue('hashed')
|
||||
authUtils.writeUsers.mockResolvedValue(true)
|
||||
|
||||
const response = await registerHandler(event)
|
||||
|
||||
expect(response.success).toBe(true)
|
||||
expect(authUtils.writeUsers).toHaveBeenCalled()
|
||||
expect(nodemailer.default.createTransport).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('POST /api/auth/reset-password', () => {
|
||||
it('prüft Pflichtfelder', async () => {
|
||||
const event = createEvent()
|
||||
mockSuccessReadBody({})
|
||||
|
||||
const response = await resetPasswordHandler(event)
|
||||
expect(response.success).toBe(true)
|
||||
})
|
||||
|
||||
it('aktualisiert Passwort bei vorhandenem Benutzer', async () => {
|
||||
const event = createEvent()
|
||||
const user = { id: '1', email: 'user@example.com', name: 'User', password: 'hash' }
|
||||
mockSuccessReadBody({ email: user.email })
|
||||
authUtils.readUsers.mockResolvedValue([user])
|
||||
authUtils.hashPassword.mockResolvedValue('new-hash')
|
||||
authUtils.writeUsers.mockResolvedValue(true)
|
||||
|
||||
const response = await resetPasswordHandler(event)
|
||||
expect(response.success).toBe(true)
|
||||
expect(authUtils.writeUsers).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('GET /api/auth/status', () => {
|
||||
it('liefert loggedOut, wenn kein Cookie gesetzt ist', async () => {
|
||||
const event = createEvent()
|
||||
const response = await statusHandler(event)
|
||||
expect(response.isLoggedIn).toBe(false)
|
||||
})
|
||||
|
||||
it('liefert Benutzerinformationen bei gültigem Token', async () => {
|
||||
const event = createEvent({ cookies: { auth_token: 'token' } })
|
||||
authUtils.getUserFromToken.mockResolvedValue({ id: '1', email: 'user@example.com', name: 'User', role: 'mitglied' })
|
||||
|
||||
const response = await statusHandler(event)
|
||||
expect(response.isLoggedIn).toBe(true)
|
||||
expect(response.user).toMatchObject({ id: '1' })
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user