174 lines
5.2 KiB
TypeScript
174 lines
5.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import { RatingEventRepository } from '../../domain/repositories/RatingEventRepository';
|
|
import { UserRatingRepository } from '../../domain/repositories/UserRatingRepository';
|
|
import { AppendRatingEventsInput, AppendRatingEventsUseCase } from './AppendRatingEventsUseCase';
|
|
|
|
describe('AppendRatingEventsUseCase', () => {
|
|
let mockEventRepo: Partial<RatingEventRepository>;
|
|
let mockRatingRepo: Partial<UserRatingRepository>;
|
|
|
|
beforeEach(() => {
|
|
mockEventRepo = {
|
|
save: vi.fn(),
|
|
getAllByUserId: vi.fn().mockResolvedValue([]),
|
|
};
|
|
|
|
mockRatingRepo = {
|
|
save: vi.fn(),
|
|
};
|
|
});
|
|
|
|
it('should be constructed with repositories', () => {
|
|
const useCase = new AppendRatingEventsUseCase(
|
|
mockEventRepo as RatingEventRepository,
|
|
mockRatingRepo as UserRatingRepository,
|
|
);
|
|
expect(useCase).toBeInstanceOf(AppendRatingEventsUseCase);
|
|
});
|
|
|
|
it('should handle empty input (no events)', async () => {
|
|
const useCase = new AppendRatingEventsUseCase(
|
|
mockEventRepo as RatingEventRepository,
|
|
mockRatingRepo as UserRatingRepository,
|
|
);
|
|
|
|
const input: AppendRatingEventsInput = {
|
|
userId: 'user-1',
|
|
};
|
|
|
|
const result = await useCase.execute(input);
|
|
|
|
expect(result.events).toEqual([]);
|
|
expect(result.snapshotUpdated).toBe(false);
|
|
expect(mockEventRepo.save).not.toHaveBeenCalled();
|
|
expect(mockRatingRepo.save).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should create and save events from direct input', async () => {
|
|
const useCase = new AppendRatingEventsUseCase(
|
|
mockEventRepo as RatingEventRepository,
|
|
mockRatingRepo as UserRatingRepository,
|
|
);
|
|
|
|
const input: AppendRatingEventsInput = {
|
|
userId: 'user-1',
|
|
events: [
|
|
{
|
|
userId: 'user-1',
|
|
dimension: 'driving',
|
|
delta: 5,
|
|
sourceType: 'race',
|
|
sourceId: 'race-1',
|
|
reasonCode: 'TEST',
|
|
reasonSummary: 'Test event',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = await useCase.execute(input);
|
|
|
|
expect(result.events).toHaveLength(1);
|
|
expect(result.snapshotUpdated).toBe(true);
|
|
expect(mockEventRepo.save).toHaveBeenCalledTimes(1);
|
|
expect(mockRatingRepo.save).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('should create events from race results using factory', async () => {
|
|
const useCase = new AppendRatingEventsUseCase(
|
|
mockEventRepo as RatingEventRepository,
|
|
mockRatingRepo as UserRatingRepository,
|
|
);
|
|
|
|
const input: AppendRatingEventsInput = {
|
|
userId: 'user-1',
|
|
raceId: 'race-123',
|
|
raceResults: [
|
|
{
|
|
position: 3,
|
|
totalDrivers: 10,
|
|
startPosition: 5,
|
|
incidents: 1,
|
|
fieldStrength: 1500,
|
|
status: 'finished',
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = await useCase.execute(input);
|
|
|
|
expect(result.events.length).toBeGreaterThan(0);
|
|
expect(result.snapshotUpdated).toBe(true);
|
|
expect(mockEventRepo.save).toHaveBeenCalled();
|
|
expect(mockRatingRepo.save).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should handle multiple race results', async () => {
|
|
const useCase = new AppendRatingEventsUseCase(
|
|
mockEventRepo as RatingEventRepository,
|
|
mockRatingRepo as UserRatingRepository,
|
|
);
|
|
|
|
const input: AppendRatingEventsInput = {
|
|
userId: 'user-1',
|
|
raceId: 'race-123',
|
|
raceResults: [
|
|
{ position: 3, totalDrivers: 10, startPosition: 5, incidents: 1, fieldStrength: 1500, status: 'finished' },
|
|
{ position: 1, totalDrivers: 10, startPosition: 2, incidents: 0, fieldStrength: 1500, status: 'finished' },
|
|
],
|
|
};
|
|
|
|
const result = await useCase.execute(input);
|
|
|
|
expect(result.events.length).toBeGreaterThan(2); // Multiple events per race
|
|
expect(result.snapshotUpdated).toBe(true);
|
|
});
|
|
|
|
it('should handle DNF status', async () => {
|
|
const useCase = new AppendRatingEventsUseCase(
|
|
mockEventRepo as RatingEventRepository,
|
|
mockRatingRepo as UserRatingRepository,
|
|
);
|
|
|
|
const input: AppendRatingEventsInput = {
|
|
userId: 'user-1',
|
|
raceId: 'race-123',
|
|
raceResults: [
|
|
{ position: 5, totalDrivers: 10, startPosition: 3, incidents: 2, fieldStrength: 1500, status: 'dnf' },
|
|
],
|
|
};
|
|
|
|
const result = await useCase.execute(input);
|
|
|
|
expect(result.events.length).toBeGreaterThan(0);
|
|
expect(result.snapshotUpdated).toBe(true);
|
|
expect(mockEventRepo.save).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should not update snapshot if no events were saved', async () => {
|
|
// Mock save to throw or do nothing
|
|
const saveMock = vi.fn().mockResolvedValue({});
|
|
const getAllMock = vi.fn().mockResolvedValue([]);
|
|
|
|
mockEventRepo = {
|
|
save: saveMock,
|
|
getAllByUserId: getAllMock,
|
|
};
|
|
|
|
const useCase = new AppendRatingEventsUseCase(
|
|
mockEventRepo as RatingEventRepository,
|
|
mockRatingRepo as UserRatingRepository,
|
|
);
|
|
|
|
const input: AppendRatingEventsInput = {
|
|
userId: 'user-1',
|
|
events: [], // Empty
|
|
};
|
|
|
|
const result = await useCase.execute(input);
|
|
|
|
expect(result.events).toEqual([]);
|
|
expect(result.snapshotUpdated).toBe(false);
|
|
expect(mockRatingRepo.save).not.toHaveBeenCalled();
|
|
});
|
|
}); |