rating
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import { describe, expect, it, vi, beforeEach } from 'vitest';
|
||||
|
||||
import { RecomputeUserRatingSnapshotUseCase } from './RecomputeUserRatingSnapshotUseCase';
|
||||
import { IRatingEventRepository } from '../../domain/repositories/IRatingEventRepository';
|
||||
import { IUserRatingRepository } from '../../domain/repositories/IUserRatingRepository';
|
||||
import { UserRating } from '../../domain/value-objects/UserRating';
|
||||
import { RatingEvent } from '../../domain/entities/RatingEvent';
|
||||
import { RatingEventId } from '../../domain/value-objects/RatingEventId';
|
||||
import { RatingDimensionKey } from '../../domain/value-objects/RatingDimensionKey';
|
||||
import { RatingDelta } from '../../domain/value-objects/RatingDelta';
|
||||
|
||||
describe('RecomputeUserRatingSnapshotUseCase', () => {
|
||||
let mockEventRepo: Partial<IRatingEventRepository>;
|
||||
let mockRatingRepo: Partial<IUserRatingRepository>;
|
||||
|
||||
beforeEach(() => {
|
||||
mockEventRepo = {
|
||||
getAllByUserId: vi.fn().mockResolvedValue([]),
|
||||
};
|
||||
|
||||
mockRatingRepo = {
|
||||
save: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
it('should be constructed with repositories', () => {
|
||||
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
||||
mockEventRepo as IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
expect(useCase).toBeInstanceOf(RecomputeUserRatingSnapshotUseCase);
|
||||
});
|
||||
|
||||
it('should compute snapshot from empty event list', async () => {
|
||||
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
||||
mockEventRepo as IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
|
||||
const result = await useCase.execute({ userId: 'user-1' });
|
||||
|
||||
expect(result.snapshot.userId).toBe('user-1');
|
||||
expect(result.snapshot.driver.value).toBe(50); // Default
|
||||
expect(mockEventRepo.getAllByUserId).toHaveBeenCalledWith('user-1');
|
||||
expect(mockRatingRepo.save).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should compute snapshot from events', async () => {
|
||||
const events = [
|
||||
RatingEvent.create({
|
||||
id: RatingEventId.generate(),
|
||||
userId: 'user-1',
|
||||
dimension: RatingDimensionKey.create('driving'),
|
||||
delta: RatingDelta.create(5),
|
||||
occurredAt: new Date('2024-01-01T10:00:00Z'),
|
||||
createdAt: new Date('2024-01-01T10:00:00Z'),
|
||||
source: { type: 'race', id: 'race-1' },
|
||||
reason: { code: 'TEST', summary: 'Test', details: {} },
|
||||
visibility: { public: true, redactedFields: [] },
|
||||
version: 1,
|
||||
}),
|
||||
];
|
||||
|
||||
mockEventRepo.getAllByUserId = vi.fn().mockResolvedValue(events);
|
||||
|
||||
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
||||
mockEventRepo as IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
|
||||
const result = await useCase.execute({ userId: 'user-1' });
|
||||
|
||||
expect(result.snapshot.userId).toBe('user-1');
|
||||
expect(result.snapshot.driver.value).toBeGreaterThan(50); // Should have increased
|
||||
expect(mockEventRepo.getAllByUserId).toHaveBeenCalledWith('user-1');
|
||||
expect(mockRatingRepo.save).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return proper DTO format', async () => {
|
||||
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
||||
mockEventRepo as IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
|
||||
const result = await useCase.execute({ userId: 'user-1' });
|
||||
|
||||
// Check DTO structure
|
||||
expect(result.snapshot).toHaveProperty('userId');
|
||||
expect(result.snapshot).toHaveProperty('driver');
|
||||
expect(result.snapshot).toHaveProperty('admin');
|
||||
expect(result.snapshot).toHaveProperty('steward');
|
||||
expect(result.snapshot).toHaveProperty('trust');
|
||||
expect(result.snapshot).toHaveProperty('fairness');
|
||||
expect(result.snapshot).toHaveProperty('overallReputation');
|
||||
expect(result.snapshot).toHaveProperty('createdAt');
|
||||
expect(result.snapshot).toHaveProperty('updatedAt');
|
||||
|
||||
// Check dimension structure
|
||||
expect(result.snapshot.driver).toEqual({
|
||||
value: expect.any(Number),
|
||||
confidence: expect.any(Number),
|
||||
sampleSize: expect.any(Number),
|
||||
trend: expect.any(String),
|
||||
lastUpdated: expect.any(String),
|
||||
});
|
||||
|
||||
// Check dates are ISO strings
|
||||
expect(result.snapshot.createdAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
|
||||
expect(result.snapshot.updatedAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
|
||||
});
|
||||
|
||||
it('should handle calculatorVersion in DTO', async () => {
|
||||
// Create a rating with calculatorVersion
|
||||
const rating = UserRating.create('user-1');
|
||||
const updated = rating.updateDriverRating(75);
|
||||
|
||||
mockRatingRepo.save = vi.fn().mockResolvedValue(updated);
|
||||
|
||||
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
||||
mockEventRepo as IRatingEventRepository,
|
||||
mockRatingRepo as IUserRatingRepository,
|
||||
);
|
||||
|
||||
const result = await useCase.execute({ userId: 'user-1' });
|
||||
|
||||
// Should have calculatorVersion
|
||||
expect(result.snapshot.calculatorVersion).toBeDefined();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user