website refactor

This commit is contained in:
2026-01-21 00:53:29 +01:00
parent 4516427a19
commit 5f3712e5ab
10 changed files with 85 additions and 201 deletions

View File

@@ -7,6 +7,7 @@
import type { ResultRepository } from '../../domain/repositories/ResultRepository';
import type { StandingRepository } from '../../domain/repositories/StandingRepository';
import type { DriverStatsRepository } from '../../domain/repositories/DriverStatsRepository';
import type { Logger } from '@core/shared/domain/Logger';
export interface DriverStats {
@@ -29,11 +30,12 @@ export class DriverStatsUseCase {
constructor(
_resultRepository: ResultRepository,
_standingRepository: StandingRepository,
private readonly _driverStatsRepository: DriverStatsRepository,
private readonly _logger: Logger,
) {}
async getDriverStats(driverId: string): Promise<DriverStats | null> {
this._logger.debug(`Getting stats for driver ${driverId}`);
return null;
return this._driverStatsRepository.getDriverStats(driverId);
}
}

View File

@@ -1,138 +0,0 @@
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
import { Team } from '../../domain/entities/Team';
import {
GetTeamsLeaderboardUseCase,
type GetTeamsLeaderboardErrorCode,
type GetTeamsLeaderboardInput
} from './GetTeamsLeaderboardUseCase';
import { Logger } from 'vite';
import { TeamMembershipRepository } from '../../domain/repositories/TeamMembershipRepository';
import { TeamRepository } from '../../domain/repositories/TeamRepository';
describe('GetTeamsLeaderboardUseCase', () => {
let useCase: GetTeamsLeaderboardUseCase;
let teamRepository: {
findAll: Mock;
findById: Mock;
};
let teamMembershipRepository: {
getTeamMembers: Mock;
};
let getDriverStats: Mock;
let logger: {
debug: Mock;
info: Mock;
warn: Mock;
error: Mock;
};
beforeEach(() => {
teamRepository = {
findAll: vi.fn(),
findById: vi.fn(),
};
teamMembershipRepository = {
getTeamMembers: vi.fn(),
};
getDriverStats = vi.fn();
logger = {
debug: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
};
useCase = new GetTeamsLeaderboardUseCase(
teamRepository as unknown as TeamRepository,
teamMembershipRepository as unknown as TeamMembershipRepository,
getDriverStats as unknown as (driverId: string) => { rating: number | null; wins: number; totalRaces: number } | null,
logger as unknown as Logger
);
});
it('should return teams leaderboard with calculated stats', async () => {
const team1 = Team.create({
id: 'team-1',
name: 'Team Alpha',
tag: 'TA',
description: 'Description 1',
ownerId: 'owner-1',
leagues: [],
});
const team2 = Team.create({
id: 'team-2',
name: 'Team Beta',
tag: 'TB',
description: 'Description 2',
ownerId: 'owner-2',
leagues: [],
});
const memberships1 = [
{ teamId: 'team-1', driverId: 'driver-1', role: 'driver' as const, status: 'active' as const, joinedAt: new Date() },
{ teamId: 'team-1', driverId: 'driver-2', role: 'driver' as const, status: 'active' as const, joinedAt: new Date() },
];
const memberships2 = [
{ teamId: 'team-2', driverId: 'driver-3', role: 'driver' as const, status: 'active' as const, joinedAt: new Date() },
];
teamRepository.findAll.mockResolvedValue([team1, team2]);
teamMembershipRepository.getTeamMembers.mockImplementation((teamId: string) => {
if (teamId === 'team-1') return Promise.resolve(memberships1);
if (teamId === 'team-2') return Promise.resolve(memberships2);
return Promise.resolve([]);
});
getDriverStats.mockImplementation((driverId: string) => {
if (driverId === 'driver-1') return { rating: 1500, wins: 5, totalRaces: 10 };
if (driverId === 'driver-2') return { rating: 1600, wins: 3, totalRaces: 8 };
if (driverId === 'driver-3') return { rating: null, wins: 2, totalRaces: 5 };
return null;
});
const input: GetTeamsLeaderboardInput = { leagueId: 'league-1' };
const result = await useCase.execute(input);
expect(result.isOk()).toBe(true);
const presented = result.unwrap();
expect(presented.recruitingCount).toBe(2); // both teams are recruiting
expect(presented.items).toHaveLength(2);
expect(presented.items[0]).toMatchObject({
team: team1,
memberCount: 2,
rating: 1550, // (1500 + 1600) / 2
totalWins: 8,
totalRaces: 18,
performanceLevel: expect.any(String),
isRecruiting: true,
});
expect(presented.items[1]).toMatchObject({
team: team2,
memberCount: 1,
rating: null,
totalWins: 2,
totalRaces: 5,
performanceLevel: expect.any(String),
isRecruiting: true,
});
});
it('should return error on repository failure', async () => {
const error = new Error('Repository error');
teamRepository.findAll.mockRejectedValue(error);
const input: GetTeamsLeaderboardInput = { leagueId: 'league-1' };
const result = await useCase.execute(input);
expect(result.isErr()).toBe(true);
const err = result.unwrapErr() as ApplicationErrorCode<
GetTeamsLeaderboardErrorCode,
{ message: string }
>;
expect(err.code).toBe('REPOSITORY_ERROR');
expect(err.details.message).toBe('Repository error');
});
});

View File

@@ -7,6 +7,7 @@
import type { StandingRepository } from '../../domain/repositories/StandingRepository';
import type { DriverRepository } from '../../domain/repositories/DriverRepository';
import type { DriverStatsRepository } from '../../domain/repositories/DriverStatsRepository';
import type { Logger } from '@core/shared/domain/Logger';
export interface DriverRanking {
@@ -21,11 +22,25 @@ export class RankingUseCase {
constructor(
_standingRepository: StandingRepository,
_driverRepository: DriverRepository,
private readonly _driverStatsRepository: DriverStatsRepository,
private readonly _logger: Logger,
) {}
async getAllDriverRankings(): Promise<DriverRanking[]> {
this._logger.debug('Getting all driver rankings');
return [];
const allStats = await this._driverStatsRepository.getAllStats();
const rankings: DriverRanking[] = [];
allStats.forEach((stats, driverId) => {
rankings.push({
driverId,
rating: stats.rating,
wins: stats.wins,
totalRaces: stats.totalRaces,
overallRank: stats.overallRank,
});
});
return rankings;
}
}