195 lines
6.3 KiB
JavaScript
195 lines
6.3 KiB
JavaScript
const RegisterUserCommandHandler = require('../../../src/application/auth/commands/RegisterUserCommandHandler');
|
|
const RegisterUserCommand = require('../../../src/application/auth/commands/RegisterUserCommand');
|
|
const bcrypt = require('bcryptjs');
|
|
const JwtService = require('../../../src/application/services/JwtService');
|
|
|
|
// Mock dependencies
|
|
jest.mock('bcryptjs');
|
|
jest.mock('../../../src/application/services/JwtService');
|
|
|
|
describe('RegisterUserCommandHandler', () => {
|
|
let handler;
|
|
let mockPrisma;
|
|
let mockEmailService;
|
|
let mockJwtService;
|
|
|
|
beforeEach(() => {
|
|
// Mock JwtService instance
|
|
mockJwtService = {
|
|
generateToken: jest.fn()
|
|
};
|
|
JwtService.mockImplementation(() => mockJwtService);
|
|
|
|
// Mock Prisma
|
|
mockPrisma = {
|
|
user: {
|
|
findUnique: jest.fn(),
|
|
create: jest.fn()
|
|
}
|
|
};
|
|
|
|
// Mock EmailService
|
|
mockEmailService = {
|
|
sendWelcomeEmail: jest.fn().mockResolvedValue(true)
|
|
};
|
|
|
|
handler = new RegisterUserCommandHandler(mockPrisma, mockEmailService);
|
|
|
|
// Reset all mocks
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe('handle - success cases', () => {
|
|
it('should register a new user successfully', async () => {
|
|
// Arrange
|
|
const command = new RegisterUserCommand('John Doe', 'john@example.com', 'password123');
|
|
|
|
mockPrisma.user.findUnique.mockResolvedValue(null); // No existing user
|
|
bcrypt.hash.mockResolvedValue('hashed_password');
|
|
mockPrisma.user.create.mockResolvedValue({
|
|
id: 1,
|
|
name: 'John Doe',
|
|
email: 'john@example.com',
|
|
password: 'hashed_password',
|
|
createdAt: new Date(),
|
|
updatedAt: new Date()
|
|
});
|
|
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.hash).toHaveBeenCalledWith('password123', 10);
|
|
expect(mockPrisma.user.create).toHaveBeenCalledWith({
|
|
data: {
|
|
name: 'John Doe',
|
|
email: 'john@example.com',
|
|
password: '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
|
|
});
|
|
|
|
it('should send welcome email after registration', async () => {
|
|
// Arrange
|
|
const command = new RegisterUserCommand('Jane Doe', 'jane@example.com', 'password123');
|
|
|
|
mockPrisma.user.findUnique.mockResolvedValue(null);
|
|
bcrypt.hash.mockResolvedValue('hashed_password');
|
|
mockPrisma.user.create.mockResolvedValue({
|
|
id: 2,
|
|
name: 'Jane Doe',
|
|
email: 'jane@example.com',
|
|
password: 'hashed_password',
|
|
createdAt: new Date(),
|
|
updatedAt: new Date()
|
|
});
|
|
mockJwtService.generateToken.mockReturnValue('mock_jwt_token');
|
|
|
|
// Act
|
|
await handler.handle(command);
|
|
|
|
// Assert
|
|
expect(mockEmailService.sendWelcomeEmail).toHaveBeenCalledWith('jane@example.com', 'Jane Doe');
|
|
});
|
|
});
|
|
|
|
describe('handle - validation errors', () => {
|
|
it('should throw error if name is missing', async () => {
|
|
// Arrange
|
|
const command = new RegisterUserCommand('', 'john@example.com', 'password123');
|
|
|
|
// Act & Assert
|
|
await expect(handler.handle(command)).rejects.toThrow('Name, email and password are required');
|
|
});
|
|
|
|
it('should throw error if email is missing', async () => {
|
|
// Arrange
|
|
const command = new RegisterUserCommand('John Doe', '', 'password123');
|
|
|
|
// Act & Assert
|
|
await expect(handler.handle(command)).rejects.toThrow('Name, email and password are required');
|
|
});
|
|
|
|
it('should throw error if password is missing', async () => {
|
|
// Arrange
|
|
const command = new RegisterUserCommand('John Doe', 'john@example.com', '');
|
|
|
|
// Act & Assert
|
|
await expect(handler.handle(command)).rejects.toThrow('Name, email and password are required');
|
|
});
|
|
|
|
it('should throw error if password is too short', async () => {
|
|
// Arrange
|
|
const command = new RegisterUserCommand('John Doe', 'john@example.com', '12345');
|
|
|
|
// Act & Assert
|
|
await expect(handler.handle(command)).rejects.toThrow('Password must be at least 6 characters long');
|
|
});
|
|
|
|
it('should throw error if email format is invalid', async () => {
|
|
// Arrange
|
|
const command = new RegisterUserCommand('John Doe', 'invalid-email', 'password123');
|
|
|
|
// Act & Assert
|
|
await expect(handler.handle(command)).rejects.toThrow('Invalid email format');
|
|
});
|
|
|
|
it('should throw error if user already exists', async () => {
|
|
// Arrange
|
|
const command = new RegisterUserCommand('John Doe', 'john@example.com', 'password123');
|
|
|
|
mockPrisma.user.findUnique.mockResolvedValue({
|
|
id: 1,
|
|
email: 'john@example.com'
|
|
});
|
|
|
|
// Act & Assert
|
|
await expect(handler.handle(command)).rejects.toThrow('User with this email already exists');
|
|
});
|
|
});
|
|
|
|
describe('handle - error handling', () => {
|
|
it('should not fail if email service throws error', async () => {
|
|
// Arrange
|
|
const command = new RegisterUserCommand('John Doe', 'john@example.com', 'password123');
|
|
|
|
mockPrisma.user.findUnique.mockResolvedValue(null);
|
|
bcrypt.hash.mockResolvedValue('hashed_password');
|
|
mockPrisma.user.create.mockResolvedValue({
|
|
id: 1,
|
|
name: 'John Doe',
|
|
email: 'john@example.com',
|
|
password: 'hashed_password',
|
|
createdAt: new Date(),
|
|
updatedAt: new Date()
|
|
});
|
|
mockJwtService.generateToken.mockReturnValue('mock_jwt_token');
|
|
mockEmailService.sendWelcomeEmail.mockRejectedValue(new Error('Email service error'));
|
|
|
|
// Act
|
|
const result = await handler.handle(command);
|
|
|
|
// Assert - should still return user and token even if email fails
|
|
expect(result.user.email).toBe('john@example.com');
|
|
expect(result.token).toBe('mock_jwt_token');
|
|
});
|
|
});
|
|
});
|