import { describe, it, expect, vi, type Mock } from 'vitest'; import { RecordEngagementUseCase, type RecordEngagementInput, type RecordEngagementOutput } from './RecordEngagementUseCase'; import type { IEngagementRepository } from '../../domain/repositories/IEngagementRepository'; import { EngagementEvent } from '../../domain/entities/EngagementEvent'; import type { Logger, UseCaseOutputPort } from '@core/shared/application'; import type { EngagementAction, EngagementEntityType } from '../../domain/types/EngagementEvent'; describe('RecordEngagementUseCase', () => { let engagementRepository: { save: Mock; }; let logger: Logger; let output: UseCaseOutputPort & { present: Mock }; let useCase: RecordEngagementUseCase; beforeEach(() => { engagementRepository = { save: vi.fn(), } as unknown as IEngagementRepository as any; logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), } as unknown as Logger; output = { present: vi.fn(), }; useCase = new RecordEngagementUseCase( engagementRepository as unknown as IEngagementRepository, logger, output, ); }); it('creates and saves an EngagementEvent and presents its id and weight', async () => { const input: RecordEngagementInput = { action: 'view' as EngagementAction, entityType: 'league' as EngagementEntityType, entityId: 'league-1', actorId: 'driver-1', actorType: 'driver', sessionId: 'session-1', metadata: { foo: 'bar' }, }; engagementRepository.save.mockResolvedValue(undefined); const result = await useCase.execute(input); expect(result.isOk()).toBe(true); expect(engagementRepository.save).toHaveBeenCalledTimes(1); const saved = (engagementRepository.save as unknown as Mock).mock.calls?.[0]?.[0] as EngagementEvent; expect(saved).toBeInstanceOf(EngagementEvent); expect(saved.id).toBeDefined(); expect(saved.entityId).toBe(input.entityId); expect(saved.entityType).toBe(input.entityType); expect(output.present).toHaveBeenCalledWith({ eventId: saved.id, engagementWeight: saved.getEngagementWeight(), }); expect((logger.info as unknown as Mock)).toHaveBeenCalled(); }); it('logs and presents error when repository save fails', async () => { const input: RecordEngagementInput = { action: 'view' as EngagementAction, entityType: 'league' as EngagementEntityType, entityId: 'league-1', actorType: 'anonymous', sessionId: 'session-1', }; const error = new Error('DB error'); engagementRepository.save.mockRejectedValue(error); const result = await useCase.execute(input); expect(result.isErr()).toBe(true); expect((logger.error as unknown as Mock)).toHaveBeenCalled(); }); });