diff --git a/packages/infrastructure/adapters/automation/PlaywrightAutomationAdapter.ts b/packages/infrastructure/adapters/automation/PlaywrightAutomationAdapter.ts index e1702dda5..af99a221d 100644 --- a/packages/infrastructure/adapters/automation/PlaywrightAutomationAdapter.ts +++ b/packages/infrastructure/adapters/automation/PlaywrightAutomationAdapter.ts @@ -960,6 +960,20 @@ export class PlaywrightAutomationAdapter implements IBrowserAutomation, IAuthent // In real mode, a modal appears asking "Last Settings" or "New Race" - click "New Race" if (this.isRealMode()) { await this.clickNewRaceInModal(); + // Ensure Race Information panel is visible by clicking sidebar nav then waiting for fallback selectors + const raceInfoFallback = '#set-session-information, .wizard-step[id*="session"], .wizard-step[id*="race-information"]'; + try { + try { await this.page!.click('[data-testid="wizard-nav-set-session-information"]'); this.log('debug','Clicked wizard nav for Race Information', { selector: '[data-testid="wizard-nav-set-session-information"]' }); } catch (e) { this.log('debug','Wizard nav for Race Information not present (continuing)', { error: String(e) }); } + await this.page!.waitForSelector(raceInfoFallback, { state: 'attached', timeout: 5000 }); + this.log('info','Race Information panel found', { selector: raceInfoFallback }); + } catch (err) { + this.log('warn','Race Information panel not found with fallback selector, dumping #create-race-wizard innerHTML', { selector: raceInfoFallback }); + const inner = await this.page!.evaluate(() => document.querySelector('#create-race-wizard')?.innerHTML || ''); + this.log('debug','create-race-wizard innerHTML (truncated)', { html: inner ? inner.substring(0,2000) : '' }); + // Retry nav click once then wait longer before failing + try { await this.page!.click('[data-testid="wizard-nav-set-session-information"]'); } catch {} + await this.page!.waitForSelector(raceInfoFallback, { state: 'attached', timeout: 10000 }); + } } // Fill form fields if provided @@ -1047,7 +1061,30 @@ export class PlaywrightAutomationAdapter implements IBrowserAutomation, IAuthent return { success: true }; } - await this.waitForWizardStep('cars'); + // Robust: try opening Cars via sidebar nav then wait for a set of fallback selectors. + const carsFallbackSelector = '#set-cars, .wizard-step[id*="cars"], .cars-panel'; + try { + try { + await this.page!.click('[data-testid="wizard-nav-set-cars"]'); + this.log('debug', 'Clicked wizard nav for Cars', { selector: '[data-testid="wizard-nav-set-cars"]' }); + } catch (e) { + this.log('debug', 'Wizard nav for Cars not present (continuing)', { error: String(e) }); + } + + try { + await this.page!.waitForSelector(carsFallbackSelector, { state: 'attached', timeout: 5000 }); + this.log('info', 'Cars panel found', { selector: carsFallbackSelector }); + } catch (err) { + this.log('warn', 'Cars panel not found with fallback selector, dumping #create-race-wizard innerHTML', { selector: carsFallbackSelector }); + const inner = await this.page!.evaluate(() => document.querySelector('#create-race-wizard')?.innerHTML || ''); + this.log('debug', 'create-race-wizard innerHTML (truncated)', { html: inner ? inner.substring(0, 2000) : '' }); + // Retry nav click once then wait longer before failing + try { await this.page!.click('[data-testid="wizard-nav-set-cars"]'); } catch {} + await this.page!.waitForSelector(carsFallbackSelector, { state: 'attached', timeout: 10000 }); + } + } catch (e) { + this.log('error', 'Failed waiting for Cars panel', { error: String(e), selector: carsFallbackSelector }); + } await this.checkWizardDismissed(step); } @@ -1057,7 +1094,7 @@ export class PlaywrightAutomationAdapter implements IBrowserAutomation, IAuthent expectedStep: 'cars', requiredSelectors: this.isRealMode() ? [IRACING_SELECTORS.steps.addCarButton] - : ['#set-cars'], // Mock mode: check for Cars container + : ['#set-cars, .wizard-step[id*="cars"], .cars-panel'], // Mock mode: check for Cars container (fallbacks) forbiddenSelectors: ['#set-track'] }); @@ -1126,7 +1163,7 @@ export class PlaywrightAutomationAdapter implements IBrowserAutomation, IAuthent expectedStep: 'cars', requiredSelectors: this.isRealMode() ? [IRACING_SELECTORS.steps.addCarButton] - : ['#set-cars'], // Mock mode: check for Cars container + : ['#set-cars, .wizard-step[id*="cars"], .cars-panel'], // Mock mode: check for Cars container (fallbacks) forbiddenSelectors: ['#set-track'] }); @@ -1357,7 +1394,30 @@ export class PlaywrightAutomationAdapter implements IBrowserAutomation, IAuthent return { success: true }; } - await this.waitForWizardStep('weather'); + // Robust: try opening Weather via sidebar nav then wait for a set of fallback selectors. + const weatherFallbackSelector = '#set-weather, .wizard-step[id*="weather"], .wizard-step[data-step="weather"], .weather-panel'; + try { + try { + await this.page!.click('[data-testid="wizard-nav-set-weather"]'); + this.log('debug', 'Clicked wizard nav for Weather', { selector: '[data-testid="wizard-nav-set-weather"]' }); + } catch (e) { + this.log('debug', 'Wizard nav for Weather not present (continuing)', { error: String(e) }); + } + + try { + await this.page!.waitForSelector(weatherFallbackSelector, { state: 'attached', timeout: 5000 }); + this.log('info', 'Weather panel found', { selector: weatherFallbackSelector }); + } catch (err) { + this.log('warn', 'Weather panel not found with fallback selector, dumping #create-race-wizard innerHTML', { selector: weatherFallbackSelector }); + const inner = await this.page!.evaluate(() => document.querySelector('#create-race-wizard')?.innerHTML || ''); + this.log('debug', 'create-race-wizard innerHTML (truncated)', { html: inner ? inner.substring(0, 2000) : '' }); + // Retry nav click once then wait longer before failing + try { await this.page!.click('[data-testid="wizard-nav-set-weather"]'); } catch {} + await this.page!.waitForSelector(weatherFallbackSelector, { state: 'attached', timeout: 10000 }); + } + } catch (e) { + this.log('error', 'Failed waiting for Weather panel', { error: String(e), selector: weatherFallbackSelector }); + } await this.checkWizardDismissed(step); } if (config.timeOfDay !== undefined) {