Files
gridpilot.gg/core/social/application/use-cases/GetUserFeedUseCase.test.ts
2026-01-16 19:46:49 +01:00

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);
});
});