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

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