integration tests
This commit is contained in:
244
tests/integration/harness/data-factory.ts
Normal file
244
tests/integration/harness/data-factory.ts
Normal file
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* Data Factory for Integration Tests
|
||||
* Uses TypeORM repositories to create test data
|
||||
*/
|
||||
|
||||
import { DataSource } from 'typeorm';
|
||||
import { LeagueOrmEntity } from '../../../adapters/racing/persistence/typeorm/entities/LeagueOrmEntity';
|
||||
import { SeasonOrmEntity } from '../../../adapters/racing/persistence/typeorm/entities/SeasonOrmEntity';
|
||||
import { DriverOrmEntity } from '../../../adapters/racing/persistence/typeorm/entities/DriverOrmEntity';
|
||||
import { RaceOrmEntity } from '../../../adapters/racing/persistence/typeorm/entities/RaceOrmEntity';
|
||||
import { ResultOrmEntity } from '../../../adapters/racing/persistence/typeorm/entities/ResultOrmEntity';
|
||||
import { LeagueOrmMapper } from '../../../adapters/racing/persistence/typeorm/mappers/LeagueOrmMapper';
|
||||
import { SeasonOrmMapper } from '../../../adapters/racing/persistence/typeorm/mappers/SeasonOrmMapper';
|
||||
import { RaceOrmMapper } from '../../../adapters/racing/persistence/typeorm/mappers/RaceOrmMapper';
|
||||
import { ResultOrmMapper } from '../../../adapters/racing/persistence/typeorm/mappers/ResultOrmMapper';
|
||||
import { TypeOrmLeagueRepository } from '../../../adapters/racing/persistence/typeorm/repositories/TypeOrmLeagueRepository';
|
||||
import { TypeOrmSeasonRepository } from '../../../adapters/racing/persistence/typeorm/repositories/TypeOrmSeasonRepository';
|
||||
import { TypeOrmRaceRepository } from '../../../adapters/racing/persistence/typeorm/repositories/TypeOrmRaceRepository';
|
||||
import { TypeOrmResultRepository } from '../../../adapters/racing/persistence/typeorm/repositories/TypeOrmResultRepository';
|
||||
import { TypeOrmDriverRepository } from '../../../adapters/racing/persistence/typeorm/repositories/TypeOrmDriverRepository';
|
||||
import { League } from '../../../core/racing/domain/entities/League';
|
||||
import { Season } from '../../../core/racing/domain/entities/season/Season';
|
||||
import { Driver } from '../../../core/racing/domain/entities/Driver';
|
||||
import { Race } from '../../../core/racing/domain/entities/Race';
|
||||
import { Result } from '../../../core/racing/domain/entities/result/Result';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export class DataFactory {
|
||||
private dataSource: DataSource;
|
||||
private leagueRepo: TypeOrmLeagueRepository;
|
||||
private seasonRepo: TypeOrmSeasonRepository;
|
||||
private driverRepo: TypeOrmDriverRepository;
|
||||
private raceRepo: TypeOrmRaceRepository;
|
||||
private resultRepo: TypeOrmResultRepository;
|
||||
|
||||
constructor(private dbUrl: string) {
|
||||
this.dataSource = new DataSource({
|
||||
type: 'postgres',
|
||||
url: dbUrl,
|
||||
entities: [
|
||||
LeagueOrmEntity,
|
||||
SeasonOrmEntity,
|
||||
DriverOrmEntity,
|
||||
RaceOrmEntity,
|
||||
ResultOrmEntity,
|
||||
],
|
||||
synchronize: false, // Don't sync, use existing schema
|
||||
});
|
||||
}
|
||||
|
||||
async initialize(): Promise<void> {
|
||||
if (!this.dataSource.isInitialized) {
|
||||
await this.dataSource.initialize();
|
||||
}
|
||||
|
||||
const leagueMapper = new LeagueOrmMapper();
|
||||
const seasonMapper = new SeasonOrmMapper();
|
||||
const raceMapper = new RaceOrmMapper();
|
||||
const resultMapper = new ResultOrmMapper();
|
||||
|
||||
this.leagueRepo = new TypeOrmLeagueRepository(this.dataSource, leagueMapper);
|
||||
this.seasonRepo = new TypeOrmSeasonRepository(this.dataSource, seasonMapper);
|
||||
this.driverRepo = new TypeOrmDriverRepository(this.dataSource, leagueMapper); // Reuse mapper
|
||||
this.raceRepo = new TypeOrmRaceRepository(this.dataSource, raceMapper);
|
||||
this.resultRepo = new TypeOrmResultRepository(this.dataSource, resultMapper);
|
||||
}
|
||||
|
||||
async cleanup(): Promise<void> {
|
||||
if (this.dataSource.isInitialized) {
|
||||
await this.dataSource.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a test league
|
||||
*/
|
||||
async createLeague(overrides: Partial<{
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
ownerId: string;
|
||||
}> = {}) {
|
||||
const league = League.create({
|
||||
id: overrides.id || uuidv4(),
|
||||
name: overrides.name || 'Test League',
|
||||
description: overrides.description || 'Integration Test League',
|
||||
ownerId: overrides.ownerId || uuidv4(),
|
||||
settings: {
|
||||
enableDriverChampionship: true,
|
||||
enableTeamChampionship: false,
|
||||
enableNationsChampionship: false,
|
||||
enableTrophyChampionship: false,
|
||||
visibility: 'unranked',
|
||||
maxDrivers: 32,
|
||||
},
|
||||
participantCount: 0,
|
||||
});
|
||||
|
||||
await this.leagueRepo.create(league);
|
||||
return league;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a test season
|
||||
*/
|
||||
async createSeason(leagueId: string, overrides: Partial<{
|
||||
id: string;
|
||||
name: string;
|
||||
year: number;
|
||||
status: string;
|
||||
}> = {}) {
|
||||
const season = Season.create({
|
||||
id: overrides.id || uuidv4(),
|
||||
leagueId,
|
||||
gameId: 'iracing',
|
||||
name: overrides.name || 'Test Season',
|
||||
year: overrides.year || 2024,
|
||||
order: 1,
|
||||
status: overrides.status || 'active',
|
||||
startDate: new Date(),
|
||||
endDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
|
||||
schedulePublished: false,
|
||||
});
|
||||
|
||||
await this.seasonRepo.create(season);
|
||||
return season;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a test driver
|
||||
*/
|
||||
async createDriver(overrides: Partial<{
|
||||
id: string;
|
||||
name: string;
|
||||
iracingId: string;
|
||||
country: string;
|
||||
}> = {}) {
|
||||
const driver = Driver.create({
|
||||
id: overrides.id || uuidv4(),
|
||||
iracingId: overrides.iracingId || `iracing-${uuidv4()}`,
|
||||
name: overrides.name || 'Test Driver',
|
||||
country: overrides.country || 'US',
|
||||
});
|
||||
|
||||
// Need to insert directly since driver repo might not exist or be different
|
||||
await this.dataSource.getRepository(DriverOrmEntity).save({
|
||||
id: driver.id.toString(),
|
||||
iracingId: driver.iracingId,
|
||||
name: driver.name.toString(),
|
||||
country: driver.country,
|
||||
joinedAt: new Date(),
|
||||
bio: null,
|
||||
category: null,
|
||||
avatarRef: null,
|
||||
});
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a test race
|
||||
*/
|
||||
async createRace(overrides: Partial<{
|
||||
id: string;
|
||||
leagueId: string;
|
||||
scheduledAt: Date;
|
||||
status: string;
|
||||
track: string;
|
||||
car: string;
|
||||
}> = {}) {
|
||||
const race = Race.create({
|
||||
id: overrides.id || uuidv4(),
|
||||
leagueId: overrides.leagueId || uuidv4(),
|
||||
scheduledAt: overrides.scheduledAt || new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
||||
track: overrides.track || 'Laguna Seca',
|
||||
car: overrides.car || 'Formula Ford',
|
||||
status: overrides.status || 'scheduled',
|
||||
});
|
||||
|
||||
await this.raceRepo.create(race);
|
||||
return race;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a test result
|
||||
*/
|
||||
async createResult(raceId: string, driverId: string, overrides: Partial<{
|
||||
id: string;
|
||||
position: number;
|
||||
fastestLap: number;
|
||||
incidents: number;
|
||||
startPosition: number;
|
||||
}> = {}) {
|
||||
const result = Result.create({
|
||||
id: overrides.id || uuidv4(),
|
||||
raceId,
|
||||
driverId,
|
||||
position: overrides.position || 1,
|
||||
fastestLap: overrides.fastestLap || 0,
|
||||
incidents: overrides.incidents || 0,
|
||||
startPosition: overrides.startPosition || 1,
|
||||
});
|
||||
|
||||
await this.resultRepo.create(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create complete test scenario: league, season, drivers, races
|
||||
*/
|
||||
async createTestScenario() {
|
||||
const league = await this.createLeague();
|
||||
const season = await this.createSeason(league.id.toString());
|
||||
const drivers = await Promise.all([
|
||||
this.createDriver({ name: 'Driver 1' }),
|
||||
this.createDriver({ name: 'Driver 2' }),
|
||||
this.createDriver({ name: 'Driver 3' }),
|
||||
]);
|
||||
const races = await Promise.all([
|
||||
this.createRace({
|
||||
leagueId: league.id.toString(),
|
||||
name: 'Race 1',
|
||||
scheduledAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
|
||||
}),
|
||||
this.createRace({
|
||||
leagueId: league.id.toString(),
|
||||
name: 'Race 2',
|
||||
scheduledAt: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000)
|
||||
}),
|
||||
]);
|
||||
|
||||
return { league, season, drivers, races };
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up specific entities
|
||||
*/
|
||||
async deleteEntities(entities: { id: any }[], entityType: string) {
|
||||
const repository = this.dataSource.getRepository(entityType);
|
||||
for (const entity of entities) {
|
||||
await repository.delete(entity.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user