Files
gridpilot.gg/core/racing/application/queries/GetTeamRatingsSummaryQuery.test.ts
2026-01-16 19:46:49 +01:00

186 lines
6.9 KiB
TypeScript

/**
* Tests for GetTeamRatingsSummaryQuery
*/
import { beforeEach, describe, expect, it, vi, type Mock } from 'vitest';
import { TeamRatingEvent } from '../../domain/entities/TeamRatingEvent';
import type { TeamRatingEventRepository } from '../../domain/repositories/TeamRatingEventRepository';
import type { TeamRatingRepository } from '../../domain/repositories/TeamRatingRepository';
import { TeamRatingSnapshot } from '../../domain/services/TeamRatingSnapshotCalculator';
import { TeamRatingDelta } from '../../domain/value-objects/TeamRatingDelta';
import { TeamRatingDimensionKey } from '../../domain/value-objects/TeamRatingDimensionKey';
import { TeamRatingEventId } from '../../domain/value-objects/TeamRatingEventId';
import { TeamRatingValue } from '../../domain/value-objects/TeamRatingValue';
import { GetTeamRatingsSummaryQuery, GetTeamRatingsSummaryQueryHandler } from './GetTeamRatingsSummaryQuery';
describe('GetTeamRatingsSummaryQuery', () => {
let mockTeamRatingRepo: { findByTeamId: Mock };
let mockRatingEventRepo: { getAllByTeamId: Mock };
let handler: GetTeamRatingsSummaryQueryHandler;
beforeEach(() => {
mockTeamRatingRepo = {
findByTeamId: vi.fn(),
};
mockRatingEventRepo = {
getAllByTeamId: vi.fn(),
};
handler = new GetTeamRatingsSummaryQueryHandler(
mockTeamRatingRepo as unknown as TeamRatingRepository,
mockRatingEventRepo as unknown as TeamRatingEventRepository
);
});
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();
});
});
});