Files
gridpilot.gg/scripts/generate-templates/SelectorConfig.ts

436 lines
12 KiB
TypeScript

/**
* 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',
},
];