team rating
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Tests for GetTeamRatingsSummaryQuery
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, vi, Mock } from 'vitest';
|
||||
import { GetTeamRatingsSummaryQuery, GetTeamRatingsSummaryQueryHandler } from './GetTeamRatingsSummaryQuery';
|
||||
import { TeamRatingSnapshot } from '../../domain/services/TeamRatingSnapshotCalculator';
|
||||
import { TeamRatingValue } from '../../domain/value-objects/TeamRatingValue';
|
||||
import { TeamRatingEvent } from '../../domain/entities/TeamRatingEvent';
|
||||
import { TeamRatingEventId } from '../../domain/value-objects/TeamRatingEventId';
|
||||
import { TeamRatingDimensionKey } from '../../domain/value-objects/TeamRatingDimensionKey';
|
||||
import { TeamRatingDelta } from '../../domain/value-objects/TeamRatingDelta';
|
||||
|
||||
describe('GetTeamRatingsSummaryQuery', () => {
|
||||
let mockTeamRatingRepo: any;
|
||||
let mockRatingEventRepo: any;
|
||||
let handler: GetTeamRatingsSummaryQueryHandler;
|
||||
|
||||
beforeEach(() => {
|
||||
mockTeamRatingRepo = {
|
||||
findByTeamId: vi.fn(),
|
||||
};
|
||||
mockRatingEventRepo = {
|
||||
getAllByTeamId: vi.fn(),
|
||||
};
|
||||
|
||||
handler = new GetTeamRatingsSummaryQueryHandler(
|
||||
mockTeamRatingRepo,
|
||||
mockRatingEventRepo
|
||||
);
|
||||
});
|
||||
|
||||
describe('execute', () => {
|
||||
it('should return summary with platform ratings', async () => {
|
||||
const teamId = 'team-123';
|
||||
|
||||
// Mock team rating snapshot
|
||||
const snapshot: TeamRatingSnapshot = {
|
||||
teamId,
|
||||
driving: TeamRatingValue.create(75),
|
||||
adminTrust: TeamRatingValue.create(60),
|
||||
overall: 70.5,
|
||||
lastUpdated: new Date('2024-01-01T10:00:00Z'),
|
||||
eventCount: 5,
|
||||
};
|
||||
mockTeamRatingRepo.findByTeamId.mockResolvedValue(snapshot);
|
||||
|
||||
// Mock rating events
|
||||
const event = TeamRatingEvent.create({
|
||||
id: TeamRatingEventId.generate(),
|
||||
teamId,
|
||||
dimension: TeamRatingDimensionKey.create('driving'),
|
||||
delta: TeamRatingDelta.create(10),
|
||||
occurredAt: new Date('2024-01-01T10:00:00Z'),
|
||||
createdAt: new Date('2024-01-01T10:00:00Z'),
|
||||
source: { type: 'race', id: 'race-123' },
|
||||
reason: { code: 'RACE_FINISH' },
|
||||
visibility: { public: true },
|
||||
version: 1,
|
||||
});
|
||||
mockRatingEventRepo.getAllByTeamId.mockResolvedValue([event]);
|
||||
|
||||
const query: GetTeamRatingsSummaryQuery = { teamId };
|
||||
const result = await handler.execute(query);
|
||||
|
||||
expect(result.teamId).toBe(teamId);
|
||||
expect(result.platform.driving.value).toBe(75);
|
||||
expect(result.platform.adminTrust.value).toBe(60);
|
||||
expect(result.platform.overall).toBe(70.5);
|
||||
expect(result.lastRatingEventAt).toBe('2024-01-01T10:00:00.000Z');
|
||||
});
|
||||
|
||||
it('should handle missing team rating gracefully', async () => {
|
||||
const teamId = 'team-123';
|
||||
|
||||
mockTeamRatingRepo.findByTeamId.mockResolvedValue(null);
|
||||
mockRatingEventRepo.getAllByTeamId.mockResolvedValue([]);
|
||||
|
||||
const query: GetTeamRatingsSummaryQuery = { teamId };
|
||||
const result = await handler.execute(query);
|
||||
|
||||
expect(result.teamId).toBe(teamId);
|
||||
expect(result.platform.driving.value).toBe(0);
|
||||
expect(result.platform.adminTrust.value).toBe(0);
|
||||
expect(result.platform.overall).toBe(0);
|
||||
expect(result.lastRatingEventAt).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle multiple events and find latest', async () => {
|
||||
const teamId = 'team-123';
|
||||
|
||||
const snapshot: TeamRatingSnapshot = {
|
||||
teamId,
|
||||
driving: TeamRatingValue.create(80),
|
||||
adminTrust: TeamRatingValue.create(70),
|
||||
overall: 77,
|
||||
lastUpdated: new Date('2024-01-02T10:00:00Z'),
|
||||
eventCount: 10,
|
||||
};
|
||||
mockTeamRatingRepo.findByTeamId.mockResolvedValue(snapshot);
|
||||
|
||||
// Multiple events with different timestamps
|
||||
const events = [
|
||||
TeamRatingEvent.create({
|
||||
id: TeamRatingEventId.generate(),
|
||||
teamId,
|
||||
dimension: TeamRatingDimensionKey.create('driving'),
|
||||
delta: TeamRatingDelta.create(5),
|
||||
occurredAt: new Date('2024-01-01T08:00:00Z'),
|
||||
createdAt: new Date('2024-01-01T08:00:00Z'),
|
||||
source: { type: 'race', id: 'race-1' },
|
||||
reason: { code: 'RACE_FINISH' },
|
||||
visibility: { public: true },
|
||||
version: 1,
|
||||
}),
|
||||
TeamRatingEvent.create({
|
||||
id: TeamRatingEventId.generate(),
|
||||
teamId,
|
||||
dimension: TeamRatingDimensionKey.create('driving'),
|
||||
delta: TeamRatingDelta.create(10),
|
||||
occurredAt: new Date('2024-01-02T10:00:00Z'),
|
||||
createdAt: new Date('2024-01-02T10:00:00Z'),
|
||||
source: { type: 'race', id: 'race-2' },
|
||||
reason: { code: 'RACE_FINISH' },
|
||||
visibility: { public: true },
|
||||
version: 1,
|
||||
}),
|
||||
];
|
||||
mockRatingEventRepo.getAllByTeamId.mockResolvedValue(events);
|
||||
|
||||
const query: GetTeamRatingsSummaryQuery = { teamId };
|
||||
const result = await handler.execute(query);
|
||||
|
||||
expect(result.lastRatingEventAt).toBe('2024-01-02T10:00:00.000Z');
|
||||
});
|
||||
|
||||
it('should calculate confidence and sampleSize from event count', async () => {
|
||||
const teamId = 'team-123';
|
||||
|
||||
const snapshot: TeamRatingSnapshot = {
|
||||
teamId,
|
||||
driving: TeamRatingValue.create(65),
|
||||
adminTrust: TeamRatingValue.create(55),
|
||||
overall: 62,
|
||||
lastUpdated: new Date('2024-01-01T10:00:00Z'),
|
||||
eventCount: 8,
|
||||
};
|
||||
mockTeamRatingRepo.findByTeamId.mockResolvedValue(snapshot);
|
||||
mockRatingEventRepo.getAllByTeamId.mockResolvedValue([]);
|
||||
|
||||
const query: GetTeamRatingsSummaryQuery = { teamId };
|
||||
const result = await handler.execute(query);
|
||||
|
||||
// Confidence should be min(1, eventCount/10) = 0.8
|
||||
expect(result.platform.driving.confidence).toBe(0.8);
|
||||
expect(result.platform.driving.sampleSize).toBe(8);
|
||||
expect(result.platform.adminTrust.confidence).toBe(0.8);
|
||||
expect(result.platform.adminTrust.sampleSize).toBe(8);
|
||||
});
|
||||
|
||||
it('should handle empty events array', async () => {
|
||||
const teamId = 'team-123';
|
||||
|
||||
const snapshot: TeamRatingSnapshot = {
|
||||
teamId,
|
||||
driving: TeamRatingValue.create(50),
|
||||
adminTrust: TeamRatingValue.create(50),
|
||||
overall: 50,
|
||||
lastUpdated: new Date('2024-01-01T10:00:00Z'),
|
||||
eventCount: 0,
|
||||
};
|
||||
mockTeamRatingRepo.findByTeamId.mockResolvedValue(snapshot);
|
||||
mockRatingEventRepo.getAllByTeamId.mockResolvedValue([]);
|
||||
|
||||
const query: GetTeamRatingsSummaryQuery = { teamId };
|
||||
const result = await handler.execute(query);
|
||||
|
||||
expect(result.platform.driving.confidence).toBe(0);
|
||||
expect(result.platform.driving.sampleSize).toBe(0);
|
||||
expect(result.platform.driving.trend).toBe('stable');
|
||||
expect(result.lastRatingEventAt).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user