import type { Logger } from '@core/shared/domain/Logger'; import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest'; import type { FeedRepository } from '../../domain/repositories/FeedRepository'; import type { FeedItem } from '../../domain/types/FeedItem'; import { GetUserFeedUseCase, type GetUserFeedApplicationError, type GetUserFeedInput, } from './GetUserFeedUseCase'; describe('GetUserFeedUseCase', () => { let feedRepository: FeedRepository & { getFeedForDriver: Mock }; let logger: Logger & { debug: Mock; info: Mock; warn: Mock; error: Mock }; let useCase: GetUserFeedUseCase; beforeEach(() => { feedRepository = { getFeedForDriver: vi.fn(), getGlobalFeed: vi.fn(), } as unknown as FeedRepository & { getFeedForDriver: Mock }; logger = { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), } as unknown as Logger & { debug: Mock; info: Mock; warn: Mock; error: Mock }; useCase = new GetUserFeedUseCase(feedRepository, logger); }); it('returns feed items when repository returns items', async () => { const items: FeedItem[] = [ { id: 'item-1', timestamp: new Date('2025-01-01T00:00:00.000Z'), type: 'friend-joined-league', actorFriendId: 'friend-1', leagueId: 'league-1', headline: 'Friend joined a league', body: 'Friend joined League 1', ctaLabel: 'View league', ctaHref: '/leagues/league-1', }, { id: 'item-2', timestamp: new Date('2025-01-02T00:00:00.000Z'), type: 'friend-finished-race', actorDriverId: 'driver-2', raceId: 'race-1', position: 3, headline: 'Race finished', }, ]; feedRepository.getFeedForDriver.mockResolvedValue(items); const input: GetUserFeedInput = { driverId: 'driver-1', limit: 10 }; const result = await useCase.execute(input); expect(result.isOk()).toBe(true); const feedResult = result.unwrap(); expect(feedRepository.getFeedForDriver).toHaveBeenCalledTimes(1); expect(feedRepository.getFeedForDriver).toHaveBeenCalledWith('driver-1', 10); expect(feedResult.items).toEqual(items); expect(logger.warn).not.toHaveBeenCalled(); }); it('returns empty list when no items exist', async () => { feedRepository.getFeedForDriver.mockResolvedValue([]); const input: GetUserFeedInput = { driverId: 'driver-1' }; const result = await useCase.execute(input); expect(result.isOk()).toBe(true); const feedResult = result.unwrap(); expect(feedResult.items).toEqual([]); expect(logger.warn).toHaveBeenCalledTimes(1); expect((logger.warn as Mock).mock.calls[0]![0]).toBe( 'No feed items found for driverId: driver-1', ); }); it('returns REPOSITORY_ERROR when repository throws', async () => { feedRepository.getFeedForDriver.mockRejectedValue(new Error('DB error')); const input: GetUserFeedInput = { driverId: 'driver-1', limit: 5 }; const result = await useCase.execute(input); expect(result.isErr()).toBe(true); const err = result.unwrapErr() as GetUserFeedApplicationError; expect(err.code).toBe('REPOSITORY_ERROR'); expect(err.details.message).toBe('DB error'); expect(logger.error).toHaveBeenCalledTimes(1); }); });