/** * Selector configuration for template generation. * Maps HTML fixture files to CSS selectors and output PNG paths. * * Since the iRacing UI uses Chakra UI with hashed CSS classes, * we rely on text content, aria-labels, and semantic selectors. */ export interface ElementCapture { selector: string; outputPath: string; description: string; waitFor?: string; } export interface FixtureConfig { htmlFile: string; captures: ElementCapture[]; } export const TEMPLATE_BASE_PATH = 'resources/templates/iracing'; export const FIXTURES_BASE_PATH = 'resources/iracing-hosted-sessions'; export const SELECTOR_CONFIG: FixtureConfig[] = [ { htmlFile: '01-hosted-racing.html', captures: [ { selector: 'text="Hosted Racing"', outputPath: 'step02-hosted/hosted-racing-tab.png', description: 'Hosted Racing tab indicator', }, { selector: 'text="Create a Race"', outputPath: 'step02-hosted/create-race-button.png', description: 'Create a Race button', }, ], }, { htmlFile: '02-create-a-race.html', captures: [ { selector: '[role="dialog"]', outputPath: 'step03-create/create-race-modal.png', description: 'Create race modal', }, { selector: 'button:has-text("Create")', outputPath: 'step03-create/confirm-button.png', description: 'Confirm create race button', }, ], }, { htmlFile: '03-race-information.html', captures: [ { selector: 'text="Race Information"', outputPath: 'step04-info/race-info-indicator.png', description: 'Race information step indicator', }, { selector: 'input[placeholder*="Session" i], input[name*="session" i], label:has-text("Session Name") + input', outputPath: 'step04-info/session-name-field.png', description: 'Session name input field', }, { selector: 'input[type="password"], label:has-text("Password") + input', outputPath: 'step04-info/password-field.png', description: 'Session password field', }, { selector: 'textarea, label:has-text("Description") + textarea', outputPath: 'step04-info/description-field.png', description: 'Session description textarea', }, { selector: 'button:has-text("Next")', outputPath: 'step04-info/next-button.png', description: 'Next button', }, ], }, { htmlFile: '04-server-details.html', captures: [ { selector: 'text="Server Details"', outputPath: 'step05-server/server-details-indicator.png', description: 'Server details step indicator', }, { selector: 'select, [role="listbox"], label:has-text("Region") ~ select', outputPath: 'step05-server/region-dropdown.png', description: 'Server region dropdown', }, { selector: 'button:has-text("Next")', outputPath: 'step05-server/next-button.png', description: 'Next button', }, ], }, { htmlFile: '05-set-admins.html', captures: [ { selector: 'text="Admins"', outputPath: 'step06-admins/admins-indicator.png', description: 'Admins step indicator', }, { selector: 'button:has-text("Add Admin")', outputPath: 'step06-admins/add-admin-button.png', description: 'Add admin button', }, { selector: 'button:has-text("Next")', outputPath: 'step06-admins/next-button.png', description: 'Next button', }, ], }, { htmlFile: '06-add-an-admin.html', captures: [ { selector: '[role="dialog"]', outputPath: 'step06-admins/admin-modal.png', description: 'Add admin modal', }, { selector: 'input[type="search"], input[placeholder*="search" i]', outputPath: 'step06-admins/search-field.png', description: 'Admin search field', }, ], }, { htmlFile: '07-time-limits.html', captures: [ { selector: 'text="Time Limits"', outputPath: 'step07-time/time-limits-indicator.png', description: 'Time limits step indicator', }, { selector: 'label:has-text("Practice") ~ input, input[name*="practice" i]', outputPath: 'step07-time/practice-field.png', description: 'Practice length field', }, { selector: 'label:has-text("Qualify") ~ input, input[name*="qualify" i]', outputPath: 'step07-time/qualify-field.png', description: 'Qualify length field', }, { selector: 'label:has-text("Race") ~ input, input[name*="race" i]', outputPath: 'step07-time/race-field.png', description: 'Race length field', }, { selector: 'button:has-text("Next")', outputPath: 'step07-time/next-button.png', description: 'Next button', }, ], }, { htmlFile: '08-set-cars.html', captures: [ { selector: 'text="Cars"', outputPath: 'step08-cars/cars-indicator.png', description: 'Cars step indicator', }, { selector: 'button:has-text("Add Car"), button:has-text("Add a Car")', outputPath: 'step08-cars/add-car-button.png', description: 'Add car button', }, { selector: 'button:has-text("Next")', outputPath: 'step08-cars/next-button.png', description: 'Next button', }, ], }, { htmlFile: '09-add-a-car.html', captures: [ { selector: '[role="dialog"]', outputPath: 'step09-addcar/car-modal.png', description: 'Add car modal', }, { selector: 'input[type="search"], input[placeholder*="search" i]', outputPath: 'step09-addcar/search-field.png', description: 'Car search field', }, { selector: 'button:has-text("Select"), button:has-text("Add")', outputPath: 'step09-addcar/select-button.png', description: 'Select car button', }, { selector: 'button[aria-label="Close"], button:has-text("Close")', outputPath: 'step09-addcar/close-button.png', description: 'Close modal button', }, ], }, { htmlFile: '10-set-car-classes.html', captures: [ { selector: 'text="Car Classes"', outputPath: 'step10-classes/car-classes-indicator.png', description: 'Car classes step indicator', }, { selector: 'select, [role="listbox"]', outputPath: 'step10-classes/class-dropdown.png', description: 'Car class dropdown', }, { selector: 'button:has-text("Next")', outputPath: 'step10-classes/next-button.png', description: 'Next button', }, ], }, { htmlFile: '11-set-track.html', captures: [ { selector: 'text="Track"', outputPath: 'step11-track/track-indicator.png', description: 'Track step indicator', }, { selector: 'button:has-text("Add Track"), button:has-text("Add a Track")', outputPath: 'step11-track/add-track-button.png', description: 'Add track button', }, { selector: 'button:has-text("Next")', outputPath: 'step11-track/next-button.png', description: 'Next button', }, ], }, { htmlFile: '12-add-a-track.html', captures: [ { selector: '[role="dialog"]', outputPath: 'step12-addtrack/track-modal.png', description: 'Add track modal', }, { selector: 'input[type="search"], input[placeholder*="search" i]', outputPath: 'step12-addtrack/search-field.png', description: 'Track search field', }, { selector: 'button:has-text("Select"), button:has-text("Add")', outputPath: 'step12-addtrack/select-button.png', description: 'Select track button', }, { selector: 'button[aria-label="Close"], button:has-text("Close")', outputPath: 'step12-addtrack/close-button.png', description: 'Close modal button', }, ], }, { htmlFile: '13-track-options.html', captures: [ { selector: 'text="Track Options"', outputPath: 'step13-trackopts/track-options-indicator.png', description: 'Track options step indicator', }, { selector: 'select, [role="listbox"]', outputPath: 'step13-trackopts/config-dropdown.png', description: 'Track configuration dropdown', }, { selector: 'button:has-text("Next")', outputPath: 'step13-trackopts/next-button.png', description: 'Next button', }, ], }, { htmlFile: '14-time-of-day.html', captures: [ { selector: 'text="Time of Day"', outputPath: 'step14-tod/time-of-day-indicator.png', description: 'Time of day step indicator', }, { selector: 'input[type="range"], [role="slider"]', outputPath: 'step14-tod/time-slider.png', description: 'Time of day slider', }, { selector: 'input[type="date"], [data-testid*="date"]', outputPath: 'step14-tod/date-picker.png', description: 'Date picker', }, { selector: 'button:has-text("Next")', outputPath: 'step14-tod/next-button.png', description: 'Next button', }, ], }, { htmlFile: '15-weather.html', captures: [ { selector: 'text="Weather"', outputPath: 'step15-weather/weather-indicator.png', description: 'Weather step indicator', }, { selector: 'select, [role="listbox"]', outputPath: 'step15-weather/weather-dropdown.png', description: 'Weather type dropdown', }, { selector: 'input[type="number"], label:has-text("Temperature") ~ input', outputPath: 'step15-weather/temperature-field.png', description: 'Temperature field', }, { selector: 'button:has-text("Next")', outputPath: 'step15-weather/next-button.png', description: 'Next button', }, ], }, { htmlFile: '16-race-options.html', captures: [ { selector: 'text="Race Options"', outputPath: 'step16-race/race-options-indicator.png', description: 'Race options step indicator', }, { selector: 'input[type="number"], label:has-text("Max") ~ input', outputPath: 'step16-race/max-drivers-field.png', description: 'Maximum drivers field', }, { selector: '[role="switch"], input[type="checkbox"]', outputPath: 'step16-race/rolling-start-toggle.png', description: 'Rolling start toggle', }, { selector: 'button:has-text("Next")', outputPath: 'step16-race/next-button.png', description: 'Next button', }, ], }, { htmlFile: '17-team-driving.html', captures: [ { selector: 'text="Team Driving"', outputPath: 'step17-team/team-driving-indicator.png', description: 'Team driving step indicator', }, { selector: '[role="switch"], input[type="checkbox"]', outputPath: 'step17-team/team-driving-toggle.png', description: 'Team driving toggle', }, { selector: 'button:has-text("Next")', outputPath: 'step17-team/next-button.png', description: 'Next button', }, ], }, { htmlFile: '18-track-conditions.html', captures: [ { selector: 'text="Track Conditions"', outputPath: 'step18-conditions/track-conditions-indicator.png', description: 'Track conditions step indicator', }, { selector: 'select, [role="listbox"]', outputPath: 'step18-conditions/track-state-dropdown.png', description: 'Track state dropdown', }, { selector: '[role="switch"], input[type="checkbox"]', outputPath: 'step18-conditions/marbles-toggle.png', description: 'Marbles toggle', }, ], }, ]; /** * Common templates that appear across multiple steps */ export const COMMON_CAPTURES: ElementCapture[] = [ { selector: 'button:has-text("Next")', outputPath: 'common/next-button.png', description: 'Generic next button for wizard navigation', }, { selector: 'button:has-text("Back")', outputPath: 'common/back-button.png', description: 'Generic back button for wizard navigation', }, { selector: 'button[aria-label="Close"], [aria-label="close"]', outputPath: 'common/close-modal-button.png', description: 'Close modal button', }, ];