import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { PlaywrightAutomationAdapter, FixtureServer, } from 'packages/automation/infrastructure/adapters/automation'; import { InMemorySessionRepository } from 'packages/automation/infrastructure/repositories/InMemorySessionRepository'; import { AutomationEngineAdapter } from 'packages/automation/infrastructure/adapters/automation/engine/AutomationEngineAdapter'; import { StartAutomationSessionUseCase } from 'packages/automation/application/use-cases/StartAutomationSessionUseCase'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; import { PinoLogAdapter } from 'packages/automation/infrastructure/adapters/logging/PinoLogAdapter'; describe('Workflow – hosted session end-to-end (fixture-backed, real stack)', () => { let server: FixtureServer; let adapter: PlaywrightAutomationAdapter; let baseUrl: string; beforeAll(async () => { server = new FixtureServer(); const info = await server.start(); baseUrl = info.url; const logger = new PinoLogAdapter(); adapter = new PlaywrightAutomationAdapter( { headless: true, timeout: 10_000, baseUrl, mode: 'real', userDataDir: '', }, logger, ); const connectResult = await adapter.connect(false); expect(connectResult.success).toBe(true); expect(adapter.isConnected()).toBe(true); }); afterAll(async () => { await adapter.disconnect(); await server.stop(); }); function createRealEngine() { const repository = new InMemorySessionRepository(); const engine = new AutomationEngineAdapter(adapter, repository); const useCase = new StartAutomationSessionUseCase(engine, adapter, repository); return { repository, engine, useCase }; } it( 'runs 1–17 from use case and stops automation at manual Track Conditions (STOPPED_AT_STEP_18)', async () => { const { repository, engine, useCase } = createRealEngine(); const config: any = { sessionName: 'Fixture E2E – full workflow (real stack)', trackId: 'spa', carIds: ['dallara-f3'], }; const dto = await useCase.execute(config); expect(dto.state).toBe('PENDING'); expect(dto.currentStep).toBe(1); await adapter.navigateToPage(server.getFixtureUrl(1)); await engine.executeStep(StepId.create(1), config); const deadline = Date.now() + 60_000; let finalSession = null; // eslint-disable-next-line no-constant-condition while (true) { const sessions = await repository.findAll(); finalSession = sessions[0] ?? null; if (finalSession && finalSession.state.isStoppedAtStep18()) { break; } if (Date.now() > deadline) { throw new Error('Timed out waiting for automation workflow to complete'); } await new Promise((resolve) => setTimeout(resolve, 250)); } expect(finalSession).not.toBeNull(); expect(finalSession!.state.isStoppedAtStep18()).toBe(true); expect(finalSession!.currentStep.value).toBe(17); expect(finalSession!.startedAt).toBeInstanceOf(Date); expect(finalSession!.completedAt).toBeInstanceOf(Date); expect(finalSession!.errorMessage).toBeUndefined(); }, ); });