186 lines
6.9 KiB
TypeScript
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();
|
|
});
|
|
});
|
|
}); |