wip
This commit is contained in:
@@ -10,6 +10,10 @@ import type {
|
||||
class FakeDashboardOverviewPresenter implements IDashboardOverviewPresenter {
|
||||
viewModel: DashboardOverviewViewModel | null = null;
|
||||
|
||||
reset(): void {
|
||||
this.viewModel = null;
|
||||
}
|
||||
|
||||
present(viewModel: DashboardOverviewViewModel): void {
|
||||
this.viewModel = viewModel;
|
||||
}
|
||||
@@ -201,11 +205,10 @@ describe('GetDashboardOverviewUseCase', () => {
|
||||
socialRepository,
|
||||
imageService,
|
||||
getDriverStats,
|
||||
presenter,
|
||||
);
|
||||
|
||||
// When
|
||||
await useCase.execute({ driverId });
|
||||
await useCase.execute({ driverId }, presenter);
|
||||
|
||||
const viewModel = presenter.getViewModel();
|
||||
expect(viewModel).not.toBeNull();
|
||||
@@ -389,11 +392,10 @@ describe('GetDashboardOverviewUseCase', () => {
|
||||
socialRepository,
|
||||
imageService,
|
||||
getDriverStats,
|
||||
presenter,
|
||||
);
|
||||
|
||||
// When
|
||||
await useCase.execute({ driverId });
|
||||
await useCase.execute({ driverId }, presenter);
|
||||
|
||||
const viewModel = presenter.getViewModel();
|
||||
expect(viewModel).not.toBeNull();
|
||||
@@ -496,11 +498,10 @@ describe('GetDashboardOverviewUseCase', () => {
|
||||
socialRepository,
|
||||
imageService,
|
||||
getDriverStats,
|
||||
presenter,
|
||||
);
|
||||
|
||||
// When
|
||||
await useCase.execute({ driverId });
|
||||
await useCase.execute({ driverId }, presenter);
|
||||
|
||||
const viewModel = presenter.getViewModel();
|
||||
expect(viewModel).not.toBeNull();
|
||||
|
||||
@@ -6,7 +6,6 @@ import type { IDriverRepository } from '@gridpilot/racing/domain/repositories/ID
|
||||
import type { IRaceRegistrationRepository } from '@gridpilot/racing/domain/repositories/IRaceRegistrationRepository';
|
||||
import type { IResultRepository } from '@gridpilot/racing/domain/repositories/IResultRepository';
|
||||
import type { ILeagueMembershipRepository } from '@gridpilot/racing/domain/repositories/ILeagueMembershipRepository';
|
||||
import type { LeagueMembership } from '@gridpilot/racing/domain/entities/LeagueMembership';
|
||||
import type { DriverRatingProvider } from '@gridpilot/racing/application/ports/DriverRatingProvider';
|
||||
import type { IImageServicePort } from '@gridpilot/racing/application/ports/IImageServicePort';
|
||||
import type {
|
||||
@@ -17,6 +16,8 @@ import type {
|
||||
import { Race } from '@gridpilot/racing/domain/entities/Race';
|
||||
import { League } from '@gridpilot/racing/domain/entities/League';
|
||||
import { Result } from '@gridpilot/racing/domain/entities/Result';
|
||||
import { Driver } from '@gridpilot/racing/domain/entities/Driver';
|
||||
import { LeagueMembership } from '@gridpilot/racing/domain/entities/LeagueMembership';
|
||||
import { GetRaceDetailUseCase } from '@gridpilot/racing/application/use-cases/GetRaceDetailUseCase';
|
||||
import { CancelRaceUseCase } from '@gridpilot/racing/application/use-cases/CancelRaceUseCase';
|
||||
|
||||
@@ -118,31 +119,39 @@ class InMemoryLeagueRepository implements ILeagueRepository {
|
||||
async exists(id: string): Promise<boolean> {
|
||||
return this.leagues.has(id);
|
||||
}
|
||||
|
||||
async searchByName(): Promise<League[]> {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
class InMemoryDriverRepository implements IDriverRepository {
|
||||
private drivers = new Map<string, { id: string; name: string; country: string }>();
|
||||
|
||||
private drivers = new Map<string, Driver>();
|
||||
|
||||
constructor(drivers: Array<{ id: string; name: string; country: string }>) {
|
||||
for (const driver of drivers) {
|
||||
this.drivers.set(driver.id, {
|
||||
...driver,
|
||||
});
|
||||
this.drivers.set(driver.id, Driver.create({
|
||||
id: driver.id,
|
||||
iracingId: `iracing-${driver.id}`,
|
||||
name: driver.name,
|
||||
country: driver.country,
|
||||
joinedAt: new Date('2024-01-01'),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
async findById(id: string): Promise<{ id: string; name: string; country: string } | null> {
|
||||
|
||||
async findById(id: string): Promise<Driver | null> {
|
||||
return this.drivers.get(id) ?? null;
|
||||
}
|
||||
|
||||
async findAll(): Promise<Array<{ id: string; name: string; country: string }>> {
|
||||
|
||||
async findAll(): Promise<Driver[]> {
|
||||
return [...this.drivers.values()];
|
||||
}
|
||||
|
||||
async findByIds(ids: string[]): Promise<Array<{ id: string; name: string; country: string }>> {
|
||||
|
||||
async findByIds(ids: string[]): Promise<Driver[]> {
|
||||
return ids
|
||||
.map(id => this.drivers.get(id))
|
||||
.filter((d): d is { id: string; name: string; country: string } => !!d);
|
||||
.filter((d): d is Driver => !!d);
|
||||
}
|
||||
|
||||
async create(): Promise<any> {
|
||||
@@ -160,6 +169,14 @@ class InMemoryDriverRepository implements IDriverRepository {
|
||||
async exists(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
async findByIRacingId(): Promise<Driver | null> {
|
||||
return null;
|
||||
}
|
||||
|
||||
async existsByIRacingId(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class InMemoryRaceRegistrationRepository implements IRaceRegistrationRepository {
|
||||
@@ -365,6 +382,10 @@ class FakeRaceDetailPresenter implements IRaceDetailPresenter {
|
||||
getViewModel(): RaceDetailViewModel | null {
|
||||
return this.viewModel;
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.viewModel = null;
|
||||
}
|
||||
}
|
||||
|
||||
describe('GetRaceDetailUseCase', () => {
|
||||
@@ -405,13 +426,13 @@ describe('GetRaceDetailUseCase', () => {
|
||||
const resultRepo = new InMemoryResultRepository([]);
|
||||
|
||||
const membershipRepo = new InMemoryLeagueMembershipRepository();
|
||||
membershipRepo.seedMembership({
|
||||
membershipRepo.seedMembership(LeagueMembership.create({
|
||||
leagueId: league.id,
|
||||
driverId,
|
||||
role: 'member',
|
||||
status: 'active',
|
||||
joinedAt: new Date('2024-01-01'),
|
||||
});
|
||||
}));
|
||||
|
||||
const ratingProvider = new TestDriverRatingProvider();
|
||||
ratingProvider.seed(driverId, 1500);
|
||||
@@ -429,11 +450,10 @@ describe('GetRaceDetailUseCase', () => {
|
||||
membershipRepo,
|
||||
ratingProvider,
|
||||
imageService,
|
||||
presenter,
|
||||
);
|
||||
|
||||
// When (execute the query for the current driver)
|
||||
await useCase.execute({ raceId: race.id, driverId });
|
||||
await useCase.execute({ raceId: race.id, driverId }, presenter);
|
||||
|
||||
const viewModel = presenter.getViewModel();
|
||||
expect(viewModel).not.toBeNull();
|
||||
@@ -502,13 +522,13 @@ describe('GetRaceDetailUseCase', () => {
|
||||
|
||||
const resultRepo = new InMemoryResultRepository([resultEntity]);
|
||||
const membershipRepo = new InMemoryLeagueMembershipRepository();
|
||||
membershipRepo.seedMembership({
|
||||
membershipRepo.seedMembership(LeagueMembership.create({
|
||||
leagueId: league.id,
|
||||
driverId,
|
||||
role: 'member',
|
||||
status: 'active',
|
||||
joinedAt: new Date('2024-01-01'),
|
||||
});
|
||||
}));
|
||||
|
||||
const ratingProvider = new TestDriverRatingProvider();
|
||||
ratingProvider.seed(driverId, 2000);
|
||||
@@ -525,11 +545,10 @@ describe('GetRaceDetailUseCase', () => {
|
||||
membershipRepo,
|
||||
ratingProvider,
|
||||
imageService,
|
||||
presenter,
|
||||
);
|
||||
|
||||
// When (executing the query for the completed race)
|
||||
await useCase.execute({ raceId: race.id, driverId });
|
||||
await useCase.execute({ raceId: race.id, driverId }, presenter);
|
||||
|
||||
const viewModel = presenter.getViewModel();
|
||||
expect(viewModel).not.toBeNull();
|
||||
@@ -566,11 +585,10 @@ describe('GetRaceDetailUseCase', () => {
|
||||
membershipRepo,
|
||||
ratingProvider,
|
||||
imageService,
|
||||
presenter,
|
||||
);
|
||||
|
||||
// When
|
||||
await useCase.execute({ raceId: 'missing-race', driverId: 'driver-x' });
|
||||
await useCase.execute({ raceId: 'missing-race', driverId: 'driver-x' }, presenter);
|
||||
|
||||
const viewModel = presenter.getViewModel();
|
||||
// Then
|
||||
|
||||
@@ -20,6 +20,10 @@ import type {
|
||||
class FakeRaceResultsDetailPresenter implements IRaceResultsDetailPresenter {
|
||||
viewModel: RaceResultsDetailViewModel | null = null;
|
||||
|
||||
reset(): void {
|
||||
this.viewModel = null;
|
||||
}
|
||||
|
||||
present(viewModel: RaceResultsDetailViewModel): RaceResultsDetailViewModel {
|
||||
this.viewModel = viewModel;
|
||||
return viewModel;
|
||||
@@ -354,7 +358,7 @@ describe('GetRaceResultsDetailUseCase', () => {
|
||||
);
|
||||
|
||||
// When executing the query
|
||||
await useCase.execute({ raceId: race.id });
|
||||
await useCase.execute({ raceId: race.id }, presenter);
|
||||
|
||||
const viewModel = presenter.getViewModel();
|
||||
expect(viewModel).not.toBeNull();
|
||||
@@ -464,7 +468,7 @@ describe('GetRaceResultsDetailUseCase', () => {
|
||||
);
|
||||
|
||||
// When
|
||||
await useCase.execute({ raceId: race.id });
|
||||
await useCase.execute({ raceId: race.id }, presenter);
|
||||
|
||||
const viewModel = presenter.getViewModel();
|
||||
expect(viewModel).not.toBeNull();
|
||||
@@ -529,7 +533,7 @@ describe('GetRaceResultsDetailUseCase', () => {
|
||||
);
|
||||
|
||||
// When
|
||||
await useCase.execute({ raceId: 'missing-race' });
|
||||
await useCase.execute({ raceId: 'missing-race' }, presenter);
|
||||
|
||||
const viewModel = presenter.getViewModel();
|
||||
expect(viewModel).not.toBeNull();
|
||||
|
||||
@@ -56,6 +56,7 @@ import type {
|
||||
DriverTeamResultDTO,
|
||||
DriverTeamViewModel,
|
||||
} from '@gridpilot/racing/application/presenters/IDriverTeamPresenter';
|
||||
import type { RaceRegistrationsResultDTO } from '@gridpilot/racing/application/presenters/IRaceRegistrationsPresenter';
|
||||
|
||||
/**
|
||||
* Simple in-memory fakes mirroring current alpha behavior.
|
||||
@@ -179,16 +180,14 @@ class TestRaceRegistrationsPresenter implements IRaceRegistrationsPresenter {
|
||||
raceId: string | null = null;
|
||||
driverIds: string[] = [];
|
||||
|
||||
// Accepts either the legacy (raceId, driverIds) shape or the new (driverIds) shape
|
||||
present(raceIdOrDriverIds: string | string[], driverIds?: string[]): void {
|
||||
if (Array.isArray(raceIdOrDriverIds) && driverIds == null) {
|
||||
this.raceId = null;
|
||||
this.driverIds = raceIdOrDriverIds;
|
||||
return;
|
||||
}
|
||||
reset(): void {
|
||||
this.raceId = null;
|
||||
this.driverIds = [];
|
||||
}
|
||||
|
||||
this.raceId = raceIdOrDriverIds as string;
|
||||
this.driverIds = driverIds ?? [];
|
||||
present(input: RaceRegistrationsResultDTO): void {
|
||||
this.driverIds = input.registeredDriverIds;
|
||||
this.raceId = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,6 +317,10 @@ class InMemoryTeamMembershipRepository implements ITeamMembershipRepository {
|
||||
getAllJoinRequests(): TeamJoinRequest[] {
|
||||
return [...this.joinRequests];
|
||||
}
|
||||
|
||||
async countByTeamId(teamId: string): Promise<number> {
|
||||
return this.memberships.filter((m) => m.teamId === teamId).length;
|
||||
}
|
||||
}
|
||||
|
||||
describe('Racing application use-cases - registrations', () => {
|
||||
@@ -342,10 +345,7 @@ describe('Racing application use-cases - registrations', () => {
|
||||
driverRegistrationPresenter,
|
||||
);
|
||||
raceRegistrationsPresenter = new TestRaceRegistrationsPresenter();
|
||||
getRaceRegistrations = new GetRaceRegistrationsUseCase(
|
||||
registrationRepo,
|
||||
raceRegistrationsPresenter,
|
||||
);
|
||||
getRaceRegistrations = new GetRaceRegistrationsUseCase(registrationRepo);
|
||||
});
|
||||
|
||||
it('registers an active league member for a race and tracks registration', async () => {
|
||||
@@ -362,7 +362,7 @@ describe('Racing application use-cases - registrations', () => {
|
||||
expect(driverRegistrationPresenter.raceId).toBe(raceId);
|
||||
expect(driverRegistrationPresenter.driverId).toBe(driverId);
|
||||
|
||||
await getRaceRegistrations.execute({ raceId });
|
||||
await getRaceRegistrations.execute({ raceId }, raceRegistrationsPresenter);
|
||||
expect(raceRegistrationsPresenter.driverIds).toContain(driverId);
|
||||
});
|
||||
|
||||
@@ -389,7 +389,7 @@ describe('Racing application use-cases - registrations', () => {
|
||||
await isDriverRegistered.execute({ raceId, driverId });
|
||||
expect(driverRegistrationPresenter.isRegistered).toBe(false);
|
||||
|
||||
await getRaceRegistrations.execute({ raceId });
|
||||
await getRaceRegistrations.execute({ raceId }, raceRegistrationsPresenter);
|
||||
expect(raceRegistrationsPresenter.driverIds).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -458,8 +458,16 @@ describe('Racing application use-cases - teams', () => {
|
||||
class TestTeamDetailsPresenter implements ITeamDetailsPresenter {
|
||||
viewModel: any = null;
|
||||
|
||||
present(team: any, membership: any, driverId: string): void {
|
||||
this.viewModel = { team, membership, driverId };
|
||||
reset(): void {
|
||||
this.viewModel = null;
|
||||
}
|
||||
|
||||
present(input: any): void {
|
||||
this.viewModel = input;
|
||||
}
|
||||
|
||||
getViewModel(): any {
|
||||
return this.viewModel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -744,7 +752,7 @@ describe('Racing application use-cases - teams', () => {
|
||||
updatedBy: ownerId,
|
||||
});
|
||||
|
||||
await getTeamDetailsUseCase.execute(created.team.id, ownerId);
|
||||
await getTeamDetailsUseCase.execute({ teamId: created.team.id, driverId: ownerId }, teamDetailsPresenter);
|
||||
|
||||
expect(teamDetailsPresenter.viewModel.team.name).toBe('Updated Name');
|
||||
expect(teamDetailsPresenter.viewModel.team.description).toBe('Updated description');
|
||||
|
||||
Reference in New Issue
Block a user