code quality
Some checks failed
CI / lint-typecheck (pull_request) Failing after 12s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped

This commit is contained in:
2026-01-26 22:16:33 +01:00
parent f2bd80ccd3
commit 09632d004d
72 changed files with 1946 additions and 277 deletions

View File

@@ -1,5 +1,5 @@
import { InMemoryLeagueRepository } from '../../../adapters/leagues/persistence/inmemory/InMemoryLeagueRepository';
import { InMemoryDriverRepository } from '../../../adapters/drivers/persistence/inmemory/InMemoryDriverRepository';
import { InMemoryDriverRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { InMemoryEventPublisher } from '../../../adapters/events/InMemoryEventPublisher';
import type { Logger } from '../../../core/shared/domain/Logger';
import { CreateLeagueUseCase } from '../../../core/leagues/application/use-cases/CreateLeagueUseCase';
@@ -35,7 +35,7 @@ import { UnpublishLeagueSeasonScheduleUseCase } from '../../../core/racing/appli
import { RegisterForRaceUseCase } from '../../../core/racing/application/use-cases/RegisterForRaceUseCase';
import { WithdrawFromRaceUseCase } from '../../../core/racing/application/use-cases/WithdrawFromRaceUseCase';
import { GetLeagueStandingsUseCase } from '../../../core/racing/application/use-cases/GetLeagueStandingsUseCase';
import { InMemoryWalletRepository } from '../../../adapters/payments/persistence/inmemory/InMemoryWalletRepository';
import { InMemoryLeagueWalletRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryLeagueWalletRepository';
import { GetLeagueWalletUseCase } from '../../../core/racing/application/use-cases/GetLeagueWalletUseCase';
import { WithdrawFromLeagueWalletUseCase } from '../../../core/racing/application/use-cases/WithdrawFromLeagueWalletUseCase';
import { InMemoryTransactionRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryTransactionRepository';
@@ -79,15 +79,21 @@ export class LeaguesTestContext {
public readonly withdrawFromRaceUseCase: WithdrawFromRaceUseCase;
public readonly getLeagueStandingsUseCase: GetLeagueStandingsUseCase;
public readonly walletRepository: InMemoryWalletRepository;
public readonly walletRepository: InMemoryLeagueWalletRepository;
public readonly transactionRepository: InMemoryTransactionRepository;
public readonly getLeagueWalletUseCase: GetLeagueWalletUseCase;
public readonly withdrawFromLeagueWalletUseCase: WithdrawFromLeagueWalletUseCase;
constructor() {
this.logger = {
info: () => {},
debug: () => {},
warn: () => {},
error: () => {},
} as unknown as Logger;
this.leagueRepository = new InMemoryLeagueRepository();
this.driverRepository = new InMemoryDriverRepository();
this.driverRepository = new InMemoryDriverRepository(this.logger);
this.eventPublisher = new InMemoryEventPublisher();
this.createLeagueUseCase = new CreateLeagueUseCase(this.leagueRepository, this.eventPublisher);
@@ -101,12 +107,6 @@ export class LeaguesTestContext {
this.demoteAdminUseCase = new DemoteAdminUseCase(this.leagueRepository, this.driverRepository, this.eventPublisher);
this.removeMemberUseCase = new RemoveMemberUseCase(this.leagueRepository, this.driverRepository, this.eventPublisher);
this.logger = {
info: () => {},
debug: () => {},
warn: () => {},
error: () => {},
} as unknown as Logger;
this.racingLeagueRepository = new InMemoryRacingLeagueRepository(this.logger);
this.seasonRepository = new InMemorySeasonRepository(this.logger);
@@ -175,7 +175,7 @@ export class LeaguesTestContext {
this.racingDriverRepository,
);
this.walletRepository = new InMemoryWalletRepository(this.logger);
this.walletRepository = new InMemoryLeagueWalletRepository(this.logger);
this.transactionRepository = new InMemoryTransactionRepository(this.logger);
this.getLeagueWalletUseCase = new GetLeagueWalletUseCase(

View File

@@ -24,7 +24,6 @@ describe('League Creation - Success Path', () => {
raceDay: 'Saturday',
raceTime: '18:00',
tracks: ['Monza', 'Spa', 'Nürburgring'],
scoringSystem: { points: [25, 18, 15, 12, 10, 8, 6, 4, 2, 1] },
bonusPointsEnabled: true,
penaltiesEnabled: true,
protestsEnabled: true,
@@ -52,7 +51,7 @@ describe('League Creation - Success Path', () => {
expect(context.eventPublisher.getLeagueCreatedEventCount()).toBe(1);
const events = context.eventPublisher.getLeagueCreatedEvents();
expect(events[0].leagueId).toBe(result.id);
expect(events[0]!.leagueId).toBe(result.id);
});
it('should create a league with minimal configuration', async () => {

View File

@@ -15,7 +15,7 @@ describe('League Discovery - Search', () => {
const results = await context.leagueRepository.search('Formula');
expect(results).toHaveLength(1);
expect(results[0].name).toBe('Formula 1');
expect(results[0]!.name).toBe('Formula 1');
});
it('should find leagues by description', async () => {
@@ -24,6 +24,6 @@ describe('League Discovery - Search', () => {
const results = await context.leagueRepository.search('Competitive');
expect(results).toHaveLength(1);
expect(results[0].name).toBe('League A');
expect(results[0]!.name).toBe('League A');
});
});

View File

@@ -1,4 +1,5 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { Driver } from '@core/racing/domain/entities/Driver';
import { LeaguesTestContext } from '../LeaguesTestContext';
describe('League Roster - Actions', () => {
@@ -13,17 +14,13 @@ describe('League Roster - Actions', () => {
const league = await context.createLeague({ approvalRequired: false });
const driverId = 'driver-joiner';
context.driverRepository.addDriver({
id: driverId,
name: 'Joiner Driver',
rating: 1500,
rank: 100,
avatar: undefined,
starts: 0,
wins: 0,
podiums: 0,
leagues: 0
});
await context.driverRepository.create(Driver.rehydrate({
id: driverId,
iracingId: `${driverId}-iracing`,
name: 'Joiner Driver',
country: 'US',
joinedAt: new Date(),
}));
await context.joinLeagueUseCase.execute({ leagueId: league.id, driverId });
@@ -35,17 +32,13 @@ describe('League Roster - Actions', () => {
const league = await context.createLeague({ approvalRequired: true });
const driverId = 'driver-requester';
context.driverRepository.addDriver({
id: driverId,
name: 'Requester Driver',
rating: 1500,
rank: 100,
avatar: undefined,
starts: 0,
wins: 0,
podiums: 0,
leagues: 0
});
await context.driverRepository.create(Driver.rehydrate({
id: driverId,
iracingId: `${driverId}-iracing`,
name: 'Requester Driver',
country: 'US',
joinedAt: new Date(),
}));
await context.joinLeagueUseCase.execute({ leagueId: league.id, driverId });
@@ -58,21 +51,17 @@ describe('League Roster - Actions', () => {
const league = await context.createLeague({ ownerId, approvalRequired: true });
const driverId = 'driver-requester';
context.driverRepository.addDriver({
id: driverId,
name: 'Requester Driver',
rating: 1500,
rank: 100,
avatar: undefined,
starts: 0,
wins: 0,
podiums: 0,
leagues: 0
});
await context.driverRepository.create(Driver.rehydrate({
id: driverId,
iracingId: `${driverId}-iracing`,
name: 'Requester Driver',
country: 'US',
joinedAt: new Date(),
}));
await context.joinLeagueUseCase.execute({ leagueId: league.id, driverId });
const requests = await context.leagueRepository.getPendingRequests(league.id);
const requestId = requests[0].id;
const requestId = requests[0]!.id;
await context.approveMembershipRequestUseCase.execute({ leagueId: league.id, requestId });
@@ -88,21 +77,17 @@ describe('League Roster - Actions', () => {
const league = await context.createLeague({ ownerId, approvalRequired: true });
const driverId = 'driver-requester';
context.driverRepository.addDriver({
id: driverId,
name: 'Requester Driver',
rating: 1500,
rank: 100,
avatar: undefined,
starts: 0,
wins: 0,
podiums: 0,
leagues: 0
});
await context.driverRepository.create(Driver.rehydrate({
id: driverId,
iracingId: `${driverId}-iracing`,
name: 'Requester Driver',
country: 'US',
joinedAt: new Date(),
}));
await context.joinLeagueUseCase.execute({ leagueId: league.id, driverId });
const requests = await context.leagueRepository.getPendingRequests(league.id);
const requestId = requests[0].id;
const requestId = requests[0]!.id;
await context.rejectMembershipRequestUseCase.execute({ leagueId: league.id, requestId });

View File

@@ -74,7 +74,7 @@ describe('League Roster - Success Path', () => {
const result = await context.getLeagueRosterUseCase.execute({ leagueId: league.id });
expect(result.members).toHaveLength(1);
expect(result.members[0].role).toBe('owner');
expect(result.members[0]!.role).toBe('owner');
expect(result.stats.adminCount).toBe(1);
});
});

View File

@@ -11,14 +11,12 @@ describe('League Settings - Scoring', () => {
it('should retrieve league scoring configuration', async () => {
const league = await context.createLeague({
scoringSystem: { points: [10, 8, 6] },
bonusPointsEnabled: true,
penaltiesEnabled: true,
});
const result = await context.leagueRepository.findById(league.id);
expect(result?.scoringSystem).toEqual({ points: [10, 8, 6] });
expect(result?.bonusPointsEnabled).toBe(true);
expect(result?.penaltiesEnabled).toBe(true);
});
@@ -26,10 +24,9 @@ describe('League Settings - Scoring', () => {
it('should update league scoring configuration', async () => {
const league = await context.createLeague({ bonusPointsEnabled: false });
await context.leagueRepository.update(league.id, { bonusPointsEnabled: true, scoringSystem: { points: [25, 18] } });
await context.leagueRepository.update(league.id, { bonusPointsEnabled: true });
const updated = await context.leagueRepository.findById(league.id);
expect(updated?.bonusPointsEnabled).toBe(true);
expect(updated?.scoringSystem).toEqual({ points: [25, 18] });
});
});

View File

@@ -96,7 +96,7 @@ describe('League Sponsorships - GetSeasonSponsorshipsUseCase', () => {
track: 'Track 3',
car: 'GT3',
scheduledAt: new Date('2025-01-25T20:00:00.000Z'),
status: 'planned',
status: 'scheduled',
}),
);
};

View File

@@ -53,12 +53,12 @@ describe('GetLeagueStandings', () => {
expect(result.isOk()).toBe(true);
const data = result.unwrap();
expect(data.standings).toHaveLength(2);
expect(data.standings[0].driverId).toBe(driver1Id);
expect(data.standings[0].points).toBe(100);
expect(data.standings[0].rank).toBe(1);
expect(data.standings[1].driverId).toBe(driver2Id);
expect(data.standings[1].points).toBe(80);
expect(data.standings[1].rank).toBe(2);
expect(data.standings[0]!.driverId).toBe(driver1Id);
expect(data.standings[0]!.points).toBe(100);
expect(data.standings[0]!.rank).toBe(1);
expect(data.standings[1]!.driverId).toBe(driver2Id);
expect(data.standings[1]!.points).toBe(80);
expect(data.standings[1]!.rank).toBe(2);
});
it('should retrieve standings with minimal driver statistics', async () => {

View File

@@ -63,6 +63,7 @@ describe('StandingsCalculation', () => {
fastestLap: 120000,
incidents: 0,
startPosition: 1,
points: 25,
}));
await context.resultRepository.create(Result.create({
@@ -73,6 +74,7 @@ describe('StandingsCalculation', () => {
fastestLap: 121000,
incidents: 2,
startPosition: 5,
points: 15,
}));
// When: Standings are recalculated

View File

@@ -107,7 +107,7 @@ describe('League Stewarding - GetLeagueStewarding', () => {
reason: 'Contact on corner entry',
issuedBy: 'steward-1',
status: params.status || 'pending',
...(params.raceId && { raceId: params.raceId }),
raceId: params.raceId || 'default-race-id',
});
await context.penaltyRepository.create(penalty);

View File

@@ -52,7 +52,6 @@ describe('League Stewarding - StewardingManagement', () => {
context.protestRepository,
context.raceRepository,
context.leagueMembershipRepository,
context.racingDriverRepository,
);
requestProtestDefenseUseCase = new RequestProtestDefenseUseCase(