dumps optimized

This commit is contained in:
2025-11-27 14:46:11 +01:00
parent 6a0cab6cc6
commit 1348c37675
48 changed files with 134350 additions and 7912 deletions

View File

@@ -38,7 +38,7 @@ export class FixtureServer implements IFixtureServer {
private fixturesPath: string;
constructor(fixturesPath?: string) {
this.fixturesPath = fixturesPath ?? path.resolve(process.cwd(), 'resources/mock-fixtures');
this.fixturesPath = fixturesPath ?? path.resolve(process.cwd(), 'html-dumps');
}
async start(port: number = 3456): Promise<{ url: string; port: number }> {

View File

@@ -17,42 +17,42 @@ export const IRACING_SELECTORS = {
hostedRacing: {
// Main "Create a Race" button on the hosted sessions page
createRaceButton: 'button:has-text("Create a Race"), button[aria-label="Create a Race"]',
hostedTab: '[aria-label*="Hosted" i], [role="tab"]:has-text("Hosted")',
hostedTab: 'a:has-text("Hosted")',
// Modal that appears after clicking "Create a Race"
createRaceModal: '#confirm-create-race-modal, .modal:has-text("Create a Race")',
createRaceModal: '#modal-children-container, .modal-content',
// "New Race" button in the modal body (not footer) - two side-by-side buttons in a row
// Verified from real iRacing HTML: buttons are <a class="btn btn-lg btn-info btn-block"> in modal-body
newRaceButton: '#confirm-create-race-modal .modal-body a.btn:has-text("New Race"), #confirm-create-race-modal a.btn:has(.icon-wand)',
lastSettingsButton: '#confirm-create-race-modal .modal-body a.btn:has-text("Last Settings"), #confirm-create-race-modal a.btn:has(.icon-servers)',
newRaceButton: 'a.btn:has-text("New Race")',
lastSettingsButton: 'a.btn:has-text("Last Settings")',
},
// Common modal/wizard selectors - VERIFIED from real HTML
wizard: {
modal: '#create-race-modal, [role="dialog"], .modal, .modal.show, .modal.fade.in, [data-modal="true"]',
modalDialog: '#create-race-modal-modal-dialog, .modal-dialog',
modalContent: '#create-race-modal .modal-content, .modal-content, .modal-body',
modal: '#create-race-modal-modal-content, .modal-content',
modalDialog: '.modal-dialog',
modalContent: '#create-race-modal-modal-content, .modal-content',
modalTitle: '[data-testid="modal-title"], .modal-title',
// Wizard footer buttons - these are anchor tags styled as buttons
// The "Next" button shows the name of the next step (e.g., "Server Details")
nextButton: '.wizard-footer a.btn:not(.disabled):has(.icon-caret-right)',
backButton: '.wizard-footer a.btn:has(.icon-caret-left):has-text("Back")',
// In the dumps, the footer has two buttons: Previous Step (left) and Next Step (right)
nextButton: '.wizard-footer a.btn:last-child',
backButton: '.wizard-footer a.btn:first-child',
// Modal footer actions
confirmButton: '.modal-footer a.btn-success, button:has-text("Confirm"), button:has-text("OK")',
cancelButton: '.modal-footer a.btn-secondary:has-text("Back"), button:has-text("Cancel")',
closeButton: '.modal-header a.close, [aria-label="Close"]',
// Wizard sidebar navigation links - VERIFIED IDs from real HTML
closeButton: '[data-testid="button-close-modal"]',
// Wizard sidebar navigation links - VERIFIED from dumps
sidebarLinks: {
raceInformation: '#wizard-sidebar-link-set-session-information',
serverDetails: '#wizard-sidebar-link-set-server-details',
admins: '#wizard-sidebar-link-set-admins',
timeLimit: '#wizard-sidebar-link-set-time-limit',
cars: '#wizard-sidebar-link-set-cars',
track: '#wizard-sidebar-link-set-track',
trackOptions: '#wizard-sidebar-link-set-track-options',
timeOfDay: '#wizard-sidebar-link-set-time-of-day',
weather: '#wizard-sidebar-link-set-weather',
raceOptions: '#wizard-sidebar-link-set-race-options',
trackConditions: '#wizard-sidebar-link-set-track-conditions',
raceInformation: '[data-testid="wizard-nav-set-session-information"]',
serverDetails: '[data-testid="wizard-nav-set-server-details"]',
admins: '[data-testid="wizard-nav-set-admins"]',
timeLimit: '[data-testid="wizard-nav-set-time-limit"]',
cars: '[data-testid="wizard-nav-set-cars"]',
track: '[data-testid="wizard-nav-set-track"]',
trackOptions: '[data-testid="wizard-nav-set-track-options"]',
timeOfDay: '[data-testid="wizard-nav-set-time-of-day"]',
weather: '[data-testid="wizard-nav-set-weather"]',
raceOptions: '[data-testid="wizard-nav-set-race-options"]',
trackConditions: '[data-testid="wizard-nav-set-track-conditions"]',
},
// Wizard step containers (the visible step content)
stepContainers: {
@@ -99,38 +99,38 @@ export const IRACING_SELECTORS = {
startNow: '#set-server-details .switch-checkbox, #set-server-details input[type="checkbox"], [data-toggle="startNow"], input[data-toggle="startNow"]',
// Step 5/6: Admins
adminSearch: '.wizard-sidebar input[placeholder*="Search"], #set-admins input[placeholder*="Search"], .wizard-sidebar input[data-search], #set-admins input[data-search], input[data-field="adminSearch"]',
adminList: '#set-admins [data-list="admins"], [data-list="admins"]',
adminSearch: 'input[placeholder*="Search"]',
adminList: '[data-list="admins"]', // Keep generic if not found in dumps, but search input is verified
addAdminButton: 'a.btn:has-text("Add an Admin")',
// Step 7: Time Limits - Bootstrap-slider uses hidden input[type="text"] with id containing slider name
// Also targets the visible slider handle for interaction
practice: '#set-time-limit input[id*="practice"], #set-time-limit .slider input[type="text"], #set-time-limit [data-slider="practice"]',
qualify: '#set-time-limit input[id*="qualify"], #set-time-limit .slider input[type="text"], #set-time-limit [data-slider="qualify"]',
race: '#set-time-limit input[id*="race"], #set-time-limit .slider input[type="text"], #set-time-limit [data-slider="race"]',
// Dumps show dynamic IDs like time-limit-slider1763726367635
practice: 'input[id*="time-limit-slider"]', // This is risky if multiple sliders share the same ID pattern.
// TODO: Need better selectors for specific sliders if they exist.
// For now, we'll assume the automation handles finding the right one by index or label if possible.
qualify: 'input[id*="qualify"], input[id*="time-limit-slider"]',
race: 'input[id*="race"], input[id*="time-limit-slider"]',
// Step 8/9: Cars
carSearch: '.wizard-sidebar input[placeholder*="Search"], #set-cars input[placeholder*="Search"], .modal input[placeholder*="Search"], input[data-search], input[data-field="carSearch"], [data-modal-trigger="car"]',
carList: '#set-cars [data-list="cars"], [data-list="cars"]',
carSearch: 'input[placeholder*="Search"]',
carList: 'table.table.table-striped',
// Add Car button - triggers car selection interface in wizard sidebar
// CORRECTED: Added fallback selectors since .icon-plus cannot be verified in minified HTML
addCarButton: '#set-cars a.btn:has(.icon-plus), #set-cars .card-header a.btn, #set-cars button:has-text("Add"), #set-cars a.btn:has-text("Add")',
addCarButton: 'a.btn:has-text("Add a Car")',
// Car selection interface - CORRECTED: No separate modal, uses wizard sidebar within main modal
addCarModal: '#create-race-modal .wizard-sidebar, #set-cars .wizard-sidebar, .wizard-sidebar:has(input[placeholder*="Search"]), [data-modal="true"], #set-cars [data-modal="true"]',
addCarModal: '.wizard-sidebar',
// Select button inside car table row - clicking this adds the car immediately (no confirm step)
// The "Select" button is an anchor styled as: a.btn.btn-block.btn-primary.btn-xs
carSelectButton: '.wizard-sidebar table .btn-primary.btn-xs:has-text("Select"), #set-cars table .btn-primary.btn-xs:has-text("Select"), .modal table .btn-primary:has-text("Select")',
carSelectButton: 'a.btn:has-text("Select")',
// Step 10/11/12: Track
trackSearch: '.wizard-sidebar input[placeholder*="Search"], #set-track input[placeholder*="Search"], .modal input[placeholder*="Search"]',
trackList: '#set-track [data-list="tracks"]',
trackSearch: 'input[placeholder*="Search"]',
trackList: 'table.table.table-striped',
// Add Track button - triggers track selection interface in wizard sidebar
// CORRECTED: Added fallback selectors since .icon-plus cannot be verified in minified HTML
addTrackButton: '#set-track a.btn:has(.icon-plus), #set-track .card-header a.btn, #set-track button:has-text("Add"), #set-track a.btn:has-text("Add")',
addTrackButton: 'a.btn:has-text("Add a Track")',
// Track selection interface - CORRECTED: No separate modal, uses wizard sidebar within main modal
addTrackModal: '#create-race-modal .wizard-sidebar, #set-track .wizard-sidebar, .wizard-sidebar:has(input[placeholder*="Search"]), [data-modal="true"], #set-track [data-modal="true"]',
addTrackModal: '.wizard-sidebar',
// Select button inside track table row - clicking this selects the track immediately (no confirm step)
// Prefer direct buttons (not dropdown toggles) for single-config tracks
trackSelectButton: '.wizard-sidebar table a.btn.btn-primary.btn-xs:not(.dropdown-toggle), #set-track table a.btn.btn-primary.btn-xs:not(.dropdown-toggle)',
trackSelectButton: 'a.btn:has-text("Select")',
// Dropdown toggle for multi-config tracks - opens a menu of track configurations
trackSelectDropdown: '.wizard-sidebar table a.btn.btn-primary.btn-xs.dropdown-toggle, #set-track table a.btn.btn-primary.btn-xs.dropdown-toggle',
// First item in the dropdown menu for selecting track configuration