fix seeds
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { Driver } from '@core/racing/domain/entities/Driver';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
export class RacingDriverFactory {
|
||||
constructor(
|
||||
@@ -7,7 +8,7 @@ export class RacingDriverFactory {
|
||||
) {}
|
||||
|
||||
create(): Driver[] {
|
||||
const countries = ['DE', 'NL', 'FR', 'GB', 'US', 'CA', 'SE', 'NO', 'IT', 'ES'] as const;
|
||||
const countries = ['DE', 'NL', 'FR', 'GB', 'US', 'CA', 'SE', 'NO', 'IT', 'ES', 'AU', 'BR', 'JP', 'KR', 'RU', 'PL', 'CZ', 'HU', 'AT', 'CH'] as const;
|
||||
|
||||
return Array.from({ length: this.driverCount }, (_, idx) => {
|
||||
const i = idx + 1;
|
||||
@@ -15,15 +16,11 @@ export class RacingDriverFactory {
|
||||
return Driver.create({
|
||||
id: `driver-${i}`,
|
||||
iracingId: String(100000 + i),
|
||||
name: `Driver ${i}`,
|
||||
country: countries[idx % countries.length]!,
|
||||
bio: `Demo driver #${i} seeded for in-memory mode.`,
|
||||
joinedAt: this.addDays(this.baseDate, -90 + i),
|
||||
name: faker.person.fullName(),
|
||||
country: faker.helpers.arrayElement(countries),
|
||||
bio: faker.lorem.sentences(2),
|
||||
joinedAt: faker.date.past({ years: 2, refDate: this.baseDate }),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private addDays(date: Date, days: number): Date {
|
||||
return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
|
||||
}
|
||||
}
|
||||
@@ -1,100 +1,58 @@
|
||||
import { League } from '@core/racing/domain/entities/League';
|
||||
import { Driver } from '@core/racing/domain/entities/Driver';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
export class RacingLeagueFactory {
|
||||
constructor(private readonly baseDate: Date) {}
|
||||
constructor(
|
||||
private readonly baseDate: Date,
|
||||
private readonly drivers: Driver[],
|
||||
) {}
|
||||
|
||||
create(): League[] {
|
||||
const createdAtBase = this.baseDate;
|
||||
const leagueCount = 20;
|
||||
const pointsSystems = ['f1-2024', 'indycar', 'custom'] as const;
|
||||
const qualifyingFormats = ['open', 'single-lap'] as const;
|
||||
|
||||
return [
|
||||
League.create({
|
||||
id: 'league-1',
|
||||
name: 'GridPilot Sprint Series',
|
||||
description: 'Weekly sprint races with stable grids.',
|
||||
ownerId: 'driver-1',
|
||||
settings: {
|
||||
pointsSystem: 'f1-2024',
|
||||
maxDrivers: 24,
|
||||
sessionDuration: 60,
|
||||
qualifyingFormat: 'open',
|
||||
},
|
||||
createdAt: this.addDays(createdAtBase, -200),
|
||||
socialLinks: {
|
||||
discordUrl: 'https://discord.gg/gridpilot-demo',
|
||||
youtubeUrl: 'https://youtube.com/@gridpilot-demo',
|
||||
websiteUrl: 'https://gridpilot-demo.example.com',
|
||||
},
|
||||
}),
|
||||
League.create({
|
||||
id: 'league-2',
|
||||
name: 'GridPilot Endurance Cup',
|
||||
description: 'Longer races with strategy and consistency.',
|
||||
ownerId: 'driver-2',
|
||||
settings: {
|
||||
pointsSystem: 'indycar',
|
||||
maxDrivers: 32,
|
||||
sessionDuration: 120,
|
||||
qualifyingFormat: 'open',
|
||||
},
|
||||
createdAt: this.addDays(createdAtBase, -180),
|
||||
socialLinks: { discordUrl: 'https://discord.gg/gridpilot-endurance' },
|
||||
}),
|
||||
League.create({
|
||||
id: 'league-3',
|
||||
name: 'GridPilot Club Ladder',
|
||||
description: 'Casual ladder with fast onboarding.',
|
||||
ownerId: 'driver-3',
|
||||
settings: {
|
||||
pointsSystem: 'f1-2024',
|
||||
maxDrivers: 48,
|
||||
sessionDuration: 45,
|
||||
qualifyingFormat: 'single-lap',
|
||||
},
|
||||
createdAt: this.addDays(createdAtBase, -160),
|
||||
}),
|
||||
League.create({
|
||||
id: 'league-4',
|
||||
name: 'Nordic Night Series',
|
||||
description: 'Evening races with tight fields.',
|
||||
ownerId: 'driver-4',
|
||||
settings: {
|
||||
pointsSystem: 'f1-2024',
|
||||
maxDrivers: 32,
|
||||
sessionDuration: 60,
|
||||
qualifyingFormat: 'open',
|
||||
},
|
||||
createdAt: this.addDays(createdAtBase, -150),
|
||||
}),
|
||||
League.create({
|
||||
id: 'league-5',
|
||||
name: 'Demo League (Admin)',
|
||||
description: 'Primary demo league owned by driver-1.',
|
||||
ownerId: 'driver-1',
|
||||
settings: {
|
||||
pointsSystem: 'f1-2024',
|
||||
maxDrivers: 24,
|
||||
sessionDuration: 60,
|
||||
qualifyingFormat: 'open',
|
||||
},
|
||||
createdAt: this.addDays(createdAtBase, -140),
|
||||
}),
|
||||
League.create({
|
||||
id: 'league-6',
|
||||
name: 'Sim Racing Alliance',
|
||||
description: 'Mixed-format season with community events.',
|
||||
ownerId: 'driver-5',
|
||||
settings: {
|
||||
pointsSystem: 'indycar',
|
||||
maxDrivers: 40,
|
||||
sessionDuration: 90,
|
||||
qualifyingFormat: 'open',
|
||||
},
|
||||
createdAt: this.addDays(createdAtBase, -130),
|
||||
}),
|
||||
];
|
||||
}
|
||||
return Array.from({ length: leagueCount }, (_, idx) => {
|
||||
const i = idx + 1;
|
||||
const owner = faker.helpers.arrayElement(this.drivers);
|
||||
const socialLinks: { discordUrl?: string; youtubeUrl?: string; websiteUrl?: string } = {};
|
||||
if (faker.datatype.boolean()) socialLinks.discordUrl = faker.internet.url();
|
||||
if (faker.datatype.boolean()) socialLinks.youtubeUrl = faker.internet.url();
|
||||
if (faker.datatype.boolean()) socialLinks.websiteUrl = faker.internet.url();
|
||||
|
||||
private addDays(date: Date, days: number): Date {
|
||||
return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
|
||||
const leagueData: {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
settings: {
|
||||
pointsSystem: 'f1-2024' | 'indycar' | 'custom';
|
||||
maxDrivers: number;
|
||||
sessionDuration: number;
|
||||
qualifyingFormat: 'open' | 'single-lap';
|
||||
};
|
||||
createdAt: Date;
|
||||
socialLinks?: { discordUrl?: string; youtubeUrl?: string; websiteUrl?: string };
|
||||
} = {
|
||||
id: `league-${i}`,
|
||||
name: faker.company.name() + ' Racing League',
|
||||
description: faker.lorem.sentences(2),
|
||||
ownerId: owner.id.toString(),
|
||||
settings: {
|
||||
pointsSystem: faker.helpers.arrayElement(pointsSystems),
|
||||
maxDrivers: faker.number.int({ min: 20, max: 50 }),
|
||||
sessionDuration: faker.number.int({ min: 30, max: 180 }),
|
||||
qualifyingFormat: faker.helpers.arrayElement(qualifyingFormats),
|
||||
},
|
||||
createdAt: faker.date.past({ years: 2, refDate: this.baseDate }),
|
||||
};
|
||||
|
||||
if (Object.keys(socialLinks).length > 0) {
|
||||
leagueData.socialLinks = socialLinks;
|
||||
}
|
||||
|
||||
return League.create(leagueData);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,31 @@
|
||||
import { League } from '@core/racing/domain/entities/League';
|
||||
import { Race } from '@core/racing/domain/entities/Race';
|
||||
import { Track } from '@core/racing/domain/entities/Track';
|
||||
|
||||
export class RacingRaceFactory {
|
||||
constructor(private readonly baseDate: Date) {}
|
||||
|
||||
create(leagues: League[]): Race[] {
|
||||
const tracks = [
|
||||
'Monza GP',
|
||||
'Spa-Francorchamps',
|
||||
'Suzuka',
|
||||
'Mount Panorama',
|
||||
'Silverstone GP',
|
||||
'Interlagos',
|
||||
'Imola',
|
||||
'Laguna Seca',
|
||||
];
|
||||
create(leagues: League[], tracks: Track[]): Race[] {
|
||||
const cars = ['GT3 – Porsche 911', 'GT3 – BMW M4', 'LMP3 Prototype', 'GT4 – Alpine', 'Touring – Civic'];
|
||||
|
||||
const leagueIds = leagues.map((l) => l.id.toString());
|
||||
const trackIds = tracks.map((t) => t.id);
|
||||
const demoLeagueId = 'league-5';
|
||||
|
||||
const races: Race[] = [];
|
||||
|
||||
for (let i = 1; i <= 25; i++) {
|
||||
for (let i = 1; i <= 50; i++) {
|
||||
const leagueId = leagueIds[(i - 1) % leagueIds.length] ?? demoLeagueId;
|
||||
const trackId = trackIds[(i - 1) % trackIds.length]!;
|
||||
const track = tracks.find(t => t.id === trackId)!;
|
||||
const scheduledAt = this.addDays(this.baseDate, i <= 10 ? -35 + i : 1 + (i - 10) * 2);
|
||||
|
||||
const base = {
|
||||
id: `race-${i}`,
|
||||
leagueId,
|
||||
scheduledAt,
|
||||
track: tracks[(i - 1) % tracks.length]!,
|
||||
track: track.name.toString(),
|
||||
trackId: track.id,
|
||||
car: cars[(i - 1) % cars.length]!,
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import { RaceRegistration } from '@core/racing/domain/entities/RaceRegistration'
|
||||
import { Result as RaceResult } from '@core/racing/domain/entities/result/Result';
|
||||
import { Standing } from '@core/racing/domain/entities/Standing';
|
||||
import { Team } from '@core/racing/domain/entities/Team';
|
||||
import { Track } from '@core/racing/domain/entities/Track';
|
||||
import type { TeamMembership } from '@core/racing/domain/types/TeamMembership';
|
||||
import type { FeedItem } from '@core/social/domain/types/FeedItem';
|
||||
import { RacingDriverFactory } from './RacingDriverFactory';
|
||||
@@ -17,6 +18,7 @@ import { RacingRaceFactory } from './RacingRaceFactory';
|
||||
import { RacingResultFactory } from './RacingResultFactory';
|
||||
import { RacingStandingFactory } from './RacingStandingFactory';
|
||||
import { RacingTeamFactory } from './RacingTeamFactory';
|
||||
import { RacingTrackFactory } from './RacingTrackFactory';
|
||||
|
||||
export type Friendship = {
|
||||
driverId: string;
|
||||
@@ -33,6 +35,7 @@ export type RacingSeed = {
|
||||
raceRegistrations: RaceRegistration[];
|
||||
teams: Team[];
|
||||
teamMemberships: TeamMembership[];
|
||||
tracks: Track[];
|
||||
friendships: Friendship[];
|
||||
feedEvents: FeedItem[];
|
||||
};
|
||||
@@ -45,7 +48,7 @@ export type RacingSeedOptions = {
|
||||
export const racingSeedDefaults: Readonly<
|
||||
Required<RacingSeedOptions>
|
||||
> = {
|
||||
driverCount: 32,
|
||||
driverCount: 100,
|
||||
baseDate: new Date('2025-01-15T12:00:00.000Z'),
|
||||
};
|
||||
|
||||
@@ -60,23 +63,25 @@ class RacingSeedFactory {
|
||||
|
||||
create(): RacingSeed {
|
||||
const driverFactory = new RacingDriverFactory(this.driverCount, this.baseDate);
|
||||
const leagueFactory = new RacingLeagueFactory(this.baseDate);
|
||||
const trackFactory = new RacingTrackFactory();
|
||||
const raceFactory = new RacingRaceFactory(this.baseDate);
|
||||
const resultFactory = new RacingResultFactory();
|
||||
const standingFactory = new RacingStandingFactory();
|
||||
const membershipFactory = new RacingMembershipFactory(this.baseDate);
|
||||
const teamFactory = new RacingTeamFactory(this.baseDate);
|
||||
const friendshipFactory = new RacingFriendshipFactory();
|
||||
const feedFactory = new RacingFeedFactory(this.baseDate);
|
||||
|
||||
const drivers = driverFactory.create();
|
||||
const tracks = trackFactory.create();
|
||||
const leagueFactory = new RacingLeagueFactory(this.baseDate, drivers);
|
||||
const leagues = leagueFactory.create();
|
||||
const races = raceFactory.create(leagues);
|
||||
const teamFactory = new RacingTeamFactory(this.baseDate, drivers, leagues);
|
||||
const teams = teamFactory.createTeams();
|
||||
const races = raceFactory.create(leagues, tracks);
|
||||
const results = resultFactory.create(drivers, races);
|
||||
const standings = standingFactory.create(leagues, races, results);
|
||||
const leagueMemberships = membershipFactory.createLeagueMemberships(drivers, leagues);
|
||||
const raceRegistrations = membershipFactory.createRaceRegistrations(races);
|
||||
const teams = teamFactory.createTeams();
|
||||
const teamMemberships = teamFactory.createTeamMemberships(drivers, teams);
|
||||
const friendships = friendshipFactory.create(drivers);
|
||||
const feedEvents = feedFactory.create(drivers, friendships, races, leagues);
|
||||
@@ -91,6 +96,7 @@ class RacingSeedFactory {
|
||||
raceRegistrations,
|
||||
teams,
|
||||
teamMemberships,
|
||||
tracks,
|
||||
friendships,
|
||||
feedEvents,
|
||||
};
|
||||
|
||||
@@ -1,92 +1,72 @@
|
||||
import { Driver } from '@core/racing/domain/entities/Driver';
|
||||
import { League } from '@core/racing/domain/entities/League';
|
||||
import { Team } from '@core/racing/domain/entities/Team';
|
||||
import type { TeamMembership } from '@core/racing/domain/types/TeamMembership';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
export class RacingTeamFactory {
|
||||
constructor(private readonly baseDate: Date) {}
|
||||
constructor(
|
||||
private readonly baseDate: Date,
|
||||
private readonly drivers: Driver[],
|
||||
private readonly leagues: League[],
|
||||
) {}
|
||||
|
||||
createTeams(): Team[] {
|
||||
return [
|
||||
Team.create({
|
||||
id: 'team-1',
|
||||
name: 'Apex Racing',
|
||||
tag: 'APEX',
|
||||
description: 'Demo team focused on clean racing.',
|
||||
ownerId: 'driver-1',
|
||||
leagues: ['league-5'],
|
||||
createdAt: this.addDays(this.baseDate, -100),
|
||||
}),
|
||||
Team.create({
|
||||
id: 'team-2',
|
||||
name: 'Night Owls',
|
||||
tag: 'NITE',
|
||||
description: 'Late-night grinders and endurance lovers.',
|
||||
ownerId: 'driver-2',
|
||||
leagues: ['league-4'],
|
||||
createdAt: this.addDays(this.baseDate, -90),
|
||||
}),
|
||||
Team.create({
|
||||
id: 'team-3',
|
||||
name: 'Club Legends',
|
||||
tag: 'CLUB',
|
||||
description: 'A casual team for ladder climbing.',
|
||||
ownerId: 'driver-3',
|
||||
leagues: ['league-3'],
|
||||
createdAt: this.addDays(this.baseDate, -80),
|
||||
}),
|
||||
];
|
||||
const teamCount = 15;
|
||||
|
||||
return Array.from({ length: teamCount }, (_, idx) => {
|
||||
const i = idx + 1;
|
||||
const owner = faker.helpers.arrayElement(this.drivers);
|
||||
const teamLeagues = faker.helpers.arrayElements(
|
||||
this.leagues.map(l => l.id.toString()),
|
||||
{ min: 0, max: 3 }
|
||||
);
|
||||
|
||||
return Team.create({
|
||||
id: `team-${i}`,
|
||||
name: faker.company.name() + ' Racing',
|
||||
tag: faker.string.alpha({ length: 4, casing: 'upper' }),
|
||||
description: faker.lorem.sentences(2),
|
||||
ownerId: owner.id,
|
||||
leagues: teamLeagues,
|
||||
createdAt: faker.date.past({ years: 2, refDate: this.baseDate }),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
createTeamMemberships(drivers: Driver[], teams: Team[]): TeamMembership[] {
|
||||
const memberships: TeamMembership[] = [];
|
||||
const usedDrivers = new Set<string>();
|
||||
|
||||
const team1 = teams.find((t) => t.id === 'team-1');
|
||||
const team2 = teams.find((t) => t.id === 'team-2');
|
||||
const team3 = teams.find((t) => t.id === 'team-3');
|
||||
teams.forEach((team) => {
|
||||
const availableDrivers = drivers.filter(d => !usedDrivers.has(d.id.toString()) && d.id.toString() !== team.ownerId.toString());
|
||||
const memberCount = faker.number.int({ min: 1, max: 8 });
|
||||
const members = faker.helpers.arrayElements(availableDrivers, memberCount);
|
||||
|
||||
if (team1) {
|
||||
const members = drivers.slice(0, 6);
|
||||
members.forEach((d, idx) => {
|
||||
memberships.push({
|
||||
teamId: team1.id,
|
||||
driverId: d.id,
|
||||
role: d.id === team1.ownerId.toString() ? 'owner' : idx === 1 ? 'manager' : 'driver',
|
||||
status: 'active',
|
||||
joinedAt: this.addDays(this.baseDate, -50),
|
||||
});
|
||||
// Add owner
|
||||
memberships.push({
|
||||
teamId: team.id.toString(),
|
||||
driverId: team.ownerId.toString(),
|
||||
role: 'owner',
|
||||
status: 'active',
|
||||
joinedAt: faker.date.past({ years: 1, refDate: team.createdAt.toDate() }),
|
||||
});
|
||||
}
|
||||
usedDrivers.add(team.ownerId.toString());
|
||||
|
||||
if (team2) {
|
||||
const members = drivers.slice(6, 12);
|
||||
members.forEach((d) => {
|
||||
// Add members
|
||||
members.forEach((driver) => {
|
||||
memberships.push({
|
||||
teamId: team2.id,
|
||||
driverId: d.id,
|
||||
role: d.id === team2.ownerId.toString() ? 'owner' : 'driver',
|
||||
teamId: team.id.toString(),
|
||||
driverId: driver.id.toString(),
|
||||
role: faker.helpers.arrayElement(['driver', 'manager']),
|
||||
status: 'active',
|
||||
joinedAt: this.addDays(this.baseDate, -45),
|
||||
joinedAt: faker.date.past({ years: 1, refDate: team.createdAt.toDate() }),
|
||||
});
|
||||
usedDrivers.add(driver.id.toString());
|
||||
});
|
||||
}
|
||||
|
||||
if (team3) {
|
||||
const members = drivers.slice(12, 18);
|
||||
members.forEach((d) => {
|
||||
memberships.push({
|
||||
teamId: team3.id,
|
||||
driverId: d.id,
|
||||
role: d.id === team3.ownerId.toString() ? 'owner' : 'driver',
|
||||
status: 'active',
|
||||
joinedAt: this.addDays(this.baseDate, -40),
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return memberships;
|
||||
}
|
||||
|
||||
private addDays(date: Date, days: number): Date {
|
||||
return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
|
||||
}
|
||||
}
|
||||
92
adapters/bootstrap/racing/RacingTrackFactory.ts
Normal file
92
adapters/bootstrap/racing/RacingTrackFactory.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { Track } from '@core/racing/domain/entities/Track';
|
||||
|
||||
export class RacingTrackFactory {
|
||||
create(): Track[] {
|
||||
return [
|
||||
Track.create({
|
||||
id: 'track-spa',
|
||||
name: 'Spa-Francorchamps',
|
||||
shortName: 'SPA',
|
||||
country: 'Belgium',
|
||||
category: 'road',
|
||||
difficulty: 'advanced',
|
||||
lengthKm: 7.004,
|
||||
turns: 19,
|
||||
imageUrl: '/images/tracks/spa.jpg',
|
||||
gameId: 'iracing',
|
||||
}),
|
||||
Track.create({
|
||||
id: 'track-monza',
|
||||
name: 'Autodromo Nazionale Monza',
|
||||
shortName: 'MON',
|
||||
country: 'Italy',
|
||||
category: 'road',
|
||||
difficulty: 'intermediate',
|
||||
lengthKm: 5.793,
|
||||
turns: 11,
|
||||
imageUrl: '/images/tracks/monza.jpg',
|
||||
gameId: 'iracing',
|
||||
}),
|
||||
Track.create({
|
||||
id: 'track-nurburgring',
|
||||
name: 'Nürburgring Grand Prix',
|
||||
shortName: 'NUR',
|
||||
country: 'Germany',
|
||||
category: 'road',
|
||||
difficulty: 'advanced',
|
||||
lengthKm: 5.148,
|
||||
turns: 15,
|
||||
imageUrl: '/images/tracks/nurburgring.jpg',
|
||||
gameId: 'iracing',
|
||||
}),
|
||||
Track.create({
|
||||
id: 'track-silverstone',
|
||||
name: 'Silverstone Circuit',
|
||||
shortName: 'SIL',
|
||||
country: 'United Kingdom',
|
||||
category: 'road',
|
||||
difficulty: 'intermediate',
|
||||
lengthKm: 5.891,
|
||||
turns: 18,
|
||||
imageUrl: '/images/tracks/silverstone.jpg',
|
||||
gameId: 'iracing',
|
||||
}),
|
||||
Track.create({
|
||||
id: 'track-suzuka',
|
||||
name: 'Suzuka International Racing Course',
|
||||
shortName: 'SUZ',
|
||||
country: 'Japan',
|
||||
category: 'road',
|
||||
difficulty: 'expert',
|
||||
lengthKm: 5.807,
|
||||
turns: 18,
|
||||
imageUrl: '/images/tracks/suzuka.jpg',
|
||||
gameId: 'iracing',
|
||||
}),
|
||||
Track.create({
|
||||
id: 'track-daytona',
|
||||
name: 'Daytona International Speedway',
|
||||
shortName: 'DAY',
|
||||
country: 'United States',
|
||||
category: 'oval',
|
||||
difficulty: 'intermediate',
|
||||
lengthKm: 4.023,
|
||||
turns: 4,
|
||||
imageUrl: '/images/tracks/daytona.jpg',
|
||||
gameId: 'iracing',
|
||||
}),
|
||||
Track.create({
|
||||
id: 'track-laguna',
|
||||
name: 'WeatherTech Raceway Laguna Seca',
|
||||
shortName: 'LAG',
|
||||
country: 'United States',
|
||||
category: 'road',
|
||||
difficulty: 'advanced',
|
||||
lengthKm: 3.602,
|
||||
turns: 11,
|
||||
imageUrl: '/images/tracks/laguna.jpg',
|
||||
gameId: 'iracing',
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ describe('CompleteDriverOnboardingUseCase', () => {
|
||||
useCase = new CompleteDriverOnboardingUseCase(
|
||||
driverRepository as unknown as IDriverRepository,
|
||||
logger,
|
||||
output,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -65,7 +66,7 @@ describe('CompleteDriverOnboardingUseCase', () => {
|
||||
const result = await useCase.execute(command);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toEqual({ driver: createdDriver });
|
||||
expect(output.present).toHaveBeenCalledWith({ driver: createdDriver });
|
||||
expect(driverRepository.findById).toHaveBeenCalledWith('user-1');
|
||||
expect(driverRepository.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
@@ -143,7 +144,7 @@ describe('CompleteDriverOnboardingUseCase', () => {
|
||||
const result = await useCase.execute(command);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toEqual({ driver: createdDriver });
|
||||
expect(output.present).toHaveBeenCalledWith({ driver: createdDriver });
|
||||
expect(driverRepository.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: 'user-1',
|
||||
|
||||
@@ -7,6 +7,8 @@ import type { IDriverRepository } from '../../domain/repositories/IDriverReposit
|
||||
import type { IRankingService } from '../../domain/services/IRankingService';
|
||||
import type { IDriverStatsService } from '../../domain/services/IDriverStatsService';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
import type { GetDriversLeaderboardResult } from './GetDriversLeaderboardUseCase';
|
||||
|
||||
describe('GetDriversLeaderboardUseCase', () => {
|
||||
const mockDriverFindAll = vi.fn();
|
||||
@@ -39,6 +41,10 @@ describe('GetDriversLeaderboardUseCase', () => {
|
||||
error: vi.fn(),
|
||||
};
|
||||
|
||||
const mockOutput: UseCaseOutputPort<GetDriversLeaderboardResult> = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
it('should return drivers leaderboard data', async () => {
|
||||
const useCase = new GetDriversLeaderboardUseCase(
|
||||
mockDriverRepo,
|
||||
@@ -46,6 +52,7 @@ describe('GetDriversLeaderboardUseCase', () => {
|
||||
mockDriverStatsService,
|
||||
mockGetDriverAvatar,
|
||||
mockLogger,
|
||||
mockOutput,
|
||||
);
|
||||
|
||||
const driver1 = { id: 'driver1', name: { value: 'Driver One' }, country: { value: 'US' } };
|
||||
@@ -75,9 +82,8 @@ describe('GetDriversLeaderboardUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented).toEqual({
|
||||
expect(mockOutput.present).toHaveBeenCalledWith({
|
||||
items: [
|
||||
expect.objectContaining({
|
||||
driver: driver1,
|
||||
@@ -115,6 +121,7 @@ describe('GetDriversLeaderboardUseCase', () => {
|
||||
mockDriverStatsService,
|
||||
mockGetDriverAvatar,
|
||||
mockLogger,
|
||||
mockOutput,
|
||||
);
|
||||
|
||||
mockDriverFindAll.mockResolvedValue([]);
|
||||
@@ -125,9 +132,8 @@ describe('GetDriversLeaderboardUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented).toEqual({
|
||||
expect(mockOutput.present).toHaveBeenCalledWith({
|
||||
items: [],
|
||||
totalRaces: 0,
|
||||
totalWins: 0,
|
||||
@@ -142,6 +148,7 @@ describe('GetDriversLeaderboardUseCase', () => {
|
||||
mockDriverStatsService,
|
||||
mockGetDriverAvatar,
|
||||
mockLogger,
|
||||
mockOutput,
|
||||
);
|
||||
|
||||
const driver1 = { id: 'driver1', name: { value: 'Driver One' }, country: { value: 'US' } };
|
||||
@@ -157,9 +164,8 @@ describe('GetDriversLeaderboardUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
const presented = result.unwrap();
|
||||
|
||||
expect(presented).toEqual({
|
||||
expect(mockOutput.present).toHaveBeenCalledWith({
|
||||
items: [
|
||||
expect.objectContaining({
|
||||
driver: driver1,
|
||||
@@ -186,6 +192,7 @@ describe('GetDriversLeaderboardUseCase', () => {
|
||||
mockDriverStatsService,
|
||||
mockGetDriverAvatar,
|
||||
mockLogger,
|
||||
mockOutput,
|
||||
);
|
||||
|
||||
const error = new Error('Repository error');
|
||||
|
||||
@@ -3,21 +3,27 @@ import {
|
||||
GetTotalDriversUseCase,
|
||||
GetTotalDriversInput,
|
||||
GetTotalDriversErrorCode,
|
||||
GetTotalDriversResult,
|
||||
} from './GetTotalDriversUseCase';
|
||||
import { IDriverRepository } from '../../domain/repositories/IDriverRepository';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
|
||||
describe('GetTotalDriversUseCase', () => {
|
||||
let useCase: GetTotalDriversUseCase;
|
||||
let driverRepository: {
|
||||
findAll: Mock;
|
||||
};
|
||||
let output: UseCaseOutputPort<GetTotalDriversResult>;
|
||||
beforeEach(() => {
|
||||
driverRepository = {
|
||||
findAll: vi.fn(),
|
||||
};
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
|
||||
useCase = new GetTotalDriversUseCase(driverRepository as unknown as IDriverRepository);
|
||||
useCase = new GetTotalDriversUseCase(driverRepository as unknown as IDriverRepository, output);
|
||||
});
|
||||
|
||||
it('should return total number of drivers', async () => {
|
||||
@@ -30,7 +36,7 @@ describe('GetTotalDriversUseCase', () => {
|
||||
const result = await useCase.execute(input);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toEqual({ totalDrivers: 2 });
|
||||
expect(output.present).toHaveBeenCalledWith({ totalDrivers: 2 });
|
||||
});
|
||||
|
||||
it('should return error on repository failure', async () => {
|
||||
|
||||
@@ -3,10 +3,12 @@ import {
|
||||
IsDriverRegisteredForRaceUseCase,
|
||||
type IsDriverRegisteredForRaceInput,
|
||||
type IsDriverRegisteredForRaceErrorCode,
|
||||
type IsDriverRegisteredForRaceResult,
|
||||
} from './IsDriverRegisteredForRaceUseCase';
|
||||
import { IRaceRegistrationRepository } from '../../domain/repositories/IRaceRegistrationRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
|
||||
describe('IsDriverRegisteredForRaceUseCase', () => {
|
||||
let useCase: IsDriverRegisteredForRaceUseCase;
|
||||
@@ -19,6 +21,7 @@ describe('IsDriverRegisteredForRaceUseCase', () => {
|
||||
warn: Mock;
|
||||
error: Mock;
|
||||
};
|
||||
let output: UseCaseOutputPort<IsDriverRegisteredForRaceResult>;
|
||||
beforeEach(() => {
|
||||
registrationRepository = {
|
||||
isRegistered: vi.fn(),
|
||||
@@ -29,9 +32,13 @@ describe('IsDriverRegisteredForRaceUseCase', () => {
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
};
|
||||
output = {
|
||||
present: vi.fn(),
|
||||
};
|
||||
useCase = new IsDriverRegisteredForRaceUseCase(
|
||||
registrationRepository as unknown as IRaceRegistrationRepository,
|
||||
logger as unknown as Logger,
|
||||
output,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -43,7 +50,7 @@ describe('IsDriverRegisteredForRaceUseCase', () => {
|
||||
const result = await useCase.execute(params);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toEqual({
|
||||
expect(output.present).toHaveBeenCalledWith({
|
||||
raceId: params.raceId,
|
||||
driverId: params.driverId,
|
||||
isRegistered: true,
|
||||
@@ -58,7 +65,7 @@ describe('IsDriverRegisteredForRaceUseCase', () => {
|
||||
const result = await useCase.execute(params);
|
||||
|
||||
expect(result.isOk()).toBe(true);
|
||||
expect(result.unwrap()).toEqual({
|
||||
expect(output.present).toHaveBeenCalledWith({
|
||||
raceId: params.raceId,
|
||||
driverId: params.driverId,
|
||||
isRegistered: false,
|
||||
|
||||
11
package-lock.json
generated
11
package-lock.json
generated
@@ -50,6 +50,7 @@
|
||||
"eslint-import-resolver-typescript": "2.7.1",
|
||||
"eslint-plugin-boundaries": "^5.3.1",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"faker": "^6.6.6",
|
||||
"glob": "^13.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"jsdom": "^22.1.0",
|
||||
@@ -87,7 +88,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/testing": "^10.4.20",
|
||||
"ts-node-dev": "^2.0.0"
|
||||
"ts-node-dev": "^2.0.0",
|
||||
"tsconfig-paths": "^3.15.0"
|
||||
}
|
||||
},
|
||||
"apps/api/node_modules/reflect-metadata": {
|
||||
@@ -8126,6 +8128,13 @@
|
||||
"@types/yauzl": "^2.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/faker": {
|
||||
"version": "6.6.6",
|
||||
"resolved": "https://registry.npmjs.org/faker/-/faker-6.6.6.tgz",
|
||||
"integrity": "sha512-9tCqYEDHI5RYFQigXFwF1hnCwcWCOJl/hmll0lr5D2Ljjb0o4wphb69wikeJDz5qCEzXCoPvG6ss5SDP6IfOdg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
|
||||
@@ -35,9 +35,10 @@
|
||||
"commander": "^11.0.0",
|
||||
"electron": "^39.2.7",
|
||||
"eslint": "^8.0.0",
|
||||
"eslint-import-resolver-typescript": "2.7.1",
|
||||
"eslint-plugin-boundaries": "^5.3.1",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-import-resolver-typescript": "2.7.1",
|
||||
"faker": "^6.6.6",
|
||||
"glob": "^13.0.0",
|
||||
"husky": "^9.1.7",
|
||||
"jsdom": "^22.1.0",
|
||||
|
||||
Reference in New Issue
Block a user