import type { Logger } from '@core/shared/domain/Logger'; import { describe, expect, it, vi, type Mock } from 'vitest'; import type { IdentitySessionPort } from '../ports/IdentitySessionPort'; import { SignupWithEmailUseCase } from './SignupWithEmailUseCase'; describe('SignupWithEmailUseCase', () => { let userRepository: { findByEmail: Mock; create: Mock; }; let sessionPort: { createSession: Mock; }; let logger: Logger; let useCase: SignupWithEmailUseCase; beforeEach(() => { userRepository = { findByEmail: vi.fn(), create: vi.fn(), }; sessionPort = { createSession: vi.fn(), }; logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), } as unknown as Logger; useCase = new SignupWithEmailUseCase( userRepository as unknown as UserRepository, sessionPort as unknown as IdentitySessionPort, logger, ); }); it('creates a new user and session for valid input', async () => { userRepository.findByEmail.mockResolvedValue(null); userRepository.create.mockResolvedValue(undefined); sessionPort.createSession.mockResolvedValue({ token: 'session-token', user: { id: 'user-1', displayName: 'Test User', email: 'test@example.com', }, issuedAt: Date.now(), expiresAt: Date.now() + 1000, }); const result = await useCase.execute({ email: 'test@example.com', password: 'Password123', displayName: 'Test User', }); expect(result.isOk()).toBe(true); const signupResult = result.unwrap(); expect(signupResult.sessionToken).toBe('session-token'); expect(signupResult.userId).toBe('user-1'); expect(signupResult.displayName).toBe('Test User'); expect(signupResult.email).toBe('test@example.com'); expect(signupResult.isNewUser).toBe(true); expect(userRepository.findByEmail).toHaveBeenCalledWith('test@example.com'); expect(userRepository.create).toHaveBeenCalled(); expect(sessionPort.createSession).toHaveBeenCalled(); }); it('returns error for invalid email format', async () => { const result = await useCase.execute({ email: 'invalid-email', password: 'Password123', displayName: 'Test User', }); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('INVALID_EMAIL_FORMAT'); }); it('returns error for weak password', async () => { const result = await useCase.execute({ email: 'test@example.com', password: 'weak', displayName: 'Test User', }); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('WEAK_PASSWORD'); }); it('returns error for invalid display name', async () => { const result = await useCase.execute({ email: 'test@example.com', password: 'Password123', displayName: 'A', }); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('INVALID_DISPLAY_NAME'); }); it('returns error when email already exists', async () => { userRepository.findByEmail.mockResolvedValue({ id: 'existing-user', email: 'test@example.com', displayName: 'Existing User', passwordHash: 'hash', createdAt: new Date(), }); const result = await useCase.execute({ email: 'test@example.com', password: 'Password123', displayName: 'Test User', }); expect(result.isErr()).toBe(true); expect(result.unwrapErr().code).toBe('EMAIL_ALREADY_EXISTS'); }); });