diff --git a/tests/auth-endpoints.spec.ts b/tests/auth-endpoints.spec.ts index 2286fd9..0af3857 100644 --- a/tests/auth-endpoints.spec.ts +++ b/tests/auth-endpoints.spec.ts @@ -63,6 +63,9 @@ import statusHandler from '../server/api/auth/status.get.js' describe('Auth API Endpoints', () => { beforeEach(() => { + // Setze SMTP-Credentials für Tests + process.env.SMTP_USER = 'test@example.com' + process.env.SMTP_PASS = 'test-password' vi.clearAllMocks() }) diff --git a/tests/cms-users-endpoints.spec.ts b/tests/cms-users-endpoints.spec.ts index 19a3145..fe7cbc5 100644 --- a/tests/cms-users-endpoints.spec.ts +++ b/tests/cms-users-endpoints.spec.ts @@ -9,6 +9,17 @@ vi.mock('../server/utils/auth.js', () => ({ if (!user) return false const userRoles = Array.isArray(user.roles) ? user.roles : (user.role ? [user.role] : []) return roles.some(r => userRoles.includes(r)) + }), + migrateUserRoles: vi.fn((user) => { + if (!user) return user + if (Array.isArray(user.roles)) return user + if (user.role) { + user.roles = [user.role] + delete user.role + } else { + user.roles = ['mitglied'] + } + return user }) })) @@ -37,21 +48,34 @@ describe('CMS User Management Endpoints', () => { const adminEvent = () => { const event = createEvent({ cookies: { auth_token: 'token' } }) - authUtils.getUserFromToken.mockResolvedValue({ id: 'admin', role: 'admin' }) + authUtils.getUserFromToken.mockResolvedValue({ id: 'admin', roles: ['admin'] }) + authUtils.hasAnyRole.mockReturnValue(true) 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' }) + authUtils.getUserFromToken.mockResolvedValue({ id: 'user', roles: ['mitglied'] }) + authUtils.hasAnyRole.mockReturnValue(false) 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' }]) + authUtils.readUsers.mockResolvedValue([{ id: '1', email: 'a@b.de', name: 'Anna', roles: ['mitglied'], phone: '1', active: true, created: 'now', lastLogin: null, password: 'secret' }]) + authUtils.migrateUserRoles.mockImplementation((user) => { + if (!user) return user + if (Array.isArray(user.roles)) return user + if (user.role) { + user.roles = [user.role] + delete user.role + } else { + user.roles = ['mitglied'] + } + return user + }) const response = await usersListHandler(event) expect(response.users[0]).not.toHaveProperty('password') @@ -62,7 +86,8 @@ describe('CMS User Management Endpoints', () => { 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' }) + authUtils.getUserFromToken.mockResolvedValue({ id: 'user', roles: ['mitglied'] }) + authUtils.hasAnyRole.mockReturnValue(false) mockSuccessReadBody({ userId: '1' }) await expect(usersApproveHandler(event)).rejects.toMatchObject({ statusCode: 403 }) @@ -78,9 +103,12 @@ describe('CMS User Management Endpoints', () => { it('aktiviert Benutzer und sendet Mail', async () => { const event = adminEvent() - mockSuccessReadBody({ userId: '1', role: 'vorstand' }) + mockSuccessReadBody({ userId: '1', roles: ['vorstand'] }) authUtils.readUsers.mockResolvedValue([{ id: '1', email: 'user@test.de', name: 'Udo', active: false }]) authUtils.writeUsers.mockResolvedValue(true) + // Setze SMTP-Credentials für Tests + process.env.SMTP_USER = 'test@example.com' + process.env.SMTP_PASS = 'test-password' const response = await usersApproveHandler(event) expect(response.success).toBe(true) @@ -124,16 +152,27 @@ describe('CMS User Management Endpoints', () => { describe('POST /api/cms/users/update-role', () => { it('validiert Rolle', async () => { const event = adminEvent() - mockSuccessReadBody({ userId: '1', role: 'invalid' }) + mockSuccessReadBody({ userId: '1', roles: ['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' }]) + mockSuccessReadBody({ userId: '1', roles: ['vorstand'] }) + authUtils.readUsers.mockResolvedValue([{ id: '1', roles: ['mitglied'] }]) authUtils.writeUsers.mockResolvedValue(true) + authUtils.migrateUserRoles.mockImplementation((user) => { + if (!user) return user + if (Array.isArray(user.roles)) return user + if (user.role) { + user.roles = [user.role] + delete user.role + } else { + user.roles = ['mitglied'] + } + return user + }) const response = await usersUpdateRoleHandler(event) expect(response.success).toBe(true) diff --git a/tests/galerie-endpoints.spec.ts b/tests/galerie-endpoints.spec.ts index fe7820d..ff40e01 100644 --- a/tests/galerie-endpoints.spec.ts +++ b/tests/galerie-endpoints.spec.ts @@ -18,7 +18,9 @@ vi.mock('../server/utils/auth.js', () => ({ vi.mock('sharp', () => ({ default: vi.fn(() => ({ resize: vi.fn().mockReturnThis(), - toFile: vi.fn().mockResolvedValue({}) + rotate: vi.fn().mockReturnThis(), + toFile: vi.fn().mockResolvedValue({}), + toBuffer: vi.fn().mockResolvedValue(Buffer.from('image data')) })) })) @@ -56,6 +58,9 @@ describe('Galerie API Endpoints', () => { vi.spyOn(fs, 'writeFile').mockResolvedValue(undefined) vi.spyOn(fs, 'mkdir').mockResolvedValue(undefined) vi.spyOn(fs, 'access').mockResolvedValue(undefined) + vi.spyOn(fs, 'rename').mockResolvedValue(undefined) + vi.spyOn(fs, 'stat').mockResolvedValue({ size: 1024 } as any) + vi.spyOn(fs, 'unlink').mockResolvedValue(undefined) }) describe('POST /api/galerie/upload', () => { @@ -72,17 +77,30 @@ describe('Galerie API Endpoints', () => { 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 }) + authUtils.getUserFromToken.mockResolvedValue({ id: '1', roles: ['mitglied'], active: true }) + authUtils.hasAnyRole.mockReturnValue(false) 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' } + const mockPath = 'tmp/test.jpg' + event.node.req.__mockFile = { filename: 'test.jpg', path: mockPath, 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 }) + authUtils.getUserFromToken.mockResolvedValue({ id: '1', roles: ['admin'], active: true }) + // hasAnyRole muss für diesen Test true zurückgeben + authUtils.hasAnyRole.mockImplementation((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)) + }) + + // Mock fs.rename für die Datei-Verschiebung + vi.spyOn(fs, 'rename').mockResolvedValue(undefined) + // Mock fs.readFile für Metadaten + vi.spyOn(fs, 'readFile').mockResolvedValue('[]') const response = await uploadHandler(event) @@ -142,6 +160,7 @@ describe('Galerie API Endpoints', () => { { id: '1', filename: 'test.jpg', previewFilename: 'preview_test.jpg', isPublic: false } ])) .mockResolvedValueOnce(Buffer.from('image data')) + vi.spyOn(fs, 'access').mockResolvedValue(undefined) authUtils.verifyToken.mockReturnValue({ id: '1' }) authUtils.getUserFromToken.mockResolvedValue({ id: '1', active: true }) @@ -158,6 +177,7 @@ describe('Galerie API Endpoints', () => { { id: '1', filename: 'test.jpg', previewFilename: 'preview_test.jpg', isPublic: true } ])) .mockResolvedValueOnce(Buffer.from('preview data')) + vi.spyOn(fs, 'access').mockResolvedValue(undefined) const response = await imageHandler(event)