iRacing Selectors Update Plan
Date: 2025-11-27
Based on: HTML dumps from html-dumps-optimized/iracing-hosted-sessions/ (01-18) vs IRacingSelectors.ts.
Goal: Verify selectors against recent dumps, propose updates for stability (React/Chakra UI resilience), prioritize fixes.
Clean Architecture Impact
Selectors adhere to Clean Arch by relying on stable attributes (text, aria-label, data-testid, IDs like #set-*) rather than volatile classes. Updates reinforce this: prefer :has-text(), data-testid, label proximity over class names. No cross-layer leaks; selectors are pure infrastructure adapters.
Priority Summary
| Priority |
Count |
Examples |
| Critical (broken) |
2 |
adminList (no [data-list="admins"]), generic sliders (risky ID match) |
| Recommended (stability) |
8 |
Time sliders (add label context), fields (add chakra-), unconfirmed fields (label-for/placeholder) |
| Optional (enhancements) |
5 |
Add Car/Track buttons (dynamic count handling), BLOCKED_SELECTORS (chakra-button) |
| Verified/Matches |
70+ |
Wizard nav/step IDs, most buttons/text |
Total selectors needing updates: 15
Selector Verification Tables
login
| Selector |
Current Selector |
Status |
Evidence (Dump) |
Proposed |
Priority |
| emailInput |
#username, input[name="username"], input[type="email"] |
Unconfirmed |
No login dump |
N/A |
- |
| passwordInput |
#password, input[type="password"] |
Unconfirmed |
No login dump |
N/A |
- |
| submitButton |
button[type="submit"], button:has-text("Sign In") |
Unconfirmed |
No login dump |
N/A |
- |
hostedRacing
| Selector |
Current Selector |
Status |
Evidence (Dump) |
Proposed |
Priority |
| createRaceButton |
button:has-text("Create a Race"), button[aria-label="Create a Race"] |
Matches |
01-hosted-racing.json: bu.chakra-button:0 t:"Create a Race" |
N/A |
Verified |
| hostedTab |
a:has-text("Hosted") |
Matches |
01: sidebar a.c0:2 t:"Hosted" |
N/A |
Verified |
| createRaceModal |
#modal-children-container, .modal-content |
Matches |
02: #confirm-create-race-modal-modal-content |
N/A |
Verified |
| newRaceButton |
a.btn:has-text("New Race") |
Matches |
02: a.btn.btn-lg:1 t:"New Race" |
N/A |
Verified |
| lastSettingsButton |
a.btn:has-text("Last Settings") |
Matches |
02: a.btn.btn-lg:0 t:"Last Settings" |
N/A |
Verified |
wizard
Core
| Selector |
Current Selector |
Status |
Evidence |
Proposed |
Priority |
| modal |
#create-race-modal-modal-content, .modal-content |
Matches |
All dumps: #create-race-modal-modal-content |
N/A |
Verified |
| modalDialog |
.modal-dialog |
Matches |
Dumps: #create-race-modal-modal-dialog |
N/A |
Verified |
| modalContent |
#create-race-modal-modal-content, .modal-content |
Matches |
Dumps |
N/A |
Verified |
| modalTitle |
[data-testid="modal-title"], .modal-title |
Unconfirmed |
No exact match |
[data-testid="modal-title"] |
Optional |
| nextButton |
.wizard-footer a.btn:last-child |
Matches |
03,05,07: d.wizard-footer@4>d.pull-xs-left>a.btn.btn-sm:1 (dynamic text) |
N/A |
Verified |
| backButton |
.wizard-footer a.btn:first-child |
Matches |
Dumps: first-child |
N/A |
Verified |
| confirmButton |
.modal-footer a.btn-success, button:has-text("Confirm") |
Unconfirmed |
No final confirm dump |
N/A |
- |
| cancelButton |
.modal-footer a.btn-secondary:has-text("Back") |
Matches |
Dumps: "Back" |
N/A |
Verified |
| closeButton |
[data-testid="button-close-modal"] |
Matches |
Dumps: data-testid=button-close-modal |
N/A |
Verified |
| Selector |
Status |
Evidence |
| raceInformation |
Matches |
03+: data-testid=wizard-nav-set-session-information |
| ... (all 11) |
Matches |
Exact data-testid in 03,05,07,08 |
stepContainers (all Matches - #set-* IDs)
| Selector |
Status |
Evidence |
| raceInformation (#set-session-information) |
Matches |
03 |
| admins (#set-admins) |
Matches |
05 |
| timeLimit (#set-time-limit) |
Matches |
07 |
| cars (#set-cars) |
Matches |
08 |
| ... (all 11) |
Matches |
Dumps |
fields (Recommended: Add chakra- for stability)
| Selector |
Current |
Status |
Evidence |
Proposed |
Priority |
| textInput |
input.form-control, .chakra-input, ... |
Matches |
Chakra inputs in dumps |
.chakra-input, input[placeholder], input[type="text"] |
Recommended |
| ... (similar for others) |
Partial |
Chakra dominant |
Add chakra- prefixes |
Recommended |
|
steps (Key issues highlighted)
| Selector |
Current |
Status |
Evidence (Dump) |
Proposed |
Priority |
| sessionName |
#set-session-information .card-block .form-group:first-of-type input.form-control, ... |
Unconfirmed |
03: form-groups, chakra-input |
label:has-text("Session Name") ~ input.chakra-input |
Recommended |
| password |
Complex |
Unconfirmed |
03 |
label:has-text("Password") ~ input[type="password"], input[placeholder*="Password"] |
Recommended |
| adminList |
[data-list="admins"] |
No Match |
05: no data-list; #set-admins card |
#set-admins table.table.table-striped, #set-admins .card-block table |
Critical |
| practice |
input[id*="time-limit-slider"] |
Matches but risky |
07: time-limit-slider1764248520320 |
label:has-text("Practice") ~ div input[id*="time-limit-slider"] |
Recommended |
| qualify/race |
Similar |
Matches risky |
07 |
Label proximity |
Recommended |
| addCarButton |
a.btn:has-text("Add a Car") |
Matches |
08: a.btn.btn-sm t:"Add a Car 16 Available" |
a.btn:has-text("Add a Car") (handles dynamic) |
Verified |
| carList |
table.table.table-striped |
Matches |
08: many table.table.table-striped |
#set-cars table.table.table-striped |
Verified |
| ... (track similar) |
Matches |
08+ |
N/A |
Verified |
|
BLOCKED_SELECTORS (Optional: Chakra enhancements)
| Selector |
Status |
Proposed |
Priority |
| checkout |
Matches |
Add .chakra-button:has-text("Check Out") |
Optional |
| ... |
Matches |
Minor |
Optional |
BDD Scenarios for Verification
- GIVEN hosted page (01), THEN
hostedRacing.createRaceButton finds 1 button.
- GIVEN #set-admins (05), THEN
steps.adminList finds 1 table; addAdminButton finds 1.
- GIVEN time-limits (07), THEN
steps.practice finds 1 slider near "Practice" label.
- GIVEN cars (08), THEN
carList finds table; addCarButton:has-text("Add a Car") finds 1.
- GIVEN any step, THEN
wizard.nextButton:last-child enabled, finds 1.
Run via Playwright: expect(page.locator(selector)).toHaveCount(1) per scenario.
Docker E2E Impacts
No major changes; selectors stable. Minor fixture updates if sliders refined (update E2ETestBrowserLauncher.ts expectations). Test post-update.
Implementation Roadmap (for Code mode)
- Apply Critical/Recommended updates via apply_diff.
- Verify with browser_action on local iRacing mock/fixture.
- Add BDD tests in tests/.