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
368 lines
13 KiB
TypeScript
368 lines
13 KiB
TypeScript
/**
|
|
* Integration Test: GetDriverUseCase Orchestration
|
|
*
|
|
* Tests the orchestration logic of GetDriverUseCase:
|
|
* - GetDriverUseCase: Retrieves a single driver by ID
|
|
* - 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 { GetDriverUseCase } from '../../../core/racing/application/use-cases/GetDriverUseCase';
|
|
import { Driver } from '../../../core/racing/domain/entities/Driver';
|
|
import { MediaReference } from '../../../core/domain/media/MediaReference';
|
|
import { Logger } from '../../../core/shared/domain/Logger';
|
|
|
|
describe('GetDriverUseCase Orchestration', () => {
|
|
let driverRepository: InMemoryDriverRepository;
|
|
let getDriverUseCase: GetDriverUseCase;
|
|
let mockLogger: Logger;
|
|
|
|
beforeAll(() => {
|
|
mockLogger = {
|
|
info: () => {},
|
|
debug: () => {},
|
|
warn: () => {},
|
|
error: () => {},
|
|
} as unknown as Logger;
|
|
|
|
driverRepository = new InMemoryDriverRepository(mockLogger);
|
|
getDriverUseCase = new GetDriverUseCase(driverRepository);
|
|
});
|
|
|
|
beforeEach(() => {
|
|
// Clear all In-Memory repositories before each test
|
|
driverRepository.clear();
|
|
});
|
|
|
|
describe('GetDriverUseCase - Success Path', () => {
|
|
it('should retrieve complete driver with all data', async () => {
|
|
// Scenario: Driver with complete profile data
|
|
// Given: A driver exists with personal information (name, avatar, bio, country)
|
|
const driverId = 'driver-123';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '12345',
|
|
name: 'John Doe',
|
|
country: 'US',
|
|
bio: 'A passionate racer with 10 years of experience',
|
|
avatarRef: MediaReference.createUploaded('avatar-123'),
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// When: GetDriverUseCase.execute() is called with driver ID
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: The result should contain all driver data
|
|
expect(result.isOk()).toBe(true);
|
|
const retrievedDriver = result.unwrap();
|
|
|
|
expect(retrievedDriver).toBeDefined();
|
|
expect(retrievedDriver.id).toBe(driverId);
|
|
expect(retrievedDriver.iracingId.toString()).toBe('12345');
|
|
expect(retrievedDriver.name.toString()).toBe('John Doe');
|
|
expect(retrievedDriver.country.toString()).toBe('US');
|
|
expect(retrievedDriver.bio?.toString()).toBe('A passionate racer with 10 years of experience');
|
|
expect(retrievedDriver.avatarRef).toBeDefined();
|
|
});
|
|
|
|
it('should retrieve driver with minimal data', async () => {
|
|
// Scenario: Driver with minimal profile data
|
|
// Given: A driver exists with only basic information (name, country)
|
|
const driverId = 'driver-456';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '67890',
|
|
name: 'Jane Smith',
|
|
country: 'UK',
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// When: GetDriverUseCase.execute() is called with driver ID
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: The result should contain basic driver info
|
|
expect(result.isOk()).toBe(true);
|
|
const retrievedDriver = result.unwrap();
|
|
|
|
expect(retrievedDriver).toBeDefined();
|
|
expect(retrievedDriver.id).toBe(driverId);
|
|
expect(retrievedDriver.iracingId.toString()).toBe('67890');
|
|
expect(retrievedDriver.name.toString()).toBe('Jane Smith');
|
|
expect(retrievedDriver.country.toString()).toBe('UK');
|
|
expect(retrievedDriver.bio).toBeUndefined();
|
|
expect(retrievedDriver.avatarRef).toBeDefined();
|
|
});
|
|
|
|
it('should retrieve driver with bio but no avatar', async () => {
|
|
// Scenario: Driver with bio but no avatar
|
|
// Given: A driver exists with bio but no avatar
|
|
const driverId = 'driver-789';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '11111',
|
|
name: 'Bob Johnson',
|
|
country: 'CA',
|
|
bio: 'Canadian racer',
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// When: GetDriverUseCase.execute() is called with driver ID
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: The result should contain driver info with bio
|
|
expect(result.isOk()).toBe(true);
|
|
const retrievedDriver = result.unwrap();
|
|
|
|
expect(retrievedDriver).toBeDefined();
|
|
expect(retrievedDriver.id).toBe(driverId);
|
|
expect(retrievedDriver.bio?.toString()).toBe('Canadian racer');
|
|
expect(retrievedDriver.avatarRef).toBeDefined();
|
|
});
|
|
|
|
it('should retrieve driver with avatar but no bio', async () => {
|
|
// Scenario: Driver with avatar but no bio
|
|
// Given: A driver exists with avatar but no bio
|
|
const driverId = 'driver-999';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '22222',
|
|
name: 'Alice Brown',
|
|
country: 'DE',
|
|
avatarRef: MediaReference.createUploaded('avatar-999'),
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// When: GetDriverUseCase.execute() is called with driver ID
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: The result should contain driver info with avatar
|
|
expect(result.isOk()).toBe(true);
|
|
const retrievedDriver = result.unwrap();
|
|
|
|
expect(retrievedDriver).toBeDefined();
|
|
expect(retrievedDriver.id).toBe(driverId);
|
|
expect(retrievedDriver.bio).toBeUndefined();
|
|
expect(retrievedDriver.avatarRef).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('GetDriverUseCase - Edge Cases', () => {
|
|
it('should handle driver with no bio', async () => {
|
|
// Scenario: Driver with no bio
|
|
// Given: A driver exists
|
|
const driverId = 'driver-no-bio';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '33333',
|
|
name: 'No Bio Driver',
|
|
country: 'FR',
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// When: GetDriverUseCase.execute() is called with driver ID
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: The result should contain driver profile
|
|
expect(result.isOk()).toBe(true);
|
|
const retrievedDriver = result.unwrap();
|
|
|
|
expect(retrievedDriver).toBeDefined();
|
|
expect(retrievedDriver.id).toBe(driverId);
|
|
expect(retrievedDriver.bio).toBeUndefined();
|
|
});
|
|
|
|
it('should handle driver with no avatar', async () => {
|
|
// Scenario: Driver with no avatar
|
|
// Given: A driver exists
|
|
const driverId = 'driver-no-avatar';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '44444',
|
|
name: 'No Avatar Driver',
|
|
country: 'ES',
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// When: GetDriverUseCase.execute() is called with driver ID
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: The result should contain driver profile
|
|
expect(result.isOk()).toBe(true);
|
|
const retrievedDriver = result.unwrap();
|
|
|
|
expect(retrievedDriver).toBeDefined();
|
|
expect(retrievedDriver.id).toBe(driverId);
|
|
expect(retrievedDriver.avatarRef).toBeDefined();
|
|
});
|
|
|
|
it('should handle driver with no data at all', async () => {
|
|
// Scenario: Driver with absolutely no data
|
|
// Given: A driver exists with only required fields
|
|
const driverId = 'driver-minimal';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '55555',
|
|
name: 'Minimal Driver',
|
|
country: 'IT',
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// When: GetDriverUseCase.execute() is called with driver ID
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: The result should contain basic driver info
|
|
expect(result.isOk()).toBe(true);
|
|
const retrievedDriver = result.unwrap();
|
|
|
|
expect(retrievedDriver).toBeDefined();
|
|
expect(retrievedDriver.id).toBe(driverId);
|
|
expect(retrievedDriver.iracingId.toString()).toBe('55555');
|
|
expect(retrievedDriver.name.toString()).toBe('Minimal Driver');
|
|
expect(retrievedDriver.country.toString()).toBe('IT');
|
|
expect(retrievedDriver.bio).toBeUndefined();
|
|
expect(retrievedDriver.avatarRef).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('GetDriverUseCase - Error Handling', () => {
|
|
it('should return null when driver does not exist', async () => {
|
|
// Scenario: Non-existent driver
|
|
// Given: No driver exists with the given ID
|
|
const driverId = 'non-existent-driver';
|
|
|
|
// When: GetDriverUseCase.execute() is called with non-existent driver ID
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: The result should be null
|
|
expect(result.isOk()).toBe(true);
|
|
expect(result.unwrap()).toBeNull();
|
|
});
|
|
|
|
it('should handle repository errors gracefully', async () => {
|
|
// Scenario: Repository throws error
|
|
// Given: A driver exists
|
|
const driverId = 'driver-error';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '66666',
|
|
name: 'Error Driver',
|
|
country: 'US',
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// Mock the repository to throw an error
|
|
const originalFindById = driverRepository.findById.bind(driverRepository);
|
|
driverRepository.findById = async () => {
|
|
throw new Error('Repository error');
|
|
};
|
|
|
|
// When: GetDriverUseCase.execute() is called
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: Should propagate the error appropriately
|
|
expect(result.isErr()).toBe(true);
|
|
const error = result.unwrapErr();
|
|
expect(error.message).toBe('Repository error');
|
|
|
|
// Restore original method
|
|
driverRepository.findById = originalFindById;
|
|
});
|
|
});
|
|
|
|
describe('GetDriverUseCase - Data Orchestration', () => {
|
|
it('should correctly retrieve driver with all fields populated', async () => {
|
|
// Scenario: Driver with all fields populated
|
|
// Given: A driver exists with all possible fields
|
|
const driverId = 'driver-complete';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '77777',
|
|
name: 'Complete Driver',
|
|
country: 'US',
|
|
bio: 'Complete driver profile with all fields',
|
|
avatarRef: MediaReference.createUploaded('avatar-complete'),
|
|
category: 'pro',
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// When: GetDriverUseCase.execute() is called
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: All fields should be correctly retrieved
|
|
expect(result.isOk()).toBe(true);
|
|
const retrievedDriver = result.unwrap();
|
|
|
|
expect(retrievedDriver.id).toBe(driverId);
|
|
expect(retrievedDriver.iracingId.toString()).toBe('77777');
|
|
expect(retrievedDriver.name.toString()).toBe('Complete Driver');
|
|
expect(retrievedDriver.country.toString()).toBe('US');
|
|
expect(retrievedDriver.bio?.toString()).toBe('Complete driver profile with all fields');
|
|
expect(retrievedDriver.avatarRef).toBeDefined();
|
|
expect(retrievedDriver.category).toBe('pro');
|
|
});
|
|
|
|
it('should correctly retrieve driver with system-default avatar', async () => {
|
|
// Scenario: Driver with system-default avatar
|
|
// Given: A driver exists with system-default avatar
|
|
const driverId = 'driver-system-avatar';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '88888',
|
|
name: 'System Avatar Driver',
|
|
country: 'US',
|
|
avatarRef: MediaReference.createSystemDefault('avatar'),
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// When: GetDriverUseCase.execute() is called
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: The avatar reference should be correctly retrieved
|
|
expect(result.isOk()).toBe(true);
|
|
const retrievedDriver = result.unwrap();
|
|
|
|
expect(retrievedDriver.avatarRef).toBeDefined();
|
|
expect(retrievedDriver.avatarRef.type).toBe('system-default');
|
|
});
|
|
|
|
it('should correctly retrieve driver with generated avatar', async () => {
|
|
// Scenario: Driver with generated avatar
|
|
// Given: A driver exists with generated avatar
|
|
const driverId = 'driver-generated-avatar';
|
|
const driver = Driver.create({
|
|
id: driverId,
|
|
iracingId: '99999',
|
|
name: 'Generated Avatar Driver',
|
|
country: 'US',
|
|
avatarRef: MediaReference.createGenerated('gen-123'),
|
|
});
|
|
|
|
await driverRepository.create(driver);
|
|
|
|
// When: GetDriverUseCase.execute() is called
|
|
const result = await getDriverUseCase.execute({ driverId });
|
|
|
|
// Then: The avatar reference should be correctly retrieved
|
|
expect(result.isOk()).toBe(true);
|
|
const retrievedDriver = result.unwrap();
|
|
|
|
expect(retrievedDriver.avatarRef).toBeDefined();
|
|
expect(retrievedDriver.avatarRef.type).toBe('generated');
|
|
});
|
|
});
|
|
});
|