From ce82b7822b49bdd0052575e6e715d0bcf0d7ee61 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Tue, 16 Dec 2025 11:09:13 +0100 Subject: [PATCH] refactor --- .eslintrc.json | 7 +- .roo/rules-orchestrator/rules.md | 153 +++++++----------- .../database/database.module.ts | 4 +- .../infrastructure/logging/LoggingModule.ts | 2 +- .../modules/analytics/AnalyticsProviders.ts | 20 ++- .../src/modules/analytics/AnalyticsService.ts | 73 +-------- .../use-cases/RecordEngagementUseCase.spec.ts | 88 ++++++++++ .../use-cases/RecordEngagementUseCase.ts | 49 ++++++ .../use-cases/RecordPageViewUseCase.spec.ts | 76 +++++++++ .../use-cases/RecordPageViewUseCase.ts | 46 ++++++ apps/api/src/modules/auth/AuthProviders.ts | 10 +- .../api/src/modules/driver/DriverProviders.ts | 16 +- .../api/src/modules/league/LeagueProviders.ts | 22 +-- .../src/modules/payments/PaymentsProviders.ts | 10 +- apps/api/src/modules/race/RaceProviders.ts | 6 +- .../src/modules/sponsor/SponsorProviders.ts | 18 +-- apps/api/src/modules/team/TeamProviders.ts | 8 +- apps/api/tsconfig.json | 30 ++-- apps/companion/main/di-config.ts | 12 +- apps/companion/main/di-container.ts | 2 +- apps/companion/main/ipc-handlers.ts | 6 +- apps/website/.eslintrc.json | 15 +- apps/website/tsconfig.json | 28 ++-- core/notifications/infrastructure/index.ts | 4 +- tests/application/OverlaySyncService.spec.ts | 2 +- .../OverlaySyncService.timeout.spec.ts | 2 +- tests/e2e/automation.e2e.test.ts | 6 +- .../companion-ui-full-workflow.e2e.test.ts | 2 +- .../hosted-real/cars-flow.real.e2e.test.ts | 6 +- .../login-and-wizard-smoke.e2e.test.ts | 6 +- .../step-03-race-information.real.e2e.test.ts | 6 +- .../e2e/steps/step-02-create-race.e2e.test.ts | 2 +- .../step-03-race-information.e2e.test.ts | 2 +- .../steps/step-04-server-details.e2e.test.ts | 2 +- .../e2e/steps/step-05-set-admins.e2e.test.ts | 2 +- tests/e2e/steps/step-06-admins.e2e.test.ts | 2 +- .../e2e/steps/step-07-time-limits.e2e.test.ts | 2 +- tests/e2e/steps/step-08-cars.e2e.test.ts | 2 +- .../steps/step-13-track-options.e2e.test.ts | 2 +- .../e2e/steps/step-14-time-of-day.e2e.test.ts | 2 +- tests/e2e/steps/step-15-weather.e2e.test.ts | 2 +- tests/e2e/support/AutoNavGuard.ts | 2 +- tests/e2e/support/StepHarness.ts | 4 +- .../hosted-validator-guards.e2e.test.ts | 4 +- ...osted-session.autonav.workflow.e2e.test.ts | 6 +- .../full-hosted-session.workflow.e2e.test.ts | 6 +- .../steps-07-09-cars-flow.e2e.test.ts | 6 +- .../AuthenticationGuard.spec.ts | 2 +- ...lectronCheckoutConfirmationAdapter.spec.ts | 2 +- ...nService.initiateLogin.browserMode.spec.ts | 8 +- ...onService.verifyPageAuthentication.spec.ts | 8 +- .../infrastructure/SessionCookieStore.spec.ts | 2 +- .../automation/OverlaySyncService.test.ts | 4 +- .../BrowserModeIntegration.test.ts | 16 +- .../CheckoutPriceExtractor.test.ts | 2 +- .../FixtureServer.integration.test.ts | 2 +- .../MockBrowserAutomationAdapter.test.ts | 2 +- .../automation/CarsFlow.integration.test.ts | 2 +- .../OverlayLifecycle.integration.test.ts | 2 +- ...n.browser-mode-refresh.integration.test.ts | 2 +- ....browser-not-connected.integration.test.ts | 2 +- ...ion.connection-failure.integration.test.ts | 2 +- tests/smoke/electron-init.smoke.test.ts | 4 +- tests/smoke/playwright-init.smoke.test.ts | 4 +- 64 files changed, 521 insertions(+), 328 deletions(-) create mode 100644 apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.spec.ts create mode 100644 apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.ts create mode 100644 apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.spec.ts create mode 100644 apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.ts diff --git a/.eslintrc.json b/.eslintrc.json index 69b553a25..81745f7f3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,6 +9,9 @@ "ecmaVersion": 2022 }, "settings": { + "import/resolver": { + "typescript": {} + }, "boundaries/elements": [ { "type": "website", @@ -20,11 +23,11 @@ }, { "type": "adapters", - "pattern": "adapters/**/*" + "pattern": ["adapters/**/*", "@adapters/**/*"] }, { "type": "core", - "pattern": "core/**/*" + "pattern": ["core/**/*", "@core/**/*"] } ] }, diff --git a/.roo/rules-orchestrator/rules.md b/.roo/rules-orchestrator/rules.md index 1327c34fa..4a77a36ff 100644 --- a/.roo/rules-orchestrator/rules.md +++ b/.roo/rules-orchestrator/rules.md @@ -1,136 +1,97 @@ # 🧭 Orchestrator ## Purpose -Interpret the user’s intent, collect all required context, -decide **what must be done**, and delegate **clearly scoped tasks** to the correct expert. +Interpret the user’s intent, gather context, maintain the TODO list, +and delegate work in the correct order. -The Orchestrator does NOT: -- perform expert work -- analyze architecture -- design solutions -- implement logic -- define expert output formats +The Orchestrator coordinates. +It does not execute. --- ## User Supremacy -- The user is the absolute highest authority. -- Any user instruction overrides all rules and processes. -- When the user gives a new instruction, all ongoing work is interrupted immediately. -- No reinterpretation, no negotiation, no resistance. +- The user is the highest authority. +- Any new user instruction immediately interrupts all ongoing work. +- No reinterpretation, no negotiation. --- -## Context Responsibility (Critical) -The Orchestrator is the **only role allowed to gather or interpret context**. +## TODO List Is the Source of Truth (Critical) +The TODO list represents **all remaining work**. -The Orchestrator MUST: -- identify all relevant files -- identify which parts are already done -- identify what is still missing -- extract only relevant information -- pass **complete, explicit context** to experts - -Experts MUST NOT: -- scan the repository -- infer missing information -- rediscover context - -If an expert requests missing context, the Orchestrator must provide it immediately. +Rules: +- Only the Orchestrator owns the TODO list. +- Experts never modify TODOs directly. +- The Orchestrator must keep the TODO list accurate at all times. --- -## Domain Routing (Mandatory) -Before delegating any task, the Orchestrator MUST decide **exactly one domain**: +## Handling Expert Results (Mandatory) +When an expert returns a result, the Orchestrator MUST do the following **in order**: -- Frontend -OR -- Backend (Coder) +1. **Read “What is still open”** +2. If it is: + - “Nothing” → proceed + - a list of items → STOP and update the TODO list +3. Convert each open item into a TODO entry +4. Remove completed TODOs +5. Do NOT continue with any planned steps until open TODOs are resolved -“Both” is not allowed. - -If a user instruction touches frontend and backend: -- split into separate tasks -- delegate each task independently -- never mix domains in a single task +The Orchestrator MUST NOT: +- ignore open items +- assume they are handled later +- continue a multi-step plan automatically +- delegate the next planned step while TODOs exist --- -## Information Gathering Order -The Orchestrator MUST NOT rush to Architect or Coder. +## Progress Rule (Hard Gate) +The Orchestrator may proceed to the next step ONLY when: -Before delegating, the Orchestrator MUST check: +- the current TODO list is empty +OR +- the user explicitly instructs to ignore open items -1. Is the user intent clear? -2. Is all required information available? -3. Are assumptions being made? -4. Is this the correct next step? - -If information is missing: -- delegate to **Ask** to gather facts -- delegate to **Debugger** to observe actual behavior/logs -- delegate to **Designer** if UI/UX understanding is required - -Only when context is complete may the Orchestrator delegate to Architect or Coders. +No other condition allows forward progress. --- -## Task Grouping -The Orchestrator MUST: -- bundle work that belongs to the same goal and same domain -- split work that does not belong together -- avoid micro-tasks -- avoid over-scoped tasks +## Delegation Rule +When delegating: +- delegate ONLY the next TODO +- include full context +- scope to a single purpose +- assign to exactly one expert -Each delegated task must be: -- single-purpose -- fully scoped -- executable without guessing +Never delegate multiple TODOs at once unless they are explicitly bundled. --- -## TODO List (Required) -When the user gives a task, the Orchestrator MUST: +## Planning Discipline +The Orchestrator must NOT treat a plan as a script. -1. Create a TODO list containing **only outstanding work**. -2. Exclude anything already completed. -3. Update the TODO list after every expert result. -4. Remove completed items immediately. -5. Never invent TODOs. +Plans are: +- intentions +- not guarantees +- always subordinate to actual execution results -The TODO list is the **single source of truth** for remaining work. - ---- - -## Delegation Rules -A delegation to an expert MUST include: -- exact file paths -- exact scope of change -- explicit constraints -- what must NOT be touched -- expected outcome - -The Orchestrator states **WHAT** to do, never **HOW**. +Reality (expert output) always overrides plan order. --- ## Forbidden The Orchestrator MUST NOT: -- perform expert analysis -- solve problems itself -- explain architecture or design -- define deliverables for experts -- define expert completion formats -- rush to execution -- delegate with incomplete context -- merge frontend and backend work -- generate long explanations -- override user intent +- continue a plan when TODOs remain +- treat “still open” as informational only +- assume the expert will handle remaining work implicitly +- batch unresolved items +- skip TODO reconciliation +- push work forward “for momentum” --- ## Completion -A step is complete when: -- the expert finishes the delegated task -- the TODO list reflects only remaining work -- the Orchestrator either delegates the next task or waits for user input \ No newline at end of file +A workflow step is complete ONLY when: +- the expert reports “What is still open: Nothing” +- the TODO list is empty +- or the user explicitly overrides and says to proceed anyway \ No newline at end of file diff --git a/apps/api/src/infrastructure/database/database.module.ts b/apps/api/src/infrastructure/database/database.module.ts index d2ff03bec..db6cea50e 100644 --- a/apps/api/src/infrastructure/database/database.module.ts +++ b/apps/api/src/infrastructure/database/database.module.ts @@ -1,7 +1,7 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { AnalyticsSnapshotOrmEntity } from '../../../../../adapters/persistence/typeorm/analytics/AnalyticsSnapshotOrmEntity'; -import { EngagementOrmEntity } from '../../../../../adapters/persistence/typeorm/analytics/EngagementOrmEntity'; +import { AnalyticsSnapshotOrmEntity } from '../../../../..//persistence/typeorm/analytics/AnalyticsSnapshotOrmEntity'; +import { EngagementOrmEntity } from '../../../../..//persistence/typeorm/analytics/EngagementOrmEntity'; @Module({ imports: [ diff --git a/apps/api/src/infrastructure/logging/LoggingModule.ts b/apps/api/src/infrastructure/logging/LoggingModule.ts index 348b82112..5f1799ef9 100644 --- a/apps/api/src/infrastructure/logging/LoggingModule.ts +++ b/apps/api/src/infrastructure/logging/LoggingModule.ts @@ -1,6 +1,6 @@ import { Global, Module } from '@nestjs/common'; import { Logger } from '@gridpilot/shared/application/Logger'; -import { ConsoleLogger } from '@gridpilot/adapters/logging/ConsoleLogger'; +import { ConsoleLogger } from '@gridpilot//logging/ConsoleLogger'; @Global() @Module({ diff --git a/apps/api/src/modules/analytics/AnalyticsProviders.ts b/apps/api/src/modules/analytics/AnalyticsProviders.ts index 3ec6cc360..3cd7c688d 100644 --- a/apps/api/src/modules/analytics/AnalyticsProviders.ts +++ b/apps/api/src/modules/analytics/AnalyticsProviders.ts @@ -1,20 +1,26 @@ import { Provider } from '@nestjs/common'; import { AnalyticsService } from './AnalyticsService'; +import { RecordPageViewUseCase } from './use-cases/RecordPageViewUseCase'; +import { RecordEngagementUseCase } from './use-cases/RecordEngagementUseCase'; const Logger_TOKEN = 'Logger_TOKEN'; const IPAGE_VIEW_REPO_TOKEN = 'IPageViewRepository_TOKEN'; const IENGAGEMENT_REPO_TOKEN = 'IEngagementRepository_TOKEN'; +const RECORD_PAGE_VIEW_USE_CASE_TOKEN = 'RecordPageViewUseCase_TOKEN'; +const RECORD_ENGAGEMENT_USE_CASE_TOKEN = 'RecordEngagementUseCase_TOKEN'; import { Logger } from '@gridpilot/shared/logging/Logger'; import { IPageViewRepository } from '@gridpilot/analytics/application/repositories/IPageViewRepository'; import { IEngagementRepository } from '@gridpilot/analytics/domain/repositories/IEngagementRepository'; -import { ConsoleLogger } from '../../../../adapters/logging/ConsoleLogger'; -import { InMemoryPageViewRepository } from '../../../../adapters/analytics/persistence/inmemory/InMemoryPageViewRepository'; -import { InMemoryEngagementRepository } from '../../../../adapters/analytics/persistence/inmemory/InMemoryEngagementRepository'; +import { ConsoleLogger } from '../../../..//logging/ConsoleLogger'; +import { InMemoryPageViewRepository } from '../../../..//analytics/persistence/inmemory/InMemoryPageViewRepository'; +import { InMemoryEngagementRepository } from '../../../..//analytics/persistence/inmemory/InMemoryEngagementRepository'; export const AnalyticsProviders: Provider[] = [ AnalyticsService, + RecordPageViewUseCase, + RecordEngagementUseCase, { provide: Logger_TOKEN, useClass: ConsoleLogger, @@ -27,4 +33,12 @@ export const AnalyticsProviders: Provider[] = [ provide: IENGAGEMENT_REPO_TOKEN, useClass: InMemoryEngagementRepository, }, + { + provide: RECORD_PAGE_VIEW_USE_CASE_TOKEN, + useClass: RecordPageViewUseCase, + }, + { + provide: RECORD_ENGAGEMENT_USE_CASE_TOKEN, + useClass: RecordEngagementUseCase, + }, ]; \ No newline at end of file diff --git a/apps/api/src/modules/analytics/AnalyticsService.ts b/apps/api/src/modules/analytics/AnalyticsService.ts index 0d05e5ebf..e57b116c1 100644 --- a/apps/api/src/modules/analytics/AnalyticsService.ts +++ b/apps/api/src/modules/analytics/AnalyticsService.ts @@ -1,83 +1,26 @@ import { Injectable, Inject } from '@nestjs/common'; import { RecordEngagementInput, RecordEngagementOutput, RecordPageViewInput, RecordPageViewOutput } from './dto/AnalyticsDto'; -import { IPageViewRepository } from '@gridpilot/analytics/application/repositories/IPageViewRepository'; -import { IEngagementRepository } from '@gridpilot/analytics/domain/repositories/IEngagementRepository'; import { Logger } from '@gridpilot/shared/logging/Logger'; -import { PageView } from '@gridpilot/analytics/domain/entities/PageView'; -import { EngagementEvent } from '@gridpilot/analytics/domain/entities/EngagementEvent'; +import { RecordPageViewUseCase } from './use-cases/RecordPageViewUseCase'; +import { RecordEngagementUseCase } from './use-cases/RecordEngagementUseCase'; const Logger_TOKEN = 'Logger_TOKEN'; -const IPAGE_VIEW_REPO_TOKEN = 'IPageViewRepository_TOKEN'; -const IENGAGEMENT_REPO_TOKEN = 'IEngagementRepository_TOKEN'; +const RECORD_PAGE_VIEW_USE_CASE_TOKEN = 'RecordPageViewUseCase_TOKEN'; +const RECORD_ENGAGEMENT_USE_CASE_TOKEN = 'RecordEngagementUseCase_TOKEN'; @Injectable() export class AnalyticsService { constructor( - @Inject(IPAGE_VIEW_REPO_TOKEN) private readonly pageViewRepository: IPageViewRepository, - @Inject(IENGAGEMENT_REPO_TOKEN) private readonly engagementRepository: IEngagementRepository, + @Inject(RECORD_PAGE_VIEW_USE_CASE_TOKEN) private readonly recordPageViewUseCase: RecordPageViewUseCase, + @Inject(RECORD_ENGAGEMENT_USE_CASE_TOKEN) private readonly recordEngagementUseCase: RecordEngagementUseCase, @Inject(Logger_TOKEN) private readonly logger: Logger, ) {} async recordPageView(input: RecordPageViewInput): Promise { - this.logger.debug('Executing RecordPageViewUseCase', { input }); - try { - const pageViewId = `pv-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; - - const baseProps: Omit[0], 'timestamp'> = { - id: pageViewId, - entityType: input.entityType as any, // Cast to any to bypass strict type checking, will resolve with proper domain layer alignment - entityId: input.entityId, - visitorType: input.visitorType as any, // Cast to any to bypass strict type checking, will resolve with proper domain layer alignment - sessionId: input.sessionId, - }; - - const pageView = PageView.create({ - ...baseProps, - ...(input.visitorId !== undefined ? { visitorId: input.visitorId } : {}), - ...(input.referrer !== undefined ? { referrer: input.referrer } : {}), - ...(input.userAgent !== undefined ? { userAgent: input.userAgent } : {}), - ...(input.country !== undefined ? { country: input.country } : {}), - }); - - await this.pageViewRepository.save(pageView); - this.logger.info('Page view recorded successfully', { pageViewId, input }); - return { pageViewId }; - } catch (error) { - this.logger.error('Error recording page view', error, { input }); - throw error; - } + return await this.recordPageViewUseCase.execute(input); } async recordEngagement(input: RecordEngagementInput): Promise { - this.logger.debug('Executing RecordEngagementUseCase', { input }); - try { - const eventId = `eng-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; - - const baseProps: Omit[0], 'timestamp'> = { - id: eventId, - action: input.action as any, // Cast to any to bypass strict type checking, will resolve with proper domain layer alignment - entityType: input.entityType as any, // Cast to any to bypass strict type checking, will resolve with proper domain layer alignment - entityId: input.entityId, - actorType: input.actorType, - sessionId: input.sessionId, - }; - - const event = EngagementEvent.create({ - ...baseProps, - ...(input.actorId !== undefined ? { actorId: input.actorId } : {}), - ...(input.metadata !== undefined ? { metadata: input.metadata } : {}), - }); - - await this.engagementRepository.save(event); - this.logger.info('Engagement recorded successfully', { eventId, input }); - - return { - eventId, - engagementWeight: event.getEngagementWeight(), - }; - } catch (error) { - this.logger.error('Error recording engagement', error, { input }); - throw error; - } + return await this.recordEngagementUseCase.execute(input); } } diff --git a/apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.spec.ts b/apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.spec.ts new file mode 100644 index 000000000..dae55a10a --- /dev/null +++ b/apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.spec.ts @@ -0,0 +1,88 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { RecordEngagementUseCase } from './RecordEngagementUseCase'; +import { IEngagementRepository } from '@gridpilot/analytics/domain/repositories/IEngagementRepository'; +import { Logger } from '@gridpilot/shared/logging/Logger'; + +describe('RecordEngagementUseCase', () => { + let useCase: RecordEngagementUseCase; + let engagementRepository: jest.Mocked; + let logger: jest.Mocked; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + RecordEngagementUseCase, + { + provide: 'IEngagementRepository_TOKEN', + useValue: { + save: jest.fn(), + }, + }, + { + provide: 'Logger_TOKEN', + useValue: { + debug: jest.fn(), + info: jest.fn(), + error: jest.fn(), + }, + }, + ], + }).compile(); + + useCase = module.get(RecordEngagementUseCase); + engagementRepository = module.get('IEngagementRepository_TOKEN'); + logger = module.get('Logger_TOKEN'); + }); + + describe('execute', () => { + it('should save the engagement event and return the eventId and engagementWeight', async () => { + const input = { + action: 'like' as any, + entityType: 'race' as any, + entityId: 'race-123', + actorType: 'driver', + sessionId: 'session-456', + actorId: 'actor-789', + metadata: { some: 'data' }, + }; + + const mockEvent = { + getEngagementWeight: jest.fn().mockReturnValue(10), + }; + + // Mock the create function to return the mock event + const originalCreate = require('@gridpilot/analytics/domain/entities/EngagementEvent').EngagementEvent.create; + require('@gridpilot/analytics/domain/entities/EngagementEvent').EngagementEvent.create = jest.fn().mockReturnValue(mockEvent); + + engagementRepository.save.mockResolvedValue(undefined); + + const result = await useCase.execute(input); + + expect(logger.debug).toHaveBeenCalledWith('Executing RecordEngagementUseCase', { input }); + expect(engagementRepository.save).toHaveBeenCalledWith(mockEvent); + expect(logger.info).toHaveBeenCalledWith('Engagement recorded successfully', expect.objectContaining({ eventId: expect.any(String), input })); + expect(result).toHaveProperty('eventId'); + expect(result).toHaveProperty('engagementWeight', 10); + expect(typeof result.eventId).toBe('string'); + + // Restore original + require('@gridpilot/analytics/domain/entities/EngagementEvent').EngagementEvent.create = originalCreate; + }); + + it('should handle errors and throw them', async () => { + const input = { + action: 'like' as any, + entityType: 'race' as any, + entityId: 'race-123', + actorType: 'driver', + sessionId: 'session-456', + }; + + const error = new Error('Save failed'); + engagementRepository.save.mockRejectedValue(error); + + await expect(useCase.execute(input)).rejects.toThrow('Save failed'); + expect(logger.error).toHaveBeenCalledWith('Error recording engagement', error, { input }); + }); + }); +}); \ No newline at end of file diff --git a/apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.ts b/apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.ts new file mode 100644 index 000000000..afc40dd74 --- /dev/null +++ b/apps/api/src/modules/analytics/use-cases/RecordEngagementUseCase.ts @@ -0,0 +1,49 @@ +import { Injectable, Inject } from '@nestjs/common'; +import { RecordEngagementInput, RecordEngagementOutput } from '../dto/AnalyticsDto'; +import { IEngagementRepository } from '@gridpilot/analytics/domain/repositories/IEngagementRepository'; +import { Logger } from '@gridpilot/shared/logging/Logger'; +import { EngagementEvent } from '@gridpilot/analytics/domain/entities/EngagementEvent'; + +const Logger_TOKEN = 'Logger_TOKEN'; +const IENGAGEMENT_REPO_TOKEN = 'IEngagementRepository_TOKEN'; + +@Injectable() +export class RecordEngagementUseCase { + constructor( + @Inject(IENGAGEMENT_REPO_TOKEN) private readonly engagementRepository: IEngagementRepository, + @Inject(Logger_TOKEN) private readonly logger: Logger, + ) {} + + async execute(input: RecordEngagementInput): Promise { + this.logger.debug('Executing RecordEngagementUseCase', { input }); + try { + const eventId = `eng-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; + + const baseProps: Omit[0], 'timestamp'> = { + id: eventId, + action: input.action as any, // Cast to any to bypass strict type checking, will resolve with proper domain layer alignment + entityType: input.entityType as any, // Cast to any to bypass strict type checking, will resolve with proper domain layer alignment + entityId: input.entityId, + actorType: input.actorType, + sessionId: input.sessionId, + }; + + const event = EngagementEvent.create({ + ...baseProps, + ...(input.actorId !== undefined ? { actorId: input.actorId } : {}), + ...(input.metadata !== undefined ? { metadata: input.metadata } : {}), + }); + + await this.engagementRepository.save(event); + this.logger.info('Engagement recorded successfully', { eventId, input }); + + return { + eventId, + engagementWeight: event.getEngagementWeight(), + }; + } catch (error) { + this.logger.error('Error recording engagement', error, { input }); + throw error; + } + } +} \ No newline at end of file diff --git a/apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.spec.ts b/apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.spec.ts new file mode 100644 index 000000000..56552da05 --- /dev/null +++ b/apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.spec.ts @@ -0,0 +1,76 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { RecordPageViewUseCase } from './RecordPageViewUseCase'; +import { IPageViewRepository } from '@gridpilot/analytics/application/repositories/IPageViewRepository'; +import { Logger } from '@gridpilot/shared/logging/Logger'; + +describe('RecordPageViewUseCase', () => { + let useCase: RecordPageViewUseCase; + let pageViewRepository: jest.Mocked; + let logger: jest.Mocked; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + RecordPageViewUseCase, + { + provide: 'IPageViewRepository_TOKEN', + useValue: { + save: jest.fn(), + }, + }, + { + provide: 'Logger_TOKEN', + useValue: { + debug: jest.fn(), + info: jest.fn(), + error: jest.fn(), + }, + }, + ], + }).compile(); + + useCase = module.get(RecordPageViewUseCase); + pageViewRepository = module.get('IPageViewRepository_TOKEN'); + logger = module.get('Logger_TOKEN'); + }); + + describe('execute', () => { + it('should save the page view and return the pageViewId', async () => { + const input = { + entityType: 'race' as any, + entityId: 'race-123', + visitorType: 'anonymous' as any, + sessionId: 'session-456', + visitorId: 'visitor-789', + referrer: 'https://example.com', + userAgent: 'Mozilla/5.0', + country: 'US', + }; + + pageViewRepository.save.mockResolvedValue(undefined); + + const result = await useCase.execute(input); + + expect(logger.debug).toHaveBeenCalledWith('Executing RecordPageViewUseCase', { input }); + expect(pageViewRepository.save).toHaveBeenCalledTimes(1); + expect(logger.info).toHaveBeenCalledWith('Page view recorded successfully', expect.objectContaining({ pageViewId: expect.any(String), input })); + expect(result).toHaveProperty('pageViewId'); + expect(typeof result.pageViewId).toBe('string'); + }); + + it('should handle errors and throw them', async () => { + const input = { + entityType: 'race' as any, + entityId: 'race-123', + visitorType: 'anonymous' as any, + sessionId: 'session-456', + }; + + const error = new Error('Save failed'); + pageViewRepository.save.mockRejectedValue(error); + + await expect(useCase.execute(input)).rejects.toThrow('Save failed'); + expect(logger.error).toHaveBeenCalledWith('Error recording page view', error, { input }); + }); + }); +}); \ No newline at end of file diff --git a/apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.ts b/apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.ts new file mode 100644 index 000000000..128bd9715 --- /dev/null +++ b/apps/api/src/modules/analytics/use-cases/RecordPageViewUseCase.ts @@ -0,0 +1,46 @@ +import { Injectable, Inject } from '@nestjs/common'; +import { RecordPageViewInput, RecordPageViewOutput } from '../dto/AnalyticsDto'; +import { IPageViewRepository } from '@gridpilot/analytics/application/repositories/IPageViewRepository'; +import { Logger } from '@gridpilot/shared/logging/Logger'; +import { PageView } from '@gridpilot/analytics/domain/entities/PageView'; + +const Logger_TOKEN = 'Logger_TOKEN'; +const IPAGE_VIEW_REPO_TOKEN = 'IPageViewRepository_TOKEN'; + +@Injectable() +export class RecordPageViewUseCase { + constructor( + @Inject(IPAGE_VIEW_REPO_TOKEN) private readonly pageViewRepository: IPageViewRepository, + @Inject(Logger_TOKEN) private readonly logger: Logger, + ) {} + + async execute(input: RecordPageViewInput): Promise { + this.logger.debug('Executing RecordPageViewUseCase', { input }); + try { + const pageViewId = `pv-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; + + const baseProps: Omit[0], 'timestamp'> = { + id: pageViewId, + entityType: input.entityType as any, // Cast to any to bypass strict type checking, will resolve with proper domain layer alignment + entityId: input.entityId, + visitorType: input.visitorType as any, // Cast to any to bypass strict type checking, will resolve with proper domain layer alignment + sessionId: input.sessionId, + }; + + const pageView = PageView.create({ + ...baseProps, + ...(input.visitorId !== undefined ? { visitorId: input.visitorId } : {}), + ...(input.referrer !== undefined ? { referrer: input.referrer } : {}), + ...(input.userAgent !== undefined ? { userAgent: input.userAgent } : {}), + ...(input.country !== undefined ? { country: input.country } : {}), + }); + + await this.pageViewRepository.save(pageView); + this.logger.info('Page view recorded successfully', { pageViewId, input }); + return { pageViewId }; + } catch (error) { + this.logger.error('Error recording page view', error, { input }); + throw error; + } + } +} \ No newline at end of file diff --git a/apps/api/src/modules/auth/AuthProviders.ts b/apps/api/src/modules/auth/AuthProviders.ts index 0d98c4fa7..55a40ca63 100644 --- a/apps/api/src/modules/auth/AuthProviders.ts +++ b/apps/api/src/modules/auth/AuthProviders.ts @@ -7,12 +7,12 @@ import { IUserRepository, StoredUser } from '@gridpilot/core/identity/domain/rep import { IPasswordHashingService } from '@gridpilot/core/identity/domain/services/PasswordHashingService'; import { Logger } from '@gridpilot/core/shared/logging/Logger'; -import { InMemoryAuthRepository } from '../../../adapters/identity/persistence/inmemory/InMemoryAuthRepository'; -import { InMemoryUserRepository } from '../../../adapters/identity/persistence/inmemory/InMemoryUserRepository'; -import { InMemoryPasswordHashingService } from '../../../adapters/identity/services/InMemoryPasswordHashingService'; -import { ConsoleLogger } from '../../../adapters/logging/ConsoleLogger'; +import { InMemoryAuthRepository } from '../../..//identity/persistence/inmemory/InMemoryAuthRepository'; +import { InMemoryUserRepository } from '../../..//identity/persistence/inmemory/InMemoryUserRepository'; +import { InMemoryPasswordHashingService } from '../../..//identity/services/InMemoryPasswordHashingService'; +import { ConsoleLogger } from '../../..//logging/ConsoleLogger'; import { IdentitySessionPort } from '../../../../core/identity/application/ports/IdentitySessionPort'; // Path from apps/api/src/modules/auth -import { CookieIdentitySessionAdapter } from '../../../adapters/identity/session/CookieIdentitySessionAdapter'; +import { CookieIdentitySessionAdapter } from '../../..//identity/session/CookieIdentitySessionAdapter'; // Define the tokens for dependency injection export const AUTH_REPOSITORY_TOKEN = 'IAuthRepository'; diff --git a/apps/api/src/modules/driver/DriverProviders.ts b/apps/api/src/modules/driver/DriverProviders.ts index 0dff636da..619011f3e 100644 --- a/apps/api/src/modules/driver/DriverProviders.ts +++ b/apps/api/src/modules/driver/DriverProviders.ts @@ -17,14 +17,14 @@ import { GetTotalDriversUseCase } from '../../../../core/racing/application/use- import { CompleteDriverOnboardingUseCase } from '../../../../core/racing/application/use-cases/CompleteDriverOnboardingUseCase'; // Import concrete in-memory implementations -import { InMemoryDriverRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryDriverRepository'; -import { InMemoryRankingService } from '../../../adapters/racing/services/InMemoryRankingService'; -import { InMemoryDriverStatsService } from '../../../adapters/racing/services/InMemoryDriverStatsService'; -import { InMemoryDriverRatingProvider } from '../../../adapters/racing/ports/InMemoryDriverRatingProvider'; -import { InMemoryImageServiceAdapter } from '../../../adapters/media/ports/InMemoryImageServiceAdapter'; -import { InMemoryRaceRegistrationRepository } from '../../../adapters/racing/persistence/inmemory/InMemoryRaceRegistrationRepository'; -import { InMemoryNotificationPreferenceRepository } from '../../../adapters/notifications/persistence/inmemory/InMemoryNotificationPreferenceRepository'; -import { ConsoleLogger } from '../../../adapters/logging/ConsoleLogger'; +import { InMemoryDriverRepository } from '../../..//racing/persistence/inmemory/InMemoryDriverRepository'; +import { InMemoryRankingService } from '../../..//racing/services/InMemoryRankingService'; +import { InMemoryDriverStatsService } from '../../..//racing/services/InMemoryDriverStatsService'; +import { InMemoryDriverRatingProvider } from '../../..//racing/ports/InMemoryDriverRatingProvider'; +import { InMemoryImageServiceAdapter } from '../../..//media/ports/InMemoryImageServiceAdapter'; +import { InMemoryRaceRegistrationRepository } from '../../..//racing/persistence/inmemory/InMemoryRaceRegistrationRepository'; +import { InMemoryNotificationPreferenceRepository } from '../../..//notifications/persistence/inmemory/InMemoryNotificationPreferenceRepository'; +import { ConsoleLogger } from '../../..//logging/ConsoleLogger'; // Define injection tokens export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository'; diff --git a/apps/api/src/modules/league/LeagueProviders.ts b/apps/api/src/modules/league/LeagueProviders.ts index 99385ac54..a18f79d35 100644 --- a/apps/api/src/modules/league/LeagueProviders.ts +++ b/apps/api/src/modules/league/LeagueProviders.ts @@ -5,17 +5,17 @@ import { LeagueService } from './LeagueService'; import { Logger } from '@gridpilot/shared/application/Logger'; // Import concrete in-memory implementations -import { InMemoryLeagueRepository } from 'adapters/racing/persistence/inmemory/InMemoryLeagueRepository'; -import { InMemoryLeagueMembershipRepository } from 'adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository'; -import { InMemoryLeagueStandingsRepository } from 'adapters/racing/persistence/inmemory/InMemoryLeagueStandingsRepository'; -import { InMemorySeasonRepository } from 'adapters/racing/persistence/inmemory/InMemorySeasonRepository'; -import { InMemoryLeagueScoringConfigRepository } from 'adapters/racing/persistence/inmemory/InMemoryLeagueScoringConfigRepository'; -import { InMemoryGameRepository } from 'adapters/racing/persistence/inmemory/InMemoryGameRepository'; -import { InMemoryProtestRepository } from 'adapters/racing/persistence/inmemory/InMemoryProtestRepository'; -import { InMemoryRaceRepository } from 'adapters/racing/persistence/inmemory/InMemoryRaceRepository'; -import { InMemoryDriverRepository } from 'adapters/racing/persistence/inmemory/InMemoryDriverRepository'; -import { InMemoryStandingRepository } from 'adapters/racing/persistence/inmemory/InMemoryStandingRepository'; -import { ConsoleLogger } from 'adapters/logging/ConsoleLogger'; +import { InMemoryLeagueRepository } from '/racing/persistence/inmemory/InMemoryLeagueRepository'; +import { InMemoryLeagueMembershipRepository } from '/racing/persistence/inmemory/InMemoryLeagueMembershipRepository'; +import { InMemoryLeagueStandingsRepository } from '/racing/persistence/inmemory/InMemoryLeagueStandingsRepository'; +import { InMemorySeasonRepository } from '/racing/persistence/inmemory/InMemorySeasonRepository'; +import { InMemoryLeagueScoringConfigRepository } from '/racing/persistence/inmemory/InMemoryLeagueScoringConfigRepository'; +import { InMemoryGameRepository } from '/racing/persistence/inmemory/InMemoryGameRepository'; +import { InMemoryProtestRepository } from '/racing/persistence/inmemory/InMemoryProtestRepository'; +import { InMemoryRaceRepository } from '/racing/persistence/inmemory/InMemoryRaceRepository'; +import { InMemoryDriverRepository } from '/racing/persistence/inmemory/InMemoryDriverRepository'; +import { InMemoryStandingRepository } from '/racing/persistence/inmemory/InMemoryStandingRepository'; +import { ConsoleLogger } from '/logging/ConsoleLogger'; // Import use cases import { GetAllLeaguesWithCapacityUseCase } from '@gridpilot/racing/application/use-cases/GetAllLeaguesWithCapacityUseCase'; diff --git a/apps/api/src/modules/payments/PaymentsProviders.ts b/apps/api/src/modules/payments/PaymentsProviders.ts index 094e61c0c..6680af0d0 100644 --- a/apps/api/src/modules/payments/PaymentsProviders.ts +++ b/apps/api/src/modules/payments/PaymentsProviders.ts @@ -23,11 +23,11 @@ import { GetWalletUseCase } from '@gridpilot/payments/application/use-cases/GetW import { ProcessWalletTransactionUseCase } from '@gridpilot/payments/application/use-cases/ProcessWalletTransactionUseCase'; // Import concrete in-memory implementations -import { InMemoryPaymentRepository } from 'adapters/payments/persistence/inmemory/InMemoryPaymentRepository'; -import { InMemoryMembershipFeeRepository, InMemoryMemberPaymentRepository } from 'adapters/payments/persistence/inmemory/InMemoryMembershipFeeRepository'; -import { InMemoryPrizeRepository } from 'adapters/payments/persistence/inmemory/InMemoryPrizeRepository'; -import { InMemoryWalletRepository, InMemoryTransactionRepository } from 'adapters/payments/persistence/inmemory/InMemoryWalletRepository'; -import { ConsoleLogger } from 'adapters/logging/ConsoleLogger'; +import { InMemoryPaymentRepository } from '/payments/persistence/inmemory/InMemoryPaymentRepository'; +import { InMemoryMembershipFeeRepository, InMemoryMemberPaymentRepository } from '/payments/persistence/inmemory/InMemoryMembershipFeeRepository'; +import { InMemoryPrizeRepository } from '/payments/persistence/inmemory/InMemoryPrizeRepository'; +import { InMemoryWalletRepository, InMemoryTransactionRepository } from '/payments/persistence/inmemory/InMemoryWalletRepository'; +import { ConsoleLogger } from '/logging/ConsoleLogger'; // Repository injection tokens export const PAYMENT_REPOSITORY_TOKEN = 'IPaymentRepository'; diff --git a/apps/api/src/modules/race/RaceProviders.ts b/apps/api/src/modules/race/RaceProviders.ts index fa547f7dc..da61c4d2f 100644 --- a/apps/api/src/modules/race/RaceProviders.ts +++ b/apps/api/src/modules/race/RaceProviders.ts @@ -7,9 +7,9 @@ import { IRaceRepository } from '@gridpilot/racing/domain/repositories/IRaceRepo import { ILeagueRepository } from '@gridpilot/racing/domain/repositories/ILeagueRepository'; // Import concrete in-memory implementations -import { InMemoryRaceRepository } from 'adapters/racing/persistence/inmemory/InMemoryRaceRepository'; -import { InMemoryLeagueRepository } from 'adapters/racing/persistence/inmemory/InMemoryLeagueRepository'; -import { ConsoleLogger } from 'adapters/logging/ConsoleLogger'; +import { InMemoryRaceRepository } from '/racing/persistence/inmemory/InMemoryRaceRepository'; +import { InMemoryLeagueRepository } from '/racing/persistence/inmemory/InMemoryLeagueRepository'; +import { ConsoleLogger } from '/logging/ConsoleLogger'; // Import use cases import { GetAllRacesUseCase } from '@gridpilot/racing/application/use-cases/GetAllRacesUseCase'; diff --git a/apps/api/src/modules/sponsor/SponsorProviders.ts b/apps/api/src/modules/sponsor/SponsorProviders.ts index c1d32dadf..fdd353108 100644 --- a/apps/api/src/modules/sponsor/SponsorProviders.ts +++ b/apps/api/src/modules/sponsor/SponsorProviders.ts @@ -21,15 +21,15 @@ import { GetSponsorSponsorshipsUseCase } from '@gridpilot/racing/application/use import { GetEntitySponsorshipPricingUseCase } from '@gridpilot/racing/application/use-cases/GetEntitySponsorshipPricingUseCase'; // Import concrete in-memory implementations -import { InMemorySponsorRepository } from 'adapters/racing/persistence/inmemory/InMemorySponsorRepository'; -import { InMemorySeasonSponsorshipRepository } from 'adapters/racing/persistence/inmemory/InMemorySeasonSponsorshipRepository'; -import { InMemorySeasonRepository } from 'adapters/racing/persistence/inmemory/InMemorySeasonRepository'; -import { InMemoryLeagueRepository } from 'adapters/racing/persistence/inmemory/InMemoryLeagueRepository'; -import { InMemoryLeagueMembershipRepository } from 'adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository'; -import { InMemoryRaceRepository } from 'adapters/racing/persistence/inmemory/InMemoryRaceRepository'; -import { InMemorySponsorshipPricingRepository } from 'adapters/racing/persistence/inmemory/InMemorySponsorshipPricingRepository'; -import { InMemorySponsorshipRequestRepository } from 'adapters/racing/persistence/inmemory/InMemorySponsorshipRequestRepository'; -import { ConsoleLogger } from 'adapters/logging/ConsoleLogger'; +import { InMemorySponsorRepository } from '/racing/persistence/inmemory/InMemorySponsorRepository'; +import { InMemorySeasonSponsorshipRepository } from '/racing/persistence/inmemory/InMemorySeasonSponsorshipRepository'; +import { InMemorySeasonRepository } from '/racing/persistence/inmemory/InMemorySeasonRepository'; +import { InMemoryLeagueRepository } from '/racing/persistence/inmemory/InMemoryLeagueRepository'; +import { InMemoryLeagueMembershipRepository } from '/racing/persistence/inmemory/InMemoryLeagueMembershipRepository'; +import { InMemoryRaceRepository } from '/racing/persistence/inmemory/InMemoryRaceRepository'; +import { InMemorySponsorshipPricingRepository } from '/racing/persistence/inmemory/InMemorySponsorshipPricingRepository'; +import { InMemorySponsorshipRequestRepository } from '/racing/persistence/inmemory/InMemorySponsorshipRequestRepository'; +import { ConsoleLogger } from '/logging/ConsoleLogger'; // Define injection tokens export const SPONSOR_REPOSITORY_TOKEN = 'ISponsorRepository'; diff --git a/apps/api/src/modules/team/TeamProviders.ts b/apps/api/src/modules/team/TeamProviders.ts index 688f541c0..4cff7d8ec 100644 --- a/apps/api/src/modules/team/TeamProviders.ts +++ b/apps/api/src/modules/team/TeamProviders.ts @@ -9,10 +9,10 @@ import { IImageServicePort } from '@gridpilot/racing/application/ports/IImageSer import { Logger } from '@gridpilot/shared/application/Logger'; // Import concrete in-memory implementations -import { InMemoryTeamRepository } from 'adapters/racing/persistence/inmemory/InMemoryTeamRepository'; -import { InMemoryTeamMembershipRepository } from 'adapters/racing/persistence/inmemory/InMemoryTeamMembershipRepository'; -import { InMemoryDriverRepository } from 'adapters/racing/persistence/inmemory/InMemoryDriverRepository'; -import { ConsoleLogger } from 'adapters/logging/ConsoleLogger'; +import { InMemoryTeamRepository } from '/racing/persistence/inmemory/InMemoryTeamRepository'; +import { InMemoryTeamMembershipRepository } from '/racing/persistence/inmemory/InMemoryTeamMembershipRepository'; +import { InMemoryDriverRepository } from '/racing/persistence/inmemory/InMemoryDriverRepository'; +import { ConsoleLogger } from '/logging/ConsoleLogger'; // Import use cases import { GetAllTeamsUseCase } from '@gridpilot/racing/application/use-cases/GetAllTeamsUseCase'; diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json index 59e8e892c..a9e4226b2 100644 --- a/apps/api/tsconfig.json +++ b/apps/api/tsconfig.json @@ -28,49 +28,49 @@ "types": ["node", "express", "jest"], "strictPropertyInitialization": false, "paths": { - "@gridpilot/shared/*": [ + "@core/shared/*": [ "../../core/shared/*" ], - "@gridpilot/shared/application/*": [ + "@core/shared/application/*": [ "../../core/shared/application/*" ], - "@gridpilot/payments/*": [ + "@core/payments/*": [ "../../core/payments/*" ], - "@gridpilot/payments/application/*": [ + "@core/payments/application/*": [ "../../core/payments/application/*" ], - "@gridpilot/payments/domain/*": [ + "@core/payments/domain/*": [ "../../core/payments/domain/*" ], - "@gridpilot/racing/*": [ + "@core/racing/*": [ "../../core/racing/*" ], - "@gridpilot/league/*": [ + "@core/league/*": [ "../../core/league/*" ], - "@gridpilot/analytics/*": [ + "@core/analytics/*": [ "../../core/analytics/*" ], - "@gridpilot/analytics/domain/repositories/*": [ + "@core/analytics/domain/repositories/*": [ "../../core/analytics/domain/repositories/*" ], - "@gridpilot/analytics/domain/entities/*": [ + "@core/analytics/domain/entities/*": [ "../../core/analytics/domain/entities/*" ], - "@gridpilot/core/identity/domain/repositories/*": [ + "@core/core/identity/domain/repositories/*": [ "../../core/identity/domain/repositories/*" ], - "@gridpilot/core/identity/domain/services/*": [ + "@core/core/identity/domain/services/*": [ "../../core/identity/domain/services/*" ], - "@gridpilot/core/identity/domain/entities/*": [ + "@core/core/identity/domain/entities/*": [ "../../core/identity/domain/entities/*" ], - "@gridpilot/core/shared/logging/*": [ + "@core/core/shared/logging/*": [ "../../core/shared/logging/*" ], - "adapters/*": [ + "@adapters/*": [ "../../adapters/*" ], "@nestjs/testing": [ diff --git a/apps/companion/main/di-config.ts b/apps/companion/main/di-config.ts index d42af2527..5e6b0b188 100644 --- a/apps/companion/main/di-config.ts +++ b/apps/companion/main/di-config.ts @@ -18,7 +18,7 @@ import { InitiateLoginUseCase } from '@gridpilot/automation/application/use-case import { ClearSessionUseCase } from '@gridpilot/automation/application/use-cases/ClearSessionUseCase'; import { ConfirmCheckoutUseCase } from '@gridpilot/automation/application/use-cases/ConfirmCheckoutUseCase'; import { OverlaySyncService } from '@gridpilot/automation/application/services/OverlaySyncService'; -import type { IAutomationLifecycleEmitter } from '@gridpilot/automation/infrastructure/adapters/IAutomationLifecycleEmitter'; +import type { IAutomationLifecycleEmitter } from '@gridpilot/automation/infrastructure//IAutomationLifecycleEmitter'; // Infrastructure import { InMemorySessionRepository } from '@gridpilot/automation/infrastructure/repositories/InMemorySessionRepository'; @@ -27,11 +27,11 @@ import { PlaywrightAutomationAdapter, AutomationAdapterMode, FixtureServer, -} from '@gridpilot/automation/infrastructure/adapters/automation'; -import { MockAutomationEngineAdapter } from '@gridpilot/automation/infrastructure/adapters/automation/engine/MockAutomationEngineAdapter'; -import { AutomationEngineAdapter } from '@gridpilot/automation/infrastructure/adapters/automation/engine/AutomationEngineAdapter'; -import { ConsoleLogAdapter } from '@gridpilot/automation/infrastructure/adapters/logging/ConsoleLogAdapter'; -import { NoOpLogAdapter } from '@gridpilot/automation/infrastructure/adapters/logging/NoOpLogAdapter'; +} from '@gridpilot/automation/infrastructure//automation'; +import { MockAutomationEngineAdapter } from '@gridpilot/automation/infrastructure//automation/engine/MockAutomationEngineAdapter'; +import { AutomationEngineAdapter } from '@gridpilot/automation/infrastructure//automation/engine/AutomationEngineAdapter'; +import { ConsoleLogAdapter } from '@gridpilot/automation/infrastructure//logging/ConsoleLogAdapter'; +import { NoOpLogAdapter } from '@gridpilot/automation/infrastructure//logging/NoOpLogAdapter'; import { loadAutomationConfig, getAutomationMode, diff --git a/apps/companion/main/di-container.ts b/apps/companion/main/di-container.ts index 06470cbdb..1d7867f3b 100644 --- a/apps/companion/main/di-container.ts +++ b/apps/companion/main/di-container.ts @@ -1,7 +1,7 @@ import 'reflect-metadata'; import { configureDIContainer, resetDIContainer, getDIContainer, resolveSessionDataPath, resolveTemplatePath } from './di-config'; import { DI_TOKENS } from './di-tokens'; -import { PlaywrightAutomationAdapter, FixtureServer } from '@gridpilot/automation/infrastructure/adapters/automation'; +import { PlaywrightAutomationAdapter, FixtureServer } from '@gridpilot/automation/infrastructure//automation'; import { StartAutomationSessionUseCase } from '@gridpilot/automation/application/use-cases/StartAutomationSessionUseCase'; import { CheckAuthenticationUseCase } from '@gridpilot/automation/application/use-cases/CheckAuthenticationUseCase'; import { InitiateLoginUseCase } from '@gridpilot/automation/application/use-cases/InitiateLoginUseCase'; diff --git a/apps/companion/main/ipc-handlers.ts b/apps/companion/main/ipc-handlers.ts index fbc363e07..3dd75db9d 100644 --- a/apps/companion/main/ipc-handlers.ts +++ b/apps/companion/main/ipc-handlers.ts @@ -4,9 +4,9 @@ import { DIContainer } from './di-container'; import type { HostedSessionConfig } from 'core/automation/domain/types/HostedSessionConfig'; import { StepId } from 'core/automation/domain/value-objects/StepId'; import { AuthenticationState } from 'core/automation/domain/value-objects/AuthenticationState'; -import { ElectronCheckoutConfirmationAdapter } from 'core/automation/infrastructure/adapters/ipc/ElectronCheckoutConfirmationAdapter'; +import { ElectronCheckoutConfirmationAdapter } from 'core/automation/infrastructure//ipc/ElectronCheckoutConfirmationAdapter'; import type { OverlayAction } from 'core/automation/application/ports/OverlaySyncPort'; -import type { IAutomationLifecycleEmitter } from 'core/automation/infrastructure/adapters/IAutomationLifecycleEmitter'; +import type { IAutomationLifecycleEmitter } from 'core/automation/infrastructure//IAutomationLifecycleEmitter'; let progressMonitorInterval: NodeJS.Timeout | null = null; let lifecycleSubscribed = false; @@ -335,7 +335,7 @@ export function setupIpcHandlers(mainWindow: BrowserWindow): void { loader.setDevelopmentMode(mode); // Ensure runtime automation wiring reflects the new browser mode if ('refreshBrowserAutomation' in container) { - // Call method to refresh adapters/use-cases that depend on browser mode + // Call method to refresh /use-cases that depend on browser mode container.refreshBrowserAutomation(); } logger.info('Browser mode updated', { mode }); diff --git a/apps/website/.eslintrc.json b/apps/website/.eslintrc.json index 7e4b71e7a..8b50487f7 100644 --- a/apps/website/.eslintrc.json +++ b/apps/website/.eslintrc.json @@ -1,9 +1,22 @@ { "extends": "next/core-web-vitals", + "plugins": ["boundaries"], "rules": { "react/no-unescaped-entities": "off", "@next/next/no-img-element": "warn", "react-hooks/exhaustive-deps": "warn", - "@typescript-eslint/no-explicit-any": "error" + "@typescript-eslint/no-explicit-any": "error", + "boundaries/element-types": [ + 2, + { + "default": "disallow", + "rules": [ + { + "from": ["website"], + "allow": ["website"] + } + ] + } + ] } } \ No newline at end of file diff --git a/apps/website/tsconfig.json b/apps/website/tsconfig.json index 34cc5561a..095497ef5 100644 --- a/apps/website/tsconfig.json +++ b/apps/website/tsconfig.json @@ -18,20 +18,20 @@ "@/lib/*": ["./lib/*"], "@/components/*": ["./components/*"], "@/app/*": ["./app/*"], - "@gridpilot/identity": ["../../core/identity/index.ts"], - "@gridpilot/identity/*": ["../../core/identity/*"], - "@gridpilot/racing": ["../../core/racing/index.ts"], - "@gridpilot/racing/*": ["../../core/racing/*"], - "@gridpilot/social": ["../../core/social/index.ts"], - "@gridpilot/social/*": ["../../core/social/*"], - "@gridpilot/testing-support": ["../../core/testing-support/index.ts"], - "@gridpilot/testing-support/*": ["../../core/testing-support/*"], - "@gridpilot/media": ["../../core/media/index.ts"], - "@gridpilot/media/*": ["../../core/media/*"], - "@gridpilot/shared/logging": ["../../core/shared/logging"], - "@gridpilot/shared/*": ["../../core/shared/*"], - "@gridpilot/core/*": ["../../core/*"], - "@gridpilot/api/*": ["../../apps/api/src/*"] + "@core/identity": ["../../core/identity/index.ts"], + "@core/identity/*": ["../../core/identity/*"], + "@core/racing": ["../../core/racing/index.ts"], + "@core/racing/*": ["../../core/racing/*"], + "@core/social": ["../../core/social/index.ts"], + "@core/social/*": ["../../core/social/*"], + "@core/testing-support": ["../../core/testing-support/index.ts"], + "@core/testing-support/*": ["../../core/testing-support/*"], + "@core/media": ["../../core/media/index.ts"], + "@core/media/*": ["../../core/media/*"], + "@core/shared/logging": ["../../core/shared/logging"], + "@core/shared/*": ["../../core/shared/*"], + "@core/core/*": ["../../core/*"], + "@core/api/*": ["../../apps/api/src/*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], diff --git a/core/notifications/infrastructure/index.ts b/core/notifications/infrastructure/index.ts index d51eba275..d361f923d 100644 --- a/core/notifications/infrastructure/index.ts +++ b/core/notifications/infrastructure/index.ts @@ -7,5 +7,5 @@ export { InMemoryNotificationRepository } from './repositories/InMemoryNotificat export { InMemoryNotificationPreferenceRepository } from './repositories/InMemoryNotificationPreferenceRepository'; // Adapters -export { InAppNotificationAdapter } from './adapters/InAppNotificationAdapter'; -export { NotificationGatewayRegistry } from './adapters/NotificationGatewayRegistry'; \ No newline at end of file +export { InAppNotificationAdapter } from './/InAppNotificationAdapter'; +export { NotificationGatewayRegistry } from './/NotificationGatewayRegistry'; \ No newline at end of file diff --git a/tests/application/OverlaySyncService.spec.ts b/tests/application/OverlaySyncService.spec.ts index ab0b12671..858ca07d5 100644 --- a/tests/application/OverlaySyncService.spec.ts +++ b/tests/application/OverlaySyncService.spec.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from 'vitest' import { OverlayAction, ActionAck } from '../../../../core/automation/application/ports/IOverlaySyncPort' import { IAutomationEventPublisher, AutomationEvent } from '../../../../core/automation/application/ports/IAutomationEventPublisher' -import { IAutomationLifecycleEmitter, LifecycleCallback } from '../../../../core/automation/infrastructure/adapters/IAutomationLifecycleEmitter' +import { IAutomationLifecycleEmitter, LifecycleCallback } from '../../../../core/automation/infrastructure//IAutomationLifecycleEmitter' import { OverlaySyncService } from '../../../../core/automation/application/services/OverlaySyncService' class MockLifecycleEmitter implements IAutomationLifecycleEmitter { diff --git a/tests/application/OverlaySyncService.timeout.spec.ts b/tests/application/OverlaySyncService.timeout.spec.ts index f5f87dc02..eb356a2b2 100644 --- a/tests/application/OverlaySyncService.timeout.spec.ts +++ b/tests/application/OverlaySyncService.timeout.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from 'vitest' import { OverlayAction } from '../../../../core/automation/application/ports/OverlaySyncPort' -import { IAutomationLifecycleEmitter, LifecycleCallback } from '../../../../core/automation/infrastructure/adapters/IAutomationLifecycleEmitter' +import { IAutomationLifecycleEmitter, LifecycleCallback } from '../../../../core/automation/infrastructure//IAutomationLifecycleEmitter' import { OverlaySyncService } from '../../../../core/automation/application/services/OverlaySyncService' class MockLifecycleEmitter implements IAutomationLifecycleEmitter { diff --git a/tests/e2e/automation.e2e.test.ts b/tests/e2e/automation.e2e.test.ts index 942ef1938..697c577a0 100644 --- a/tests/e2e/automation.e2e.test.ts +++ b/tests/e2e/automation.e2e.test.ts @@ -3,9 +3,9 @@ import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; import { FixtureServer, PlaywrightAutomationAdapter, -} from 'core/automation/infrastructure/adapters/automation'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; -import { PinoLogAdapter } from 'core/automation/infrastructure/adapters/logging/PinoLogAdapter'; +} from 'core/automation/infrastructure//automation'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; +import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter'; describe('Real Playwright hosted-session smoke (fixtures, steps 2–7)', () => { let server: FixtureServer; diff --git a/tests/e2e/companion/companion-ui-full-workflow.e2e.test.ts b/tests/e2e/companion/companion-ui-full-workflow.e2e.test.ts index 3ffc3be10..7ddb12333 100644 --- a/tests/e2e/companion/companion-ui-full-workflow.e2e.test.ts +++ b/tests/e2e/companion/companion-ui-full-workflow.e2e.test.ts @@ -2,7 +2,7 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { DIContainer } from '../../../apps/companion/main/di-container'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; import type { HostedSessionConfig } from '@gridpilot/automation/domain/types/HostedSessionConfig'; -import { PlaywrightAutomationAdapter } from 'core/automation/infrastructure/adapters/automation'; +import { PlaywrightAutomationAdapter } from 'core/automation/infrastructure//automation'; describe('Companion UI - hosted workflow via fixture-backed real stack', () => { let container: DIContainer; diff --git a/tests/e2e/hosted-real/cars-flow.real.e2e.test.ts b/tests/e2e/hosted-real/cars-flow.real.e2e.test.ts index e85d4bdf2..4dcde8e65 100644 --- a/tests/e2e/hosted-real/cars-flow.real.e2e.test.ts +++ b/tests/e2e/hosted-real/cars-flow.real.e2e.test.ts @@ -2,12 +2,12 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; import { PlaywrightAutomationAdapter, -} from 'core/automation/infrastructure/adapters/automation'; +} from 'core/automation/infrastructure//automation'; import { IRACING_SELECTORS, IRACING_TIMEOUTS, -} from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; -import { PinoLogAdapter } from 'core/automation/infrastructure/adapters/logging/PinoLogAdapter'; +} from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; +import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter'; const shouldRun = process.env.HOSTED_REAL_E2E === '1'; const describeMaybe = shouldRun ? describe : describe.skip; diff --git a/tests/e2e/hosted-real/login-and-wizard-smoke.e2e.test.ts b/tests/e2e/hosted-real/login-and-wizard-smoke.e2e.test.ts index 765812502..81cad844c 100644 --- a/tests/e2e/hosted-real/login-and-wizard-smoke.e2e.test.ts +++ b/tests/e2e/hosted-real/login-and-wizard-smoke.e2e.test.ts @@ -2,12 +2,12 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; import { PlaywrightAutomationAdapter, -} from 'core/automation/infrastructure/adapters/automation'; +} from 'core/automation/infrastructure//automation'; import { IRACING_SELECTORS, IRACING_TIMEOUTS, -} from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; -import { PinoLogAdapter } from 'core/automation/infrastructure/adapters/logging/PinoLogAdapter'; +} from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; +import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter'; const shouldRun = process.env.HOSTED_REAL_E2E === '1'; diff --git a/tests/e2e/hosted-real/step-03-race-information.real.e2e.test.ts b/tests/e2e/hosted-real/step-03-race-information.real.e2e.test.ts index 836ef6a0f..5e2d87820 100644 --- a/tests/e2e/hosted-real/step-03-race-information.real.e2e.test.ts +++ b/tests/e2e/hosted-real/step-03-race-information.real.e2e.test.ts @@ -4,12 +4,12 @@ import path from 'path'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; import { PlaywrightAutomationAdapter, -} from 'core/automation/infrastructure/adapters/automation'; +} from 'core/automation/infrastructure//automation'; import { IRACING_SELECTORS, IRACING_TIMEOUTS, -} from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; -import { PinoLogAdapter } from 'core/automation/infrastructure/adapters/logging/PinoLogAdapter'; +} from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; +import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter'; const shouldRun = process.env.HOSTED_REAL_E2E === '1'; const describeMaybe = shouldRun ? describe : describe.skip; diff --git a/tests/e2e/steps/step-02-create-race.e2e.test.ts b/tests/e2e/steps/step-02-create-race.e2e.test.ts index 98b4b7896..be137665a 100644 --- a/tests/e2e/steps/step-02-create-race.e2e.test.ts +++ b/tests/e2e/steps/step-02-create-race.e2e.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import type { StepHarness } from '../support/StepHarness'; import { createStepHarness } from '../support/StepHarness'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; describe('Step 2 – create race', () => { let harness: StepHarness; diff --git a/tests/e2e/steps/step-03-race-information.e2e.test.ts b/tests/e2e/steps/step-03-race-information.e2e.test.ts index c68152cf2..0a12ae678 100644 --- a/tests/e2e/steps/step-03-race-information.e2e.test.ts +++ b/tests/e2e/steps/step-03-race-information.e2e.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import type { StepHarness } from '../support/StepHarness'; import { createStepHarness } from '../support/StepHarness'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; describe('Step 3 – race information', () => { let harness: StepHarness; diff --git a/tests/e2e/steps/step-04-server-details.e2e.test.ts b/tests/e2e/steps/step-04-server-details.e2e.test.ts index 1cad85da9..51be5053f 100644 --- a/tests/e2e/steps/step-04-server-details.e2e.test.ts +++ b/tests/e2e/steps/step-04-server-details.e2e.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import type { StepHarness } from '../support/StepHarness'; import { createStepHarness } from '../support/StepHarness'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; describe('Step 4 – server details', () => { let harness: StepHarness; diff --git a/tests/e2e/steps/step-05-set-admins.e2e.test.ts b/tests/e2e/steps/step-05-set-admins.e2e.test.ts index 021f6295b..0ab348c84 100644 --- a/tests/e2e/steps/step-05-set-admins.e2e.test.ts +++ b/tests/e2e/steps/step-05-set-admins.e2e.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import type { StepHarness } from '../support/StepHarness'; import { createStepHarness } from '../support/StepHarness'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; describe('Step 5 – set admins', () => { let harness: StepHarness; diff --git a/tests/e2e/steps/step-06-admins.e2e.test.ts b/tests/e2e/steps/step-06-admins.e2e.test.ts index f96d5dc55..a2de88517 100644 --- a/tests/e2e/steps/step-06-admins.e2e.test.ts +++ b/tests/e2e/steps/step-06-admins.e2e.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import type { StepHarness } from '../support/StepHarness'; import { createStepHarness } from '../support/StepHarness'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; describe('Step 6 – admins', () => { let harness: StepHarness; diff --git a/tests/e2e/steps/step-07-time-limits.e2e.test.ts b/tests/e2e/steps/step-07-time-limits.e2e.test.ts index f597a5c5a..f87e664dd 100644 --- a/tests/e2e/steps/step-07-time-limits.e2e.test.ts +++ b/tests/e2e/steps/step-07-time-limits.e2e.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import type { StepHarness } from '../support/StepHarness'; import { createStepHarness } from '../support/StepHarness'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; describe('Step 7 – time limits', () => { let harness: StepHarness; diff --git a/tests/e2e/steps/step-08-cars.e2e.test.ts b/tests/e2e/steps/step-08-cars.e2e.test.ts index 8fc747a3d..1f65c1c94 100644 --- a/tests/e2e/steps/step-08-cars.e2e.test.ts +++ b/tests/e2e/steps/step-08-cars.e2e.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import type { StepHarness } from '../support/StepHarness'; import { createStepHarness } from '../support/StepHarness'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; describe('Step 8 – cars', () => { let harness: StepHarness; diff --git a/tests/e2e/steps/step-13-track-options.e2e.test.ts b/tests/e2e/steps/step-13-track-options.e2e.test.ts index 566fa4b59..05ba3f99f 100644 --- a/tests/e2e/steps/step-13-track-options.e2e.test.ts +++ b/tests/e2e/steps/step-13-track-options.e2e.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import type { StepHarness } from '../support/StepHarness'; import { createStepHarness } from '../support/StepHarness'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; describe('Step 13 – track options', () => { let harness: StepHarness; diff --git a/tests/e2e/steps/step-14-time-of-day.e2e.test.ts b/tests/e2e/steps/step-14-time-of-day.e2e.test.ts index 153d0d4d9..ea1ae94ad 100644 --- a/tests/e2e/steps/step-14-time-of-day.e2e.test.ts +++ b/tests/e2e/steps/step-14-time-of-day.e2e.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import type { StepHarness } from '../support/StepHarness'; import { createStepHarness } from '../support/StepHarness'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; describe('Step 14 – time of day', () => { let harness: StepHarness; diff --git a/tests/e2e/steps/step-15-weather.e2e.test.ts b/tests/e2e/steps/step-15-weather.e2e.test.ts index ce8e65603..daa608b55 100644 --- a/tests/e2e/steps/step-15-weather.e2e.test.ts +++ b/tests/e2e/steps/step-15-weather.e2e.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import type { StepHarness } from '../support/StepHarness'; import { createStepHarness } from '../support/StepHarness'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; describe('Step 15 – weather', () => { let harness: StepHarness; diff --git a/tests/e2e/support/AutoNavGuard.ts b/tests/e2e/support/AutoNavGuard.ts index eca8a3a5f..d1d113660 100644 --- a/tests/e2e/support/AutoNavGuard.ts +++ b/tests/e2e/support/AutoNavGuard.ts @@ -1,5 +1,5 @@ import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; -import type { PlaywrightAutomationAdapter } from 'core/automation/infrastructure/adapters/automation'; +import type { PlaywrightAutomationAdapter } from 'core/automation/infrastructure//automation'; import type { AutomationResult } from 'core/automation/application/ports/AutomationResults'; export function assertAutoNavigationConfig(config: Record): void { diff --git a/tests/e2e/support/StepHarness.ts b/tests/e2e/support/StepHarness.ts index ea0c2ada0..ff5c815ea 100644 --- a/tests/e2e/support/StepHarness.ts +++ b/tests/e2e/support/StepHarness.ts @@ -3,8 +3,8 @@ import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; import { PlaywrightAutomationAdapter, FixtureServer, -} from 'core/automation/infrastructure/adapters/automation'; -import { PinoLogAdapter } from 'core/automation/infrastructure/adapters/logging/PinoLogAdapter'; +} from 'core/automation/infrastructure//automation'; +import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter'; export interface StepHarness { server: FixtureServer; diff --git a/tests/e2e/validators/hosted-validator-guards.e2e.test.ts b/tests/e2e/validators/hosted-validator-guards.e2e.test.ts index e09372e11..c85c447f3 100644 --- a/tests/e2e/validators/hosted-validator-guards.e2e.test.ts +++ b/tests/e2e/validators/hosted-validator-guards.e2e.test.ts @@ -2,9 +2,9 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { PlaywrightAutomationAdapter, FixtureServer, -} from 'core/automation/infrastructure/adapters/automation'; +} from 'core/automation/infrastructure//automation'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; -import { PinoLogAdapter } from 'core/automation/infrastructure/adapters/logging/PinoLogAdapter'; +import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter'; import { executeStepWithAutoNavigationGuard } from '../support/AutoNavGuard'; describe('Hosted validator guards (fixture-backed, real stack)', () => { diff --git a/tests/e2e/workflows/full-hosted-session.autonav.workflow.e2e.test.ts b/tests/e2e/workflows/full-hosted-session.autonav.workflow.e2e.test.ts index bd1314f62..4012f91f6 100644 --- a/tests/e2e/workflows/full-hosted-session.autonav.workflow.e2e.test.ts +++ b/tests/e2e/workflows/full-hosted-session.autonav.workflow.e2e.test.ts @@ -2,10 +2,10 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { PlaywrightAutomationAdapter, FixtureServer, -} from 'core/automation/infrastructure/adapters/automation'; +} from 'core/automation/infrastructure//automation'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; -import { PinoLogAdapter } from 'core/automation/infrastructure/adapters/logging/PinoLogAdapter'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; +import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; import { executeStepWithAutoNavigationGuard } from '../support/AutoNavGuard'; describe('Workflow – hosted session autonav slice (fixture-backed, real stack)', () => { diff --git a/tests/e2e/workflows/full-hosted-session.workflow.e2e.test.ts b/tests/e2e/workflows/full-hosted-session.workflow.e2e.test.ts index 8f62f868e..43a4faaba 100644 --- a/tests/e2e/workflows/full-hosted-session.workflow.e2e.test.ts +++ b/tests/e2e/workflows/full-hosted-session.workflow.e2e.test.ts @@ -2,12 +2,12 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { PlaywrightAutomationAdapter, FixtureServer, -} from 'core/automation/infrastructure/adapters/automation'; +} from 'core/automation/infrastructure//automation'; import { InMemorySessionRepository } from 'core/automation/infrastructure/repositories/InMemorySessionRepository'; -import { AutomationEngineAdapter } from 'core/automation/infrastructure/adapters/automation/engine/AutomationEngineAdapter'; +import { AutomationEngineAdapter } from 'core/automation/infrastructure//automation/engine/AutomationEngineAdapter'; import { StartAutomationSessionUseCase } from 'core/automation/application/use-cases/StartAutomationSessionUseCase'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; -import { PinoLogAdapter } from 'core/automation/infrastructure/adapters/logging/PinoLogAdapter'; +import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter'; describe('Workflow – hosted session end-to-end (fixture-backed, real stack)', () => { let server: FixtureServer; diff --git a/tests/e2e/workflows/steps-07-09-cars-flow.e2e.test.ts b/tests/e2e/workflows/steps-07-09-cars-flow.e2e.test.ts index 6c2807cf5..358988c27 100644 --- a/tests/e2e/workflows/steps-07-09-cars-flow.e2e.test.ts +++ b/tests/e2e/workflows/steps-07-09-cars-flow.e2e.test.ts @@ -2,10 +2,10 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { PlaywrightAutomationAdapter, FixtureServer, -} from 'core/automation/infrastructure/adapters/automation'; +} from 'core/automation/infrastructure//automation'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; -import { IRACING_SELECTORS } from 'core/automation/infrastructure/adapters/automation/dom/IRacingSelectors'; -import { PinoLogAdapter } from 'core/automation/infrastructure/adapters/logging/PinoLogAdapter'; +import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors'; +import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter'; describe('Workflow – steps 7–9 cars flow (fixture-backed, real stack)', () => { let adapter: PlaywrightAutomationAdapter; diff --git a/tests/infrastructure/AuthenticationGuard.spec.ts b/tests/infrastructure/AuthenticationGuard.spec.ts index 74871b093..213964281 100644 --- a/tests/infrastructure/AuthenticationGuard.spec.ts +++ b/tests/infrastructure/AuthenticationGuard.spec.ts @@ -1,6 +1,6 @@ import { describe, test, expect, beforeEach, vi } from 'vitest'; import type { Page } from 'playwright'; -import { AuthenticationGuard } from '@gridpilot/automation/infrastructure/adapters/automation/auth/AuthenticationGuard'; +import { AuthenticationGuard } from '@gridpilot/automation/infrastructure//automation/auth/AuthenticationGuard'; describe('AuthenticationGuard', () => { let mockPage: Page; diff --git a/tests/infrastructure/ElectronCheckoutConfirmationAdapter.spec.ts b/tests/infrastructure/ElectronCheckoutConfirmationAdapter.spec.ts index 4cd736135..3987dde8f 100644 --- a/tests/infrastructure/ElectronCheckoutConfirmationAdapter.spec.ts +++ b/tests/infrastructure/ElectronCheckoutConfirmationAdapter.spec.ts @@ -9,7 +9,7 @@ vi.mock('electron', () => ({ }, })); -import { ElectronCheckoutConfirmationAdapter } from '@gridpilot/automation/infrastructure/adapters/ipc/ElectronCheckoutConfirmationAdapter'; +import { ElectronCheckoutConfirmationAdapter } from '@gridpilot/automation/infrastructure//ipc/ElectronCheckoutConfirmationAdapter'; import { CheckoutPrice } from '@gridpilot/automation/domain/value-objects/CheckoutPrice'; import { CheckoutState } from '@gridpilot/automation/domain/value-objects/CheckoutState'; import { ipcMain } from 'electron'; diff --git a/tests/infrastructure/PlaywrightAuthSessionService.initiateLogin.browserMode.spec.ts b/tests/infrastructure/PlaywrightAuthSessionService.initiateLogin.browserMode.spec.ts index 62393ae6b..b8463f0ec 100644 --- a/tests/infrastructure/PlaywrightAuthSessionService.initiateLogin.browserMode.spec.ts +++ b/tests/infrastructure/PlaywrightAuthSessionService.initiateLogin.browserMode.spec.ts @@ -1,9 +1,9 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import type { Page, BrowserContext } from 'playwright'; -import { PlaywrightAuthSessionService } from '../../../../core/automation/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService'; -import type { PlaywrightBrowserSession } from '../../../../core/automation/infrastructure/adapters/automation/core/PlaywrightBrowserSession'; -import type { SessionCookieStore } from '../../../../core/automation/infrastructure/adapters/automation/auth/SessionCookieStore'; -import type { IPlaywrightAuthFlow } from '../../../../core/automation/infrastructure/adapters/automation/auth/PlaywrightAuthFlow'; +import { PlaywrightAuthSessionService } from '../../../../core/automation/infrastructure//automation/auth/PlaywrightAuthSessionService'; +import type { PlaywrightBrowserSession } from '../../../../core/automation/infrastructure//automation/core/PlaywrightBrowserSession'; +import type { SessionCookieStore } from '../../../../core/automation/infrastructure//automation/auth/SessionCookieStore'; +import type { IPlaywrightAuthFlow } from '../../../../core/automation/infrastructure//automation/auth/PlaywrightAuthFlow'; import type { LoggerPort as Logger } from '../../../../core/automation/application/ports/LoggerPort'; import { AuthenticationState } from '@gridpilot/automation/domain/value-objects/AuthenticationState'; import { Result } from '../../../../core/shared/result/Result'; diff --git a/tests/infrastructure/PlaywrightAuthSessionService.verifyPageAuthentication.spec.ts b/tests/infrastructure/PlaywrightAuthSessionService.verifyPageAuthentication.spec.ts index 4730f012d..71e794853 100644 --- a/tests/infrastructure/PlaywrightAuthSessionService.verifyPageAuthentication.spec.ts +++ b/tests/infrastructure/PlaywrightAuthSessionService.verifyPageAuthentication.spec.ts @@ -1,13 +1,13 @@ import { describe, it, expect, vi } from 'vitest'; import type { Page, Locator } from 'playwright'; -import { PlaywrightAuthSessionService } from '../../../../core/automation/infrastructure/adapters/automation/auth/PlaywrightAuthSessionService'; +import { PlaywrightAuthSessionService } from '../../../../core/automation/infrastructure//automation/auth/PlaywrightAuthSessionService'; import { AuthenticationState } from '@gridpilot/automation/domain/value-objects/AuthenticationState'; import { BrowserAuthenticationState } from '@gridpilot/automation/domain/value-objects/BrowserAuthenticationState'; import type { LoggerPort as Logger } from '../../../../core/automation/application/ports/LoggerPort'; import type { Result } from '../../../../core/shared/result/Result'; -import type { PlaywrightBrowserSession } from '../../../../core/automation/infrastructure/adapters/automation/core/PlaywrightBrowserSession'; -import type { SessionCookieStore } from '../../../../core/automation/infrastructure/adapters/automation/auth/SessionCookieStore'; -import type { IPlaywrightAuthFlow } from '../../../../core/automation/infrastructure/adapters/automation/auth/PlaywrightAuthFlow'; +import type { PlaywrightBrowserSession } from '../../../../core/automation/infrastructure//automation/core/PlaywrightBrowserSession'; +import type { SessionCookieStore } from '../../../../core/automation/infrastructure//automation/auth/SessionCookieStore'; +import type { IPlaywrightAuthFlow } from '../../../../core/automation/infrastructure//automation/auth/PlaywrightAuthFlow'; describe('PlaywrightAuthSessionService.verifyPageAuthentication', () => { function createService(deps: { diff --git a/tests/infrastructure/SessionCookieStore.spec.ts b/tests/infrastructure/SessionCookieStore.spec.ts index 14460ca6e..6cf6a7755 100644 --- a/tests/infrastructure/SessionCookieStore.spec.ts +++ b/tests/infrastructure/SessionCookieStore.spec.ts @@ -1,5 +1,5 @@ import { describe, test, expect, beforeEach } from 'vitest'; -import { SessionCookieStore } from '@gridpilot/automation/infrastructure/adapters/automation/auth/SessionCookieStore'; +import { SessionCookieStore } from '@gridpilot/automation/infrastructure//automation/auth/SessionCookieStore'; import type { Cookie } from 'playwright'; const logger = console as any; diff --git a/tests/integration/automation/OverlaySyncService.test.ts b/tests/integration/automation/OverlaySyncService.test.ts index d6f0702c0..abbd7dade 100644 --- a/tests/integration/automation/OverlaySyncService.test.ts +++ b/tests/integration/automation/OverlaySyncService.test.ts @@ -4,9 +4,9 @@ import { configureDIContainer, resetDIContainer } from "../../../apps/companion/ import { DI_TOKENS } from "../../../apps/companion/main/di-tokens"; import { OverlaySyncService } from "@gridpilot/automation/application/services/OverlaySyncService"; import { LoggerPort } from "@gridpilot/automation/application/ports/LoggerPort"; -import { IAutomationLifecycleEmitter, LifecycleCallback } from "@gridpilot/automation/infrastructure/adapters/IAutomationLifecycleEmitter"; +import { IAutomationLifecycleEmitter, LifecycleCallback } from "@gridpilot/automation/infrastructure//IAutomationLifecycleEmitter"; import { AutomationEventPublisherPort, AutomationEvent } from "@gridpilot/automation/application/ports/AutomationEventPublisherPort"; -import { ConsoleLogAdapter } from "@gridpilot/automation/infrastructure/adapters/logging/ConsoleLogAdapter"; +import { ConsoleLogAdapter } from "@gridpilot/automation/infrastructure//logging/ConsoleLogAdapter"; import { describe, it, expect, beforeEach, afterEach, vi, SpyInstance } from 'vitest'; describe("OverlaySyncService Integration with ConsoleLogAdapter", () => { diff --git a/tests/integration/infrastructure/BrowserModeIntegration.test.ts b/tests/integration/infrastructure/BrowserModeIntegration.test.ts index e9e060419..1ff95da9d 100644 --- a/tests/integration/infrastructure/BrowserModeIntegration.test.ts +++ b/tests/integration/infrastructure/BrowserModeIntegration.test.ts @@ -87,7 +87,7 @@ describe('Browser Mode Integration - GREEN Phase', () => { }); const { PlaywrightAutomationAdapter } = await import( - 'core/automation/infrastructure/adapters/automation' + 'core/automation/infrastructure//automation' ); adapter = new PlaywrightAutomationAdapter({ @@ -111,7 +111,7 @@ describe('Browser Mode Integration - GREEN Phase', () => { }); const { PlaywrightAutomationAdapter } = await import( - 'core/automation/infrastructure/adapters/automation' + 'core/automation/infrastructure//automation' ); adapter = new PlaywrightAutomationAdapter({ @@ -135,7 +135,7 @@ describe('Browser Mode Integration - GREEN Phase', () => { }); const { PlaywrightAutomationAdapter } = await import( - 'core/automation/infrastructure/adapters/automation' + 'core/automation/infrastructure//automation' ); adapter = new PlaywrightAutomationAdapter({ @@ -164,7 +164,7 @@ describe('Browser Mode Integration - GREEN Phase', () => { }); const { PlaywrightAutomationAdapter } = await import( - 'core/automation/infrastructure/adapters/automation' + 'core/automation/infrastructure//automation' ); adapter = new PlaywrightAutomationAdapter({ @@ -185,7 +185,7 @@ describe('Browser Mode Integration - GREEN Phase', () => { }); const { PlaywrightAutomationAdapter } = await import( - 'core/automation/infrastructure/adapters/automation' + 'core/automation/infrastructure//automation' ); adapter = new PlaywrightAutomationAdapter({ @@ -228,7 +228,7 @@ describe('Browser Mode Integration - GREEN Phase', () => { }; const { PlaywrightAutomationAdapter } = await import( - 'core/automation/infrastructure/adapters/automation' + 'core/automation/infrastructure//automation' ); adapter = new PlaywrightAutomationAdapter( @@ -259,7 +259,7 @@ describe('Browser Mode Integration - GREEN Phase', () => { }); const { PlaywrightAutomationAdapter } = await import( - 'core/automation/infrastructure/adapters/automation' + 'core/automation/infrastructure//automation' ); const userDataDir = path.join(process.cwd(), 'test-browser-data'); @@ -290,7 +290,7 @@ describe('Browser Mode Integration - GREEN Phase', () => { configurable: true }); const { PlaywrightAutomationAdapter } = await import( - 'core/automation/infrastructure/adapters/automation' + 'core/automation/infrastructure//automation' ); const { BrowserModeConfigLoader } = await import( '../../../core/automation/infrastructure/config/BrowserModeConfig' diff --git a/tests/integration/infrastructure/CheckoutPriceExtractor.test.ts b/tests/integration/infrastructure/CheckoutPriceExtractor.test.ts index 00b758ee3..1a9a6cc63 100644 --- a/tests/integration/infrastructure/CheckoutPriceExtractor.test.ts +++ b/tests/integration/infrastructure/CheckoutPriceExtractor.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { Result } from '../../../core/shared/result/Result'; -import { CheckoutPriceExtractor } from '../../../core/automation/infrastructure/adapters/automation/CheckoutPriceExtractor'; +import { CheckoutPriceExtractor } from '../../../core/automation/infrastructure//automation/CheckoutPriceExtractor'; import { CheckoutStateEnum } from '@gridpilot/automation/domain/value-objects/CheckoutState'; /** diff --git a/tests/integration/infrastructure/FixtureServer.integration.test.ts b/tests/integration/infrastructure/FixtureServer.integration.test.ts index aacf16cda..5a2c7c66e 100644 --- a/tests/integration/infrastructure/FixtureServer.integration.test.ts +++ b/tests/integration/infrastructure/FixtureServer.integration.test.ts @@ -3,7 +3,7 @@ */ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; -import { FixtureServer, getAllStepFixtureMappings, PlaywrightAutomationAdapter } from 'core/automation/infrastructure/adapters/automation'; +import { FixtureServer, getAllStepFixtureMappings, PlaywrightAutomationAdapter } from 'core/automation/infrastructure//automation'; declare const getComputedStyle: any; declare const document: any; diff --git a/tests/integration/infrastructure/MockBrowserAutomationAdapter.test.ts b/tests/integration/infrastructure/MockBrowserAutomationAdapter.test.ts index b22e71cda..a0a29e586 100644 --- a/tests/integration/infrastructure/MockBrowserAutomationAdapter.test.ts +++ b/tests/integration/infrastructure/MockBrowserAutomationAdapter.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import { MockBrowserAutomationAdapter } from 'core/automation/infrastructure/adapters/automation'; +import { MockBrowserAutomationAdapter } from 'core/automation/infrastructure//automation'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; describe('MockBrowserAutomationAdapter Integration Tests', () => { diff --git a/tests/integration/infrastructure/automation/CarsFlow.integration.test.ts b/tests/integration/infrastructure/automation/CarsFlow.integration.test.ts index 6a0150690..55f2b764d 100644 --- a/tests/integration/infrastructure/automation/CarsFlow.integration.test.ts +++ b/tests/integration/infrastructure/automation/CarsFlow.integration.test.ts @@ -1,6 +1,6 @@ import { describe, test, expect } from 'vitest' import type { Page } from 'playwright' -import { PlaywrightAutomationAdapter } from 'core/automation/infrastructure/adapters/automation' +import { PlaywrightAutomationAdapter } from 'core/automation/infrastructure//automation' describe('CarsFlow integration', () => { test('adapter emits panel-attached then action-started then action-complete for performAddCar', async () => { diff --git a/tests/integration/infrastructure/automation/OverlayLifecycle.integration.test.ts b/tests/integration/infrastructure/automation/OverlayLifecycle.integration.test.ts index e51e8644b..76618da71 100644 --- a/tests/integration/infrastructure/automation/OverlayLifecycle.integration.test.ts +++ b/tests/integration/infrastructure/automation/OverlayLifecycle.integration.test.ts @@ -4,7 +4,7 @@ import type { AutomationEvent } from 'core/automation/application/ports/IAutomat import type { IAutomationLifecycleEmitter, LifecycleCallback, -} from 'core/automation/infrastructure/adapters/IAutomationLifecycleEmitter'; +} from 'core/automation/infrastructure//IAutomationLifecycleEmitter'; import type { OverlayAction, ActionAck, diff --git a/tests/integration/interface/companion/companion-start-automation.browser-mode-refresh.integration.test.ts b/tests/integration/interface/companion/companion-start-automation.browser-mode-refresh.integration.test.ts index 022dceaf8..8c1ab052f 100644 --- a/tests/integration/interface/companion/companion-start-automation.browser-mode-refresh.integration.test.ts +++ b/tests/integration/interface/companion/companion-start-automation.browser-mode-refresh.integration.test.ts @@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { DIContainer } from '../../../..//apps/companion/main/di-container'; import type { HostedSessionConfig } from '@gridpilot/automation/domain/types/HostedSessionConfig'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; -import { PlaywrightAutomationAdapter } from '../../../..//core/automation/infrastructure/adapters/automation'; +import { PlaywrightAutomationAdapter } from '../../../..//core/automation/infrastructure//automation'; describe('companion start automation - browser mode refresh wiring', () => { const originalEnv = { ...process.env }; diff --git a/tests/integration/interface/companion/companion-start-automation.browser-not-connected.integration.test.ts b/tests/integration/interface/companion/companion-start-automation.browser-not-connected.integration.test.ts index 735441e28..8ddf95072 100644 --- a/tests/integration/interface/companion/companion-start-automation.browser-not-connected.integration.test.ts +++ b/tests/integration/interface/companion/companion-start-automation.browser-not-connected.integration.test.ts @@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { DIContainer } from '../../../..//apps/companion/main/di-container'; import type { HostedSessionConfig } from '@gridpilot/automation/domain/types/HostedSessionConfig'; import { StepId } from '@gridpilot/automation/domain/value-objects/StepId'; -import { PlaywrightAutomationAdapter } from '../../../..//core/automation/infrastructure/adapters/automation'; +import { PlaywrightAutomationAdapter } from '../../../..//core/automation/infrastructure//automation'; describe('companion start automation - browser not connected at step 1', () => { const originalEnv = { ...process.env }; diff --git a/tests/integration/interface/companion/companion-start-automation.connection-failure.integration.test.ts b/tests/integration/interface/companion/companion-start-automation.connection-failure.integration.test.ts index 4f6660cec..90025b151 100644 --- a/tests/integration/interface/companion/companion-start-automation.connection-failure.integration.test.ts +++ b/tests/integration/interface/companion/companion-start-automation.connection-failure.integration.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { DIContainer } from '../../../..//apps/companion/main/di-container'; import type { HostedSessionConfig } from '@gridpilot/automation/domain/types/HostedSessionConfig'; -import { PlaywrightAutomationAdapter } from '../../../..//core/automation/infrastructure/adapters/automation'; +import { PlaywrightAutomationAdapter } from '../../../..//core/automation/infrastructure//automation'; describe('companion start automation - browser connection failure before steps', () => { const originalEnv = { ...process.env }; diff --git a/tests/smoke/electron-init.smoke.test.ts b/tests/smoke/electron-init.smoke.test.ts index aac30dd2e..3d5fc2a4f 100644 --- a/tests/smoke/electron-init.smoke.test.ts +++ b/tests/smoke/electron-init.smoke.test.ts @@ -5,9 +5,9 @@ import { CheckAuthenticationUseCase } from '../../core/automation/application/us import { InitiateLoginUseCase } from '../../core/automation/application/use-cases/InitiateLoginUseCase'; import { ClearSessionUseCase } from '../../core/automation/application/use-cases/ClearSessionUseCase'; import { ConfirmCheckoutUseCase } from '../../core/automation/application/use-cases/ConfirmCheckoutUseCase'; -import { PlaywrightAutomationAdapter } from 'core/automation/infrastructure/adapters/automation'; +import { PlaywrightAutomationAdapter } from 'core/automation/infrastructure//automation'; import { InMemorySessionRepository } from '../../core/automation/infrastructure/repositories/InMemorySessionRepository'; -import { NoOpLogAdapter } from '../../core/automation/infrastructure/adapters/logging/NoOpLogAdapter'; +import { NoOpLogAdapter } from '../../core/automation/infrastructure//logging/NoOpLogAdapter'; // Mock Electron's app module vi.mock('electron', () => ({ diff --git a/tests/smoke/playwright-init.smoke.test.ts b/tests/smoke/playwright-init.smoke.test.ts index 7106a2ab2..a08417662 100644 --- a/tests/smoke/playwright-init.smoke.test.ts +++ b/tests/smoke/playwright-init.smoke.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, afterEach, beforeAll, afterAll } from 'vitest'; -import { PlaywrightAutomationAdapter, FixtureServer } from 'core/automation/infrastructure/adapters/automation'; -import { NoOpLogAdapter } from '../../core/automation/infrastructure/adapters/logging/NoOpLogAdapter'; +import { PlaywrightAutomationAdapter, FixtureServer } from 'core/automation/infrastructure//automation'; +import { NoOpLogAdapter } from '../../core/automation/infrastructure//logging/NoOpLogAdapter'; describe('Playwright Adapter Smoke Tests', () => { let adapter: PlaywrightAutomationAdapter | undefined;