rating
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
import { describe, expect, it, vi, beforeEach } from 'vitest';
|
||||
|
||||
import { AppendRatingEventsUseCase, AppendRatingEventsInput } from './AppendRatingEventsUseCase';
|
||||
import { IRatingEventRepository } from '../../domain/repositories/IRatingEventRepository';
|
||||
import { IUserRatingRepository } from '../../domain/repositories/IUserRatingRepository';
|
||||
import { RatingEvent } from '../../domain/entities/RatingEvent';
|
||||
import { UserRating } from '../../domain/value-objects/UserRating';
|
||||
import { RatingEventId } from '../../domain/value-objects/RatingEventId';
|
||||
|
||||
describe('AppendRatingEventsUseCase', () => {
|
||||
let mockEventRepo: Partial<IRatingEventRepository>;
|
||||
let mockRatingRepo: Partial<IUserRatingRepository>;
|
||||
|
||||
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 IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
expect(useCase).toBeInstanceOf(AppendRatingEventsUseCase);
|
||||
});
|
||||
|
||||
it('should handle empty input (no events)', async () => {
|
||||
const useCase = new AppendRatingEventsUseCase(
|
||||
mockEventRepo as IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
|
||||
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 IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
|
||||
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 IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
|
||||
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 IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
|
||||
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 IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
|
||||
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 IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user