import { describe, it, expect, vi, type Mock } from 'vitest'; import { GetNotificationPreferencesQuery, UpdateChannelPreferenceUseCase, UpdateTypePreferenceUseCase, UpdateQuietHoursUseCase, SetDigestModeUseCase, } from './NotificationPreferencesUseCases'; import type { INotificationPreferenceRepository } from '../../domain/repositories/INotificationPreferenceRepository'; import type { NotificationPreference , ChannelPreference, TypePreference } from '../../domain/entities/NotificationPreference'; import type { Logger } from '@core/shared/application'; import type { NotificationChannel, NotificationType } from '../../domain/types/NotificationTypes'; import { NotificationDomainError } from '../../domain/errors/NotificationDomainError'; describe('NotificationPreferencesUseCases', () => { let preferenceRepository: { getOrCreateDefault: Mock; save: Mock; }; let logger: Logger; beforeEach(() => { preferenceRepository = { getOrCreateDefault: vi.fn(), save: vi.fn(), } as unknown as INotificationPreferenceRepository as any; logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), } as unknown as Logger; }); it('GetNotificationPreferencesQuery returns preferences from repository', async () => { const preference = { id: 'pref-1', } as unknown as NotificationPreference; preferenceRepository.getOrCreateDefault.mockResolvedValue(preference); const useCase = new GetNotificationPreferencesQuery( preferenceRepository as unknown as INotificationPreferenceRepository, logger, ); const result = await useCase.execute('driver-1'); expect(preferenceRepository.getOrCreateDefault).toHaveBeenCalledWith('driver-1'); expect(result).toBe(preference); }); it('UpdateChannelPreferenceUseCase updates channel preference', async () => { const preference = { updateChannel: vi.fn().mockReturnThis(), } as unknown as NotificationPreference; preferenceRepository.getOrCreateDefault.mockResolvedValue(preference); const useCase = new UpdateChannelPreferenceUseCase( preferenceRepository as unknown as INotificationPreferenceRepository, logger, ); await useCase.execute({ driverId: 'driver-1', channel: 'email' as NotificationChannel, preference: 'enabled' as ChannelPreference, }); expect(preference.updateChannel).toHaveBeenCalled(); expect(preferenceRepository.save).toHaveBeenCalledWith(preference); }); it('UpdateTypePreferenceUseCase updates type preference', async () => { const preference = { updateTypePreference: vi.fn().mockReturnThis(), } as unknown as NotificationPreference; preferenceRepository.getOrCreateDefault.mockResolvedValue(preference); const useCase = new UpdateTypePreferenceUseCase( preferenceRepository as unknown as INotificationPreferenceRepository, logger, ); await useCase.execute({ driverId: 'driver-1', type: 'info' as NotificationType, preference: 'enabled' as TypePreference, }); expect(preference.updateTypePreference).toHaveBeenCalled(); expect(preferenceRepository.save).toHaveBeenCalledWith(preference); }); it('UpdateQuietHoursUseCase validates hours and updates preferences', async () => { const preference = { updateQuietHours: vi.fn().mockReturnThis(), } as unknown as NotificationPreference; preferenceRepository.getOrCreateDefault.mockResolvedValue(preference); const useCase = new UpdateQuietHoursUseCase( preferenceRepository as unknown as INotificationPreferenceRepository, logger, ); await useCase.execute({ driverId: 'driver-1', startHour: 22, endHour: 7, }); expect(preference.updateQuietHours).toHaveBeenCalledWith(22, 7); expect(preferenceRepository.save).toHaveBeenCalledWith(preference); }); it('UpdateQuietHoursUseCase throws on invalid hours', async () => { const useCase = new UpdateQuietHoursUseCase( preferenceRepository as unknown as INotificationPreferenceRepository, logger, ); await expect( useCase.execute({ driverId: 'd1', startHour: -1, endHour: 10 }), ).rejects.toThrow(NotificationDomainError); await expect( useCase.execute({ driverId: 'd1', startHour: 10, endHour: 24 }), ).rejects.toThrow(NotificationDomainError); }); it('SetDigestModeUseCase sets digest mode with valid frequency', async () => { const preference = { setDigestMode: vi.fn().mockReturnThis(), } as unknown as NotificationPreference; preferenceRepository.getOrCreateDefault.mockResolvedValue(preference); const useCase = new SetDigestModeUseCase( preferenceRepository as unknown as INotificationPreferenceRepository, ); await useCase.execute({ driverId: 'driver-1', enabled: true, frequencyHours: 4, }); expect(preference.setDigestMode).toHaveBeenCalledWith(true, 4); expect(preferenceRepository.save).toHaveBeenCalledWith(preference); }); it('SetDigestModeUseCase throws on invalid frequency', async () => { const useCase = new SetDigestModeUseCase( preferenceRepository as unknown as INotificationPreferenceRepository, ); await expect( useCase.execute({ driverId: 'driver-1', enabled: true, frequencyHours: 0 }), ).rejects.toThrow(NotificationDomainError); }); });