integration tests
Some checks failed
CI / lint-typecheck (pull_request) Failing after 4m50s
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-23 11:44:59 +01:00
parent a0f41f242f
commit 6df38a462a
125 changed files with 4712 additions and 19184 deletions

View File

@@ -0,0 +1,32 @@
import { InMemoryDriverRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { CompleteDriverOnboardingUseCase } from '../../../core/racing/application/use-cases/CompleteDriverOnboardingUseCase';
import { Logger } from '../../../core/shared/domain/Logger';
export class OnboardingTestContext {
public readonly driverRepository: InMemoryDriverRepository;
public readonly completeDriverOnboardingUseCase: CompleteDriverOnboardingUseCase;
public readonly mockLogger: Logger;
constructor() {
this.mockLogger = {
info: () => {},
debug: () => {},
warn: () => {},
error: () => {},
} as unknown as Logger;
this.driverRepository = new InMemoryDriverRepository(this.mockLogger);
this.completeDriverOnboardingUseCase = new CompleteDriverOnboardingUseCase(
this.driverRepository,
this.mockLogger
);
}
async clear() {
await this.driverRepository.clear();
}
static create() {
return new OnboardingTestContext();
}
}

View File

@@ -0,0 +1,5 @@
import { describe, it } from 'vitest';
describe('Onboarding Avatar Use Case Orchestration', () => {
it.todo('should test onboarding-specific avatar orchestration when implemented');
});

View File

@@ -0,0 +1,83 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { OnboardingTestContext } from '../OnboardingTestContext';
describe('CompleteDriverOnboardingUseCase - Success Path', () => {
let context: OnboardingTestContext;
beforeEach(async () => {
context = OnboardingTestContext.create();
await context.clear();
});
it('should complete onboarding with valid personal info', async () => {
// Scenario: Complete onboarding successfully
// Given: A new user ID
const userId = 'user-123';
const input = {
userId,
firstName: 'John',
lastName: 'Doe',
displayName: 'RacerJohn',
country: 'US',
bio: 'New racer on the grid',
};
// When: CompleteDriverOnboardingUseCase.execute() is called
const result = await context.completeDriverOnboardingUseCase.execute(input);
// Then: Driver should be created
expect(result.isOk()).toBe(true);
const { driver } = result.unwrap();
expect(driver.id).toBe(userId);
expect(driver.name.toString()).toBe('RacerJohn');
expect(driver.country.toString()).toBe('US');
expect(driver.bio?.toString()).toBe('New racer on the grid');
// And: Repository should contain the driver
const savedDriver = await context.driverRepository.findById(userId);
expect(savedDriver).not.toBeNull();
expect(savedDriver?.id).toBe(userId);
});
it('should complete onboarding with minimal required data', async () => {
// Scenario: Complete onboarding with minimal data
// Given: A new user ID
const userId = 'user-456';
const input = {
userId,
firstName: 'Jane',
lastName: 'Smith',
displayName: 'JaneS',
country: 'UK',
};
// When: CompleteDriverOnboardingUseCase.execute() is called
const result = await context.completeDriverOnboardingUseCase.execute(input);
// Then: Driver should be created successfully
expect(result.isOk()).toBe(true);
const { driver } = result.unwrap();
expect(driver.id).toBe(userId);
expect(driver.bio).toBeUndefined();
});
it('should handle bio as optional personal information', async () => {
// Scenario: Optional bio field
// Given: Personal info with bio
const input = {
userId: 'user-bio',
firstName: 'Bob',
lastName: 'Builder',
displayName: 'BobBuilds',
country: 'AU',
bio: 'I build fast cars',
};
// When: CompleteDriverOnboardingUseCase.execute() is called
const result = await context.completeDriverOnboardingUseCase.execute(input);
// Then: Bio should be saved
expect(result.isOk()).toBe(true);
expect(result.unwrap().driver.bio?.toString()).toBe('I build fast cars');
});
});

View File

@@ -0,0 +1,67 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { OnboardingTestContext } from '../OnboardingTestContext';
describe('CompleteDriverOnboardingUseCase - Validation & Errors', () => {
let context: OnboardingTestContext;
beforeEach(async () => {
context = OnboardingTestContext.create();
await context.clear();
});
it('should reject onboarding if driver already exists', async () => {
// Scenario: Already onboarded user
// Given: A driver already exists for the user
const userId = 'existing-user';
const existingInput = {
userId,
firstName: 'Old',
lastName: 'Name',
displayName: 'OldRacer',
country: 'DE',
};
await context.completeDriverOnboardingUseCase.execute(existingInput);
// When: CompleteDriverOnboardingUseCase.execute() is called again for same user
const result = await context.completeDriverOnboardingUseCase.execute({
userId,
firstName: 'New',
lastName: 'Name',
displayName: 'NewRacer',
country: 'FR',
});
// Then: Should return DRIVER_ALREADY_EXISTS error
expect(result.isErr()).toBe(true);
const error = result.unwrapErr();
expect(error.code).toBe('DRIVER_ALREADY_EXISTS');
});
it('should handle repository errors gracefully', async () => {
// Scenario: Repository error
// Given: Repository throws an error
const userId = 'error-user';
const originalCreate = context.driverRepository.create.bind(context.driverRepository);
context.driverRepository.create = async () => {
throw new Error('Database failure');
};
// When: CompleteDriverOnboardingUseCase.execute() is called
const result = await context.completeDriverOnboardingUseCase.execute({
userId,
firstName: 'John',
lastName: 'Doe',
displayName: 'RacerJohn',
country: 'US',
});
// Then: Should return REPOSITORY_ERROR
expect(result.isErr()).toBe(true);
const error = result.unwrapErr();
expect(error.code).toBe('REPOSITORY_ERROR');
expect(error.details.message).toBe('Database failure');
// Restore
context.driverRepository.create = originalCreate;
});
});

View File

@@ -1,17 +0,0 @@
/**
* Integration Test: Onboarding Avatar Use Case Orchestration
*
* Tests the orchestration logic of avatar-related Use Cases.
*
* NOTE: Currently, avatar generation is handled in core/media domain.
* This file remains as a placeholder for future onboarding-specific avatar orchestration
* if it moves out of the general media domain.
*
* Focus: Business logic orchestration, NOT UI rendering
*/
import { describe, it } from 'vitest';
describe('Onboarding Avatar Use Case Orchestration', () => {
it.todo('should test onboarding-specific avatar orchestration when implemented');
});

View File

@@ -1,84 +0,0 @@
/**
* Integration Test: Onboarding Personal Information Use Case Orchestration
*
* Tests the orchestration logic of personal information-related Use Cases:
* - CompleteDriverOnboardingUseCase: Handles the initial driver profile creation
*
* Validates that Use Cases correctly interact with their Ports (Repositories)
* Uses In-Memory adapters for fast, deterministic testing
*
* Focus: Business logic orchestration, NOT UI rendering
*/
import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
import { InMemoryDriverRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { CompleteDriverOnboardingUseCase } from '../../../core/racing/application/use-cases/CompleteDriverOnboardingUseCase';
import { Logger } from '../../../core/shared/domain/Logger';
describe('Onboarding Personal Information Use Case Orchestration', () => {
let driverRepository: InMemoryDriverRepository;
let completeDriverOnboardingUseCase: CompleteDriverOnboardingUseCase;
let mockLogger: Logger;
beforeAll(() => {
mockLogger = {
info: () => {},
debug: () => {},
warn: () => {},
error: () => {},
} as unknown as Logger;
driverRepository = new InMemoryDriverRepository(mockLogger);
completeDriverOnboardingUseCase = new CompleteDriverOnboardingUseCase(
driverRepository,
mockLogger
);
});
beforeEach(async () => {
await driverRepository.clear();
});
describe('CompleteDriverOnboardingUseCase - Personal Info Scenarios', () => {
it('should create driver with valid personal information', async () => {
// Scenario: Valid personal info
// Given: A new user
const input = {
userId: 'user-789',
firstName: 'Alice',
lastName: 'Wonderland',
displayName: 'AliceRacer',
country: 'UK',
};
// When: CompleteDriverOnboardingUseCase.execute() is called
const result = await completeDriverOnboardingUseCase.execute(input);
// Then: Validation should pass and driver be created
expect(result.isOk()).toBe(true);
const { driver } = result.unwrap();
expect(driver.name.toString()).toBe('AliceRacer');
expect(driver.country.toString()).toBe('UK');
});
it('should handle bio as optional personal information', async () => {
// Scenario: Optional bio field
// Given: Personal info with bio
const input = {
userId: 'user-bio',
firstName: 'Bob',
lastName: 'Builder',
displayName: 'BobBuilds',
country: 'AU',
bio: 'I build fast cars',
};
// When: CompleteDriverOnboardingUseCase.execute() is called
const result = await completeDriverOnboardingUseCase.execute(input);
// Then: Bio should be saved
expect(result.isOk()).toBe(true);
expect(result.unwrap().driver.bio?.toString()).toBe('I build fast cars');
});
});
});

View File

@@ -1,69 +0,0 @@
/**
* Integration Test: Onboarding Validation Use Case Orchestration
*
* Tests the orchestration logic of validation-related Use Cases:
* - CompleteDriverOnboardingUseCase: Validates driver data before creation
*
* Validates that Use Cases correctly interact with their Ports (Repositories)
* Uses In-Memory adapters for fast, deterministic testing
*
* Focus: Business logic orchestration, NOT UI rendering
*/
import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
import { InMemoryDriverRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { CompleteDriverOnboardingUseCase } from '../../../core/racing/application/use-cases/CompleteDriverOnboardingUseCase';
import { Logger } from '../../../core/shared/domain/Logger';
describe('Onboarding Validation Use Case Orchestration', () => {
let driverRepository: InMemoryDriverRepository;
let completeDriverOnboardingUseCase: CompleteDriverOnboardingUseCase;
let mockLogger: Logger;
beforeAll(() => {
mockLogger = {
info: () => {},
debug: () => {},
warn: () => {},
error: () => {},
} as unknown as Logger;
driverRepository = new InMemoryDriverRepository(mockLogger);
completeDriverOnboardingUseCase = new CompleteDriverOnboardingUseCase(
driverRepository,
mockLogger
);
});
beforeEach(async () => {
await driverRepository.clear();
});
describe('CompleteDriverOnboardingUseCase - Validation Scenarios', () => {
it('should validate that driver does not already exist', async () => {
// Scenario: Duplicate driver validation
// Given: A driver already exists
const userId = 'duplicate-user';
await completeDriverOnboardingUseCase.execute({
userId,
firstName: 'First',
lastName: 'Last',
displayName: 'FirstLast',
country: 'US',
});
// When: Attempting to onboard again
const result = await completeDriverOnboardingUseCase.execute({
userId,
firstName: 'Second',
lastName: 'Attempt',
displayName: 'SecondAttempt',
country: 'US',
});
// Then: Validation should fail
expect(result.isErr()).toBe(true);
expect(result.unwrapErr().code).toBe('DRIVER_ALREADY_EXISTS');
});
});
});

View File

@@ -1,153 +0,0 @@
/**
* Integration Test: Onboarding Wizard Use Case Orchestration
*
* Tests the orchestration logic of onboarding wizard-related Use Cases:
* - CompleteDriverOnboardingUseCase: Orchestrates the driver creation flow
*
* Validates that Use Cases correctly interact with their Ports (Repositories)
* Uses In-Memory adapters for fast, deterministic testing
*
* Focus: Business logic orchestration, NOT UI rendering
*/
import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
import { InMemoryDriverRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryDriverRepository';
import { CompleteDriverOnboardingUseCase } from '../../../core/racing/application/use-cases/CompleteDriverOnboardingUseCase';
import { Logger } from '../../../core/shared/domain/Logger';
describe('Onboarding Wizard Use Case Orchestration', () => {
let driverRepository: InMemoryDriverRepository;
let completeDriverOnboardingUseCase: CompleteDriverOnboardingUseCase;
let mockLogger: Logger;
beforeAll(() => {
mockLogger = {
info: () => {},
debug: () => {},
warn: () => {},
error: () => {},
} as unknown as Logger;
driverRepository = new InMemoryDriverRepository(mockLogger);
completeDriverOnboardingUseCase = new CompleteDriverOnboardingUseCase(
driverRepository,
mockLogger
);
});
beforeEach(async () => {
await driverRepository.clear();
});
describe('CompleteDriverOnboardingUseCase - Success Path', () => {
it('should complete onboarding with valid personal info', async () => {
// Scenario: Complete onboarding successfully
// Given: A new user ID
const userId = 'user-123';
const input = {
userId,
firstName: 'John',
lastName: 'Doe',
displayName: 'RacerJohn',
country: 'US',
bio: 'New racer on the grid',
};
// When: CompleteDriverOnboardingUseCase.execute() is called
const result = await completeDriverOnboardingUseCase.execute(input);
// Then: Driver should be created
expect(result.isOk()).toBe(true);
const { driver } = result.unwrap();
expect(driver.id).toBe(userId);
expect(driver.name.toString()).toBe('RacerJohn');
expect(driver.country.toString()).toBe('US');
expect(driver.bio?.toString()).toBe('New racer on the grid');
// And: Repository should contain the driver
const savedDriver = await driverRepository.findById(userId);
expect(savedDriver).not.toBeNull();
expect(savedDriver?.id).toBe(userId);
});
it('should complete onboarding with minimal required data', async () => {
// Scenario: Complete onboarding with minimal data
// Given: A new user ID
const userId = 'user-456';
const input = {
userId,
firstName: 'Jane',
lastName: 'Smith',
displayName: 'JaneS',
country: 'UK',
};
// When: CompleteDriverOnboardingUseCase.execute() is called
const result = await completeDriverOnboardingUseCase.execute(input);
// Then: Driver should be created successfully
expect(result.isOk()).toBe(true);
const { driver } = result.unwrap();
expect(driver.id).toBe(userId);
expect(driver.bio).toBeUndefined();
});
});
describe('CompleteDriverOnboardingUseCase - Validation & Errors', () => {
it('should reject onboarding if driver already exists', async () => {
// Scenario: Already onboarded user
// Given: A driver already exists for the user
const userId = 'existing-user';
const existingInput = {
userId,
firstName: 'Old',
lastName: 'Name',
displayName: 'OldRacer',
country: 'DE',
};
await completeDriverOnboardingUseCase.execute(existingInput);
// When: CompleteDriverOnboardingUseCase.execute() is called again for same user
const result = await completeDriverOnboardingUseCase.execute({
userId,
firstName: 'New',
lastName: 'Name',
displayName: 'NewRacer',
country: 'FR',
});
// Then: Should return DRIVER_ALREADY_EXISTS error
expect(result.isErr()).toBe(true);
const error = result.unwrapErr();
expect(error.code).toBe('DRIVER_ALREADY_EXISTS');
});
it('should handle repository errors gracefully', async () => {
// Scenario: Repository error
// Given: Repository throws an error
const userId = 'error-user';
const originalCreate = driverRepository.create.bind(driverRepository);
driverRepository.create = async () => {
throw new Error('Database failure');
};
// When: CompleteDriverOnboardingUseCase.execute() is called
const result = await completeDriverOnboardingUseCase.execute({
userId,
firstName: 'John',
lastName: 'Doe',
displayName: 'RacerJohn',
country: 'US',
});
// Then: Should return REPOSITORY_ERROR
expect(result.isErr()).toBe(true);
const error = result.unwrapErr();
expect(error.code).toBe('REPOSITORY_ERROR');
expect(error.details.message).toBe('Database failure');
// Restore
driverRepository.create = originalCreate;
});
});
});