const LoginUserCommandHandler = require('../../../src/application/auth/commands/LoginUserCommandHandler'); const LoginUserCommand = require('../../../src/application/auth/commands/LoginUserCommand'); const bcrypt = require('bcryptjs'); const JwtService = require('../../../src/application/services/JwtService'); // Mock dependencies jest.mock('bcryptjs'); jest.mock('../../../src/application/services/JwtService'); describe('LoginUserCommandHandler', () => { let handler; let mockPrisma; let mockJwtService; beforeEach(() => { // Mock JwtService instance mockJwtService = { generateToken: jest.fn() }; JwtService.mockImplementation(() => mockJwtService); // Mock Prisma mockPrisma = { user: { findUnique: jest.fn() } }; handler = new LoginUserCommandHandler(mockPrisma); // Reset all mocks jest.clearAllMocks(); }); describe('handle - success cases', () => { it('should login user successfully with valid credentials', async () => { // Arrange const command = new LoginUserCommand('john@example.com', 'password123'); mockPrisma.user.findUnique.mockResolvedValue({ id: 1, name: 'John Doe', email: 'john@example.com', password: 'hashed_password', createdAt: new Date(), updatedAt: new Date() }); bcrypt.compare.mockResolvedValue(true); // Password is valid mockJwtService.generateToken.mockReturnValue('mock_jwt_token'); // Act const result = await handler.handle(command); // Assert expect(mockPrisma.user.findUnique).toHaveBeenCalledWith({ where: { email: 'john@example.com' } }); expect(bcrypt.compare).toHaveBeenCalledWith('password123', 'hashed_password'); expect(mockJwtService.generateToken).toHaveBeenCalledWith({ userId: 1, email: 'john@example.com' }); expect(result.user).toEqual({ id: 1, name: 'John Doe', email: 'john@example.com', createdAt: expect.any(Date), updatedAt: expect.any(Date) }); expect(result.token).toBe('mock_jwt_token'); expect(result.user.password).toBeUndefined(); // Password should not be returned }); }); describe('handle - validation errors', () => { it('should throw error if email is missing', async () => { // Arrange const command = new LoginUserCommand('', 'password123'); // Act & Assert await expect(handler.handle(command)).rejects.toThrow('Email and password are required'); }); it('should throw error if password is missing', async () => { // Arrange const command = new LoginUserCommand('john@example.com', ''); // Act & Assert await expect(handler.handle(command)).rejects.toThrow('Email and password are required'); }); it('should throw error if user does not exist', async () => { // Arrange const command = new LoginUserCommand('nonexistent@example.com', 'password123'); mockPrisma.user.findUnique.mockResolvedValue(null); // Act & Assert await expect(handler.handle(command)).rejects.toThrow('Invalid email or password'); }); it('should throw error if password is incorrect', async () => { // Arrange const command = new LoginUserCommand('john@example.com', 'wrongpassword'); mockPrisma.user.findUnique.mockResolvedValue({ id: 1, email: 'john@example.com', password: 'hashed_password' }); bcrypt.compare.mockResolvedValue(false); // Password is invalid // Act & Assert await expect(handler.handle(command)).rejects.toThrow('Invalid email or password'); }); }); });