import { ServiceUnavailableException } from '@nestjs/common'; import { PasswordService } from './password.service'; describe('PasswordService', () => { it('logs password reset mail delivery failures with stable error code', async () => { const resetTokens = { create: jest.fn((value) => value), save: jest.fn(async (value) => ({ ...value, id: 'token-id' })), delete: jest.fn().mockResolvedValue(undefined), }; const service = new PasswordService( resetTokens as any, { get: jest.fn((key: string) => (key === 'SMTP_HOST' ? 'smtp.example.com' : 'secret')), getOrThrow: jest.fn(() => 'secret') } as any, {} as any, { findUserByEmail: jest.fn().mockResolvedValue({ id: 'user-1', email: 'maria@example.com' }) } as any, { sendPasswordResetMail: jest.fn().mockRejectedValue(new Error('SMTP unavailable')) } as any, { record: jest.fn().mockResolvedValue(undefined) } as any, { log: jest.fn().mockResolvedValue(undefined) } as any, { get: jest.fn(() => ({ correlationId: 'corr-1' })) } as any, ); await expect(service.requestReset('maria@example.com')).rejects.toBeInstanceOf(ServiceUnavailableException); expect((service as any).applicationErrorLogger.log).toHaveBeenCalledWith(expect.objectContaining({ code: 'PASSWORD_RESET_EMAIL_SEND_FAILED', category: 'EMAIL', requestContext: expect.objectContaining({ correlationId: 'corr-1', userId: 'user-1' }), context: expect.objectContaining({ maskedRecipient: 'm***@example.com', mailProvider: 'smtp.example.com' }), handled: true, })); }); });