import { Result } from '../../shared/result/Result'; /** * Configuration for page state validation. * Defines expected and forbidden elements on the current page. */ export interface PageStateValidation { /** Expected wizard step name (e.g., 'cars', 'track') */ expectedStep: string; /** Selectors that MUST be present on the page */ requiredSelectors: string[]; /** Selectors that MUST NOT be present on the page */ forbiddenSelectors?: string[]; } /** * Result of page state validation. */ export interface PageStateValidationResult { isValid: boolean; message: string; expectedStep: string; missingSelectors?: string[]; unexpectedSelectors?: string[]; } /** * Domain service for validating page state during wizard navigation. * * Purpose: Prevent navigation bugs by ensuring each step executes on the correct page. * * Clean Architecture: This is pure domain logic with no infrastructure dependencies. * It validates state based on selector presence/absence without knowing HOW to check them. */ export class PageStateValidator { /** * Validate that the page state matches expected conditions. * * @param actualState Function that checks if selectors exist on the page * @param validation Expected page state configuration * @returns Result with validation outcome */ validateState( actualState: (selector: string) => boolean, validation: PageStateValidation ): Result { try { const { expectedStep, requiredSelectors, forbiddenSelectors = [] } = validation; // Check required selectors are present const missingSelectors = requiredSelectors.filter(selector => !actualState(selector)); if (missingSelectors.length > 0) { const result: PageStateValidationResult = { isValid: false, message: `Page state mismatch: Expected to be on "${expectedStep}" page but missing required elements`, expectedStep, missingSelectors }; return Result.ok(result); } // Check forbidden selectors are absent const unexpectedSelectors = forbiddenSelectors.filter(selector => actualState(selector)); if (unexpectedSelectors.length > 0) { const result: PageStateValidationResult = { isValid: false, message: `Page state mismatch: Found unexpected elements on "${expectedStep}" page`, expectedStep, unexpectedSelectors }; return Result.ok(result); } // All checks passed const result: PageStateValidationResult = { isValid: true, message: `Page state valid for "${expectedStep}"`, expectedStep }; return Result.ok(result); } catch (error) { return Result.err( error instanceof Error ? error : new Error(`Page state validation failed: ${String(error)}`) ); } } }