From 68e21cc271f381b939dad0d673cc4a7c2c19081e Mon Sep 17 00:00:00 2001 From: Leopoldadmin Date: Mon, 22 Jun 2026 05:41:13 +0000 Subject: [PATCH] feat(auth): add unit tests for AuthService --- backend/src/auth/__tests__/auth.test.ts | 125 ++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 backend/src/auth/__tests__/auth.test.ts diff --git a/backend/src/auth/__tests__/auth.test.ts b/backend/src/auth/__tests__/auth.test.ts new file mode 100644 index 0000000..cf33c93 --- /dev/null +++ b/backend/src/auth/__tests__/auth.test.ts @@ -0,0 +1,125 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import AuthService from '../AuthService'; +import { FastifyInstance } from 'fastify'; + +// Mock Fastify instance +const mockFastify = { + jwt: { + sign: (payload: any) => JSON.stringify(payload), + verify: (token: string) => JSON.parse(token) + } +} as unknown as FastifyInstance; + +describe('AuthService', () => { + let authService: AuthService; + + beforeEach(() => { + authService = new AuthService(mockFastify); + }); + + describe('register', () => { + it('should create a user with hashed password', async () => { + const user = await authService.register('test@example.com', 'password123', 'Test User'); + + expect(user).toHaveProperty('id'); + expect(user.email).toBe('test@example.com'); + expect(user.displayName).toBe('Test User'); + expect(user).not.toHaveProperty('passwordHash'); + }); + + it('should throw an error if user already exists', async () => { + await authService.register('test@example.com', 'password123', 'Test User'); + + await expect(authService.register('test@example.com', 'password123', 'Test User')) + .rejects.toThrow('User already exists'); + }); + }); + + describe('login', () => { + it('should return a JWT token for valid credentials', async () => { + await authService.register('test@example.com', 'password123', 'Test User'); + + const token = await authService.login('test@example.com', 'password123'); + + expect(token).toBeDefined(); + expect(typeof token).toBe('string'); + }); + + it('should throw an error for invalid credentials', async () => { + await expect(authService.login('test@example.com', 'wrongpassword')) + .rejects.toThrow('Invalid credentials'); + }); + }); + + describe('logout', () => { + it('should invalidate the session', async () => { + await authService.register('test@example.com', 'password123', 'Test User'); + const token = await authService.login('test@example.com', 'password123'); + + await expect(authService.logout(token)).resolves.not.toThrow(); + }); + + it('should throw an error for invalid token', async () => { + await expect(authService.logout('invalid-token')) + .rejects.toThrow('Invalid token'); + }); + }); + + describe('getMe', () => { + it('should return current user info', async () => { + const user = await authService.register('test@example.com', 'password123', 'Test User'); + + const userInfo = await authService.getMe(user.id); + + expect(userInfo).toEqual(user); + }); + + it('should throw an error if user not found', async () => { + await expect(authService.getMe('non-existent-id')) + .rejects.toThrow('User not found'); + }); + }); + + describe('requestPasswordReset', () => { + it('should generate a reset token', async () => { + await authService.register('test@example.com', 'password123', 'Test User'); + + // Mock console.log to verify it's called + const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); + + await authService.requestPasswordReset('test@example.com'); + + expect(consoleSpy).toHaveBeenCalled(); + + consoleSpy.mockRestore(); + }); + }); + + describe('confirmPasswordReset', () => { + it('should reset password with valid token', async () => { + // Register user + const user = await authService.register('test@example.com', 'password123', 'Test User'); + + // Mock console.log to capture the reset token + let resetToken = ''; + const consoleSpy = vi.spyOn(console, 'log').mockImplementation((msg) => { + if (msg.startsWith('Password reset token for')) { + resetToken = msg.split(': ')[1]; + } + }); + + // Request password reset + await authService.requestPasswordReset('test@example.com'); + + consoleSpy.mockRestore(); + + // Confirm password reset + await expect(authService.confirmPasswordReset(resetToken, 'newpassword123')) + .resolves.not.toThrow(); + + // Verify login with new password works + await expect(authService.login('test@example.com', 'newpassword123')) + .resolves.toBeDefined(); + }); + }); +});