/** * Integration Test: Profile Liveries Use Case Orchestration * * Tests the orchestration logic of profile liveries-related Use Cases: * - GetProfileLiveriesUseCase: Retrieves driver's uploaded liveries * - GetLiveryDetailsUseCase: Retrieves livery details * - DeleteLiveryUseCase: Deletes a livery * - Validates that Use Cases correctly interact with their Ports (Repositories, Event Publishers) * - Uses In-Memory adapters for fast, deterministic testing * * Focus: Business logic orchestration, NOT UI rendering */ import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest'; import { InMemoryDriverRepository } from '../../../adapters/drivers/persistence/inmemory/InMemoryDriverRepository'; import { InMemoryLiveryRepository } from '../../../adapters/media/persistence/inmemory/InMemoryLiveryRepository'; import { InMemoryEventPublisher } from '../../../adapters/events/InMemoryEventPublisher'; import { GetProfileLiveriesUseCase } from '../../../core/profile/use-cases/GetProfileLiveriesUseCase'; import { GetLiveryDetailsUseCase } from '../../../core/media/use-cases/GetLiveryDetailsUseCase'; import { DeleteLiveryUseCase } from '../../../core/media/use-cases/DeleteLiveryUseCase'; import { ProfileLiveriesQuery } from '../../../core/profile/ports/ProfileLiveriesQuery'; import { LiveryDetailsQuery } from '../../../core/media/ports/LiveryDetailsQuery'; import { DeleteLiveryCommand } from '../../../core/media/ports/DeleteLiveryCommand'; describe('Profile Liveries Use Case Orchestration', () => { let driverRepository: InMemoryDriverRepository; let liveryRepository: InMemoryLiveryRepository; let eventPublisher: InMemoryEventPublisher; let getProfileLiveriesUseCase: GetProfileLiveriesUseCase; let getLiveryDetailsUseCase: GetLiveryDetailsUseCase; let deleteLiveryUseCase: DeleteLiveryUseCase; beforeAll(() => { // TODO: Initialize In-Memory repositories and event publisher // driverRepository = new InMemoryDriverRepository(); // liveryRepository = new InMemoryLiveryRepository(); // eventPublisher = new InMemoryEventPublisher(); // getProfileLiveriesUseCase = new GetProfileLiveriesUseCase({ // driverRepository, // liveryRepository, // eventPublisher, // }); // getLiveryDetailsUseCase = new GetLiveryDetailsUseCase({ // liveryRepository, // eventPublisher, // }); // deleteLiveryUseCase = new DeleteLiveryUseCase({ // driverRepository, // liveryRepository, // eventPublisher, // }); }); beforeEach(() => { // TODO: Clear all In-Memory repositories before each test // driverRepository.clear(); // liveryRepository.clear(); // eventPublisher.clear(); }); describe('GetProfileLiveriesUseCase - Success Path', () => { it('should retrieve complete list of uploaded liveries', async () => { // TODO: Implement test // Scenario: Driver with multiple liveries // Given: A driver exists // And: The driver has uploaded 3 liveries // And: Each livery has different validation status (Validated/Pending) // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should contain all liveries // And: Each livery should display car name, thumbnail, and validation status // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should retrieve liveries with minimal data', async () => { // TODO: Implement test // Scenario: Driver with minimal liveries // Given: A driver exists // And: The driver has uploaded 1 livery // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should contain the livery // And: The livery should display basic information // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should retrieve liveries with validation status', async () => { // TODO: Implement test // Scenario: Driver with liveries having different validation statuses // Given: A driver exists // And: The driver has a validated livery // And: The driver has a pending livery // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should show validation status for each livery // And: Validated liveries should be clearly marked // And: Pending liveries should be clearly marked // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should retrieve liveries with upload date', async () => { // TODO: Implement test // Scenario: Driver with liveries having upload dates // Given: A driver exists // And: The driver has liveries uploaded on different dates // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should show upload date for each livery // And: The date should be formatted correctly // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should retrieve liveries with car name', async () => { // TODO: Implement test // Scenario: Driver with liveries for different cars // Given: A driver exists // And: The driver has liveries for Porsche 911 GT3, Ferrari 488, etc. // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should show car name for each livery // And: The car name should be accurate // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should retrieve liveries with car ID', async () => { // TODO: Implement test // Scenario: Driver with liveries having car IDs // Given: A driver exists // And: The driver has liveries with car IDs // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should show car ID for each livery // And: The car ID should be accurate // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should retrieve liveries with livery preview', async () => { // TODO: Implement test // Scenario: Driver with liveries having previews // Given: A driver exists // And: The driver has liveries with preview images // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should show preview image for each livery // And: The preview should be accessible // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should retrieve liveries with file metadata', async () => { // TODO: Implement test // Scenario: Driver with liveries having file metadata // Given: A driver exists // And: The driver has liveries with file size, format, etc. // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should show file metadata for each livery // And: Metadata should include file size, format, and upload date // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should retrieve liveries with file size', async () => { // TODO: Implement test // Scenario: Driver with liveries having file sizes // Given: A driver exists // And: The driver has liveries with different file sizes // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should show file size for each livery // And: The file size should be formatted correctly (e.g., MB, KB) // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should retrieve liveries with file format', async () => { // TODO: Implement test // Scenario: Driver with liveries having different file formats // Given: A driver exists // And: The driver has liveries in PNG, DDS, etc. formats // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should show file format for each livery // And: The format should be clearly indicated // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should retrieve liveries with error state', async () => { // TODO: Implement test // Scenario: Driver with liveries having error state // Given: A driver exists // And: The driver has a livery that failed to load // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should show error state for the livery // And: The livery should show error placeholder // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); }); describe('GetProfileLiveriesUseCase - Edge Cases', () => { it('should handle driver with no liveries', async () => { // TODO: Implement test // Scenario: Driver without liveries // Given: A driver exists without liveries // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should contain empty list // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should handle driver with only validated liveries', async () => { // TODO: Implement test // Scenario: Driver with only validated liveries // Given: A driver exists // And: The driver has only validated liveries // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should contain only validated liveries // And: All liveries should show Validated status // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should handle driver with only pending liveries', async () => { // TODO: Implement test // Scenario: Driver with only pending liveries // Given: A driver exists // And: The driver has only pending liveries // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should contain only pending liveries // And: All liveries should show Pending status // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should handle driver with liveries having no preview', async () => { // TODO: Implement test // Scenario: Driver with liveries having no preview // Given: A driver exists // And: The driver has liveries without preview images // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should contain liveries // And: Preview section should show placeholder // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); it('should handle driver with liveries having no metadata', async () => { // TODO: Implement test // Scenario: Driver with liveries having no metadata // Given: A driver exists // And: The driver has liveries without file metadata // When: GetProfileLiveriesUseCase.execute() is called with driver ID // Then: The result should contain liveries // And: Metadata section should be empty // And: EventPublisher should emit ProfileLiveriesAccessedEvent }); }); describe('GetProfileLiveriesUseCase - Error Handling', () => { it('should throw error when driver does not exist', async () => { // TODO: Implement test // Scenario: Non-existent driver // Given: No driver exists with the given ID // When: GetProfileLiveriesUseCase.execute() is called with non-existent driver ID // Then: Should throw DriverNotFoundError // And: EventPublisher should NOT emit any events }); it('should throw error when driver ID is invalid', async () => { // TODO: Implement test // Scenario: Invalid driver ID // Given: An invalid driver ID (e.g., empty string, null, undefined) // When: GetProfileLiveriesUseCase.execute() is called with invalid driver ID // Then: Should throw ValidationError // And: EventPublisher should NOT emit any events }); it('should handle repository errors gracefully', async () => { // TODO: Implement test // Scenario: Repository throws error // Given: A driver exists // And: DriverRepository throws an error during query // When: GetProfileLiveriesUseCase.execute() is called // Then: Should propagate the error appropriately // And: EventPublisher should NOT emit any events }); }); describe('GetLiveryDetailsUseCase - Success Path', () => { it('should retrieve complete livery details', async () => { // TODO: Implement test // Scenario: Livery with complete details // Given: A livery exists with complete information // And: The livery has car name, car ID, validation status, upload date // And: The livery has file size, format, preview // When: GetLiveryDetailsUseCase.execute() is called with livery ID // Then: The result should contain all livery details // And: EventPublisher should emit LiveryDetailsAccessedEvent }); it('should retrieve livery details with minimal information', async () => { // TODO: Implement test // Scenario: Livery with minimal details // Given: A livery exists with minimal information // And: The livery has only car name and validation status // When: GetLiveryDetailsUseCase.execute() is called with livery ID // Then: The result should contain basic livery details // And: EventPublisher should emit LiveryDetailsAccessedEvent }); it('should retrieve livery details with validation status', async () => { // TODO: Implement test // Scenario: Livery with validation status // Given: A livery exists with validation status // When: GetLiveryDetailsUseCase.execute() is called with livery ID // Then: The result should show validation status // And: The status should be clearly indicated // And: EventPublisher should emit LiveryDetailsAccessedEvent }); it('should retrieve livery details with file metadata', async () => { // TODO: Implement test // Scenario: Livery with file metadata // Given: A livery exists with file metadata // When: GetLiveryDetailsUseCase.execute() is called with livery ID // Then: The result should show file metadata // And: Metadata should include file size, format, and upload date // And: EventPublisher should emit LiveryDetailsAccessedEvent }); it('should retrieve livery details with preview', async () => { // TODO: Implement test // Scenario: Livery with preview // Given: A livery exists with preview image // When: GetLiveryDetailsUseCase.execute() is called with livery ID // Then: The result should show preview image // And: The preview should be accessible // And: EventPublisher should emit LiveryDetailsAccessedEvent }); }); describe('GetLiveryDetailsUseCase - Error Handling', () => { it('should throw error when livery does not exist', async () => { // TODO: Implement test // Scenario: Non-existent livery // Given: No livery exists with the given ID // When: GetLiveryDetailsUseCase.execute() is called with non-existent livery ID // Then: Should throw LiveryNotFoundError // And: EventPublisher should NOT emit any events }); it('should throw error when livery ID is invalid', async () => { // TODO: Implement test // Scenario: Invalid livery ID // Given: An invalid livery ID (e.g., empty string, null, undefined) // When: GetLiveryDetailsUseCase.execute() is called with invalid livery ID // Then: Should throw ValidationError // And: EventPublisher should NOT emit any events }); }); describe('DeleteLiveryUseCase - Success Path', () => { it('should allow driver to delete a livery', async () => { // TODO: Implement test // Scenario: Driver deletes a livery // Given: A driver exists // And: The driver has uploaded a livery // When: DeleteLiveryUseCase.execute() is called with driver ID and livery ID // Then: The livery should be removed from the driver's list // And: EventPublisher should emit LiveryDeletedEvent }); it('should allow driver to delete multiple liveries', async () => { // TODO: Implement test // Scenario: Driver deletes multiple liveries // Given: A driver exists // And: The driver has uploaded 3 liveries // When: DeleteLiveryUseCase.execute() is called for each livery // Then: All liveries should be removed from the driver's list // And: EventPublisher should emit LiveryDeletedEvent for each livery }); it('should allow driver to delete validated livery', async () => { // TODO: Implement test // Scenario: Driver deletes validated livery // Given: A driver exists // And: The driver has a validated livery // When: DeleteLiveryUseCase.execute() is called with driver ID and livery ID // Then: The validated livery should be removed // And: EventPublisher should emit LiveryDeletedEvent }); it('should allow driver to delete pending livery', async () => { // TODO: Implement test // Scenario: Driver deletes pending livery // Given: A driver exists // And: The driver has a pending livery // When: DeleteLiveryUseCase.execute() is called with driver ID and livery ID // Then: The pending livery should be removed // And: EventPublisher should emit LiveryDeletedEvent }); }); describe('DeleteLiveryUseCase - Validation', () => { it('should reject deleting livery when driver is not owner', async () => { // TODO: Implement test // Scenario: Driver not owner of livery // Given: A driver exists // And: The driver is not the owner of a livery // When: DeleteLiveryUseCase.execute() is called with driver ID and livery ID // Then: Should throw NotOwnerError // And: EventPublisher should NOT emit any events }); it('should reject deleting livery with invalid livery ID', async () => { // TODO: Implement test // Scenario: Invalid livery ID // Given: A driver exists // When: DeleteLiveryUseCase.execute() is called with invalid livery ID // Then: Should throw ValidationError // And: EventPublisher should NOT emit any events }); }); describe('DeleteLiveryUseCase - Error Handling', () => { it('should throw error when driver does not exist', async () => { // TODO: Implement test // Scenario: Non-existent driver // Given: No driver exists with the given ID // When: DeleteLiveryUseCase.execute() is called with non-existent driver ID // Then: Should throw DriverNotFoundError // And: EventPublisher should NOT emit any events }); it('should throw error when livery does not exist', async () => { // TODO: Implement test // Scenario: Non-existent livery // Given: A driver exists // And: No livery exists with the given ID // When: DeleteLiveryUseCase.execute() is called with non-existent livery ID // Then: Should throw LiveryNotFoundError // And: EventPublisher should NOT emit any events }); it('should handle repository errors gracefully', async () => { // TODO: Implement test // Scenario: Repository throws error // Given: A driver exists // And: LiveryRepository throws an error during delete // When: DeleteLiveryUseCase.execute() is called // Then: Should propagate the error appropriately // And: EventPublisher should NOT emit any events }); }); describe('Profile Liveries Data Orchestration', () => { it('should correctly format validation status with visual cues', async () => { // TODO: Implement test // Scenario: Livery validation status formatting // Given: A driver exists // And: The driver has a validated livery // And: The driver has a pending livery // When: GetProfileLiveriesUseCase.execute() is called // Then: Validated liveries should show "Validated" status with green indicator // And: Pending liveries should show "Pending" status with yellow indicator }); it('should correctly format upload date', async () => { // TODO: Implement test // Scenario: Livery upload date formatting // Given: A driver exists // And: The driver has a livery uploaded on 2024-01-15 // When: GetProfileLiveriesUseCase.execute() is called // Then: Upload date should show as "January 15, 2024" or similar format }); it('should correctly format file size', async () => { // TODO: Implement test // Scenario: Livery file size formatting // Given: A driver exists // And: The driver has a livery with file size 5242880 bytes (5 MB) // When: GetProfileLiveriesUseCase.execute() is called // Then: File size should show as "5 MB" or "5.0 MB" }); it('should correctly format file format', async () => { // TODO: Implement test // Scenario: Livery file format formatting // Given: A driver exists // And: The driver has liveries in PNG and DDS formats // When: GetProfileLiveriesUseCase.execute() is called // Then: File format should show as "PNG" or "DDS" }); it('should correctly filter liveries by validation status', async () => { // TODO: Implement test // Scenario: Livery filtering by validation status // Given: A driver exists // And: The driver has 2 validated liveries and 1 pending livery // When: GetProfileLiveriesUseCase.execute() is called with status filter "Validated" // Then: The result should show only the 2 validated liveries // And: The pending livery should be hidden }); it('should correctly search liveries by car name', async () => { // TODO: Implement test // Scenario: Livery search by car name // Given: A driver exists // And: The driver has liveries for "Porsche 911 GT3" and "Ferrari 488" // When: GetProfileLiveriesUseCase.execute() is called with search term "Porsche" // Then: The result should show only "Porsche 911 GT3" livery // And: "Ferrari 488" livery should be hidden }); it('should correctly identify livery owner', async () => { // TODO: Implement test // Scenario: Livery owner identification // Given: A driver exists // And: The driver has uploaded a livery // When: GetProfileLiveriesUseCase.execute() is called // Then: The livery should be associated with the driver // And: The driver should be able to delete the livery }); it('should correctly handle livery error state', async () => { // TODO: Implement test // Scenario: Livery error state handling // Given: A driver exists // And: The driver has a livery that failed to load // When: GetProfileLiveriesUseCase.execute() is called // Then: The livery should show error state // And: The livery should show retry option }); }); });