103 lines
3.3 KiB
TypeScript
103 lines
3.3 KiB
TypeScript
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);
|
|
});
|
|
}); |