add tests to core
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
GetCurrentUserSocialUseCase,
|
||||
type GetCurrentUserSocialApplicationError,
|
||||
type GetCurrentUserSocialInput,
|
||||
type GetCurrentUserSocialResult,
|
||||
} from './GetCurrentUserSocialUseCase';
|
||||
import type { ISocialGraphRepository } from '../../domain/repositories/ISocialGraphRepository';
|
||||
import type { Logger, UseCaseOutputPort } from '@core/shared/application';
|
||||
import { Driver } from '@core/racing/domain/entities/Driver';
|
||||
|
||||
describe('GetCurrentUserSocialUseCase', () => {
|
||||
let socialGraphRepository: ISocialGraphRepository & { getFriends: Mock };
|
||||
let logger: Logger & { debug: Mock; info: Mock; warn: Mock; error: Mock };
|
||||
let output: UseCaseOutputPort<GetCurrentUserSocialResult> & { present: Mock };
|
||||
let useCase: GetCurrentUserSocialUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
socialGraphRepository = {
|
||||
getFriends: vi.fn(),
|
||||
getFriendIds: vi.fn(),
|
||||
getSuggestedFriends: vi.fn(),
|
||||
} as unknown as ISocialGraphRepository & { getFriends: 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 };
|
||||
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
} as unknown as UseCaseOutputPort<GetCurrentUserSocialResult> & { present: Mock };
|
||||
|
||||
useCase = new GetCurrentUserSocialUseCase(socialGraphRepository, logger, output);
|
||||
});
|
||||
|
||||
it('presents current user social with mapped friends', async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date('2025-01-01T00:00:00.000Z'));
|
||||
|
||||
const friends = [
|
||||
Driver.create({
|
||||
id: 'friend-1',
|
||||
iracingId: '123',
|
||||
name: 'Friend One',
|
||||
country: 'US',
|
||||
}),
|
||||
];
|
||||
|
||||
socialGraphRepository.getFriends.mockResolvedValue(friends);
|
||||
|
||||
const input: GetCurrentUserSocialInput = { driverId: 'driver-1' };
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
|
||||
expect(output.present).toHaveBeenCalledTimes(1);
|
||||
const presented = (output.present as Mock).mock.calls[0]![0] as GetCurrentUserSocialResult;
|
||||
|
||||
expect(presented.currentUser).toEqual({
|
||||
driverId: 'driver-1',
|
||||
displayName: '',
|
||||
avatarUrl: '',
|
||||
countryCode: '',
|
||||
});
|
||||
|
||||
expect(presented.friends).toHaveLength(1);
|
||||
expect(presented.friends[0]).toEqual({
|
||||
driverId: 'friend-1',
|
||||
displayName: 'Friend One',
|
||||
avatarUrl: '',
|
||||
countryCode: '',
|
||||
isOnline: false,
|
||||
lastSeen: new Date('2025-01-01T00:00:00.000Z'),
|
||||
});
|
||||
|
||||
expect(logger.warn).not.toHaveBeenCalled();
|
||||
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('warns and presents empty friends list when no friends exist', async () => {
|
||||
socialGraphRepository.getFriends.mockResolvedValue([]);
|
||||
|
||||
const input: GetCurrentUserSocialInput = { driverId: 'driver-1' };
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(output.present).toHaveBeenCalledTimes(1);
|
||||
|
||||
const presented = (output.present as Mock).mock.calls[0]![0] as GetCurrentUserSocialResult;
|
||||
expect(presented.friends).toEqual([]);
|
||||
|
||||
expect(logger.warn).toHaveBeenCalledTimes(1);
|
||||
expect((logger.warn as Mock).mock.calls[0]![0]).toBe(
|
||||
'GetCurrentUserSocialUseCase.execute: No friends found for driverId: driver-1',
|
||||
);
|
||||
});
|
||||
|
||||
it('returns REPOSITORY_ERROR when repository throws', async () => {
|
||||
socialGraphRepository.getFriends.mockRejectedValue(new Error('DB error'));
|
||||
|
||||
const input: GetCurrentUserSocialInput = { driverId: 'driver-1' };
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isErr()).toBe(true);
|
||||
|
||||
const err = result.unwrapErr() as GetCurrentUserSocialApplicationError;
|
||||
expect(err.code).toBe('REPOSITORY_ERROR');
|
||||
expect(err.details.message).toBe('DB error');
|
||||
|
||||
expect(output.present).not.toHaveBeenCalled();
|
||||
expect(logger.error).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
113
core/social/application/use-cases/GetUserFeedUseCase.test.ts
Normal file
113
core/social/application/use-cases/GetUserFeedUseCase.test.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
|
||||
import {
|
||||
GetUserFeedUseCase,
|
||||
type GetUserFeedApplicationError,
|
||||
type GetUserFeedInput,
|
||||
type GetUserFeedResult,
|
||||
} from './GetUserFeedUseCase';
|
||||
import type { IFeedRepository } from '../../domain/repositories/IFeedRepository';
|
||||
import type { FeedItem } from '../../domain/types/FeedItem';
|
||||
import type { Logger, UseCaseOutputPort } from '@core/shared/application';
|
||||
|
||||
describe('GetUserFeedUseCase', () => {
|
||||
let feedRepository: IFeedRepository & { getFeedForDriver: Mock };
|
||||
let logger: Logger & { debug: Mock; info: Mock; warn: Mock; error: Mock };
|
||||
let output: UseCaseOutputPort<GetUserFeedResult> & { present: Mock };
|
||||
let useCase: GetUserFeedUseCase;
|
||||
|
||||
beforeEach(() => {
|
||||
feedRepository = {
|
||||
getFeedForDriver: vi.fn(),
|
||||
getGlobalFeed: vi.fn(),
|
||||
} as unknown as IFeedRepository & { 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 };
|
||||
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
} as unknown as UseCaseOutputPort<GetUserFeedResult> & { present: Mock };
|
||||
|
||||
useCase = new GetUserFeedUseCase(feedRepository, logger, output);
|
||||
});
|
||||
|
||||
it('presents 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);
|
||||
expect(result.unwrap()).toBeUndefined();
|
||||
|
||||
expect(feedRepository.getFeedForDriver).toHaveBeenCalledTimes(1);
|
||||
expect(feedRepository.getFeedForDriver).toHaveBeenCalledWith('driver-1', 10);
|
||||
|
||||
expect(output.present).toHaveBeenCalledTimes(1);
|
||||
const presented = (output.present as Mock).mock.calls[0]![0] as GetUserFeedResult;
|
||||
expect(presented.items).toEqual(items);
|
||||
|
||||
expect(logger.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('warns and presents 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);
|
||||
expect(output.present).toHaveBeenCalledTimes(1);
|
||||
|
||||
const presented = (output.present as Mock).mock.calls[0]![0] as GetUserFeedResult;
|
||||
expect(presented.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(output.present).not.toHaveBeenCalled();
|
||||
expect(logger.error).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user