locator-strategist·codegen·active

Locator Strategist

Picks the most stable selector for a target element — role-based first, label-based next, test-id last. Avoids brittle CSS class chains.

EVANtrigger · agent
Locator Strategist
Picks the most stable selector for any target element, applying a strict priority hierarchy that minimizes test fragility.
When this skill fires
·Page Object Generator requests a locator for a discovered element
·An engineer asks EVAN to "find a stable selector" for a manually-identified element
·Locator Healer needs a replacement after a CI failure
Priority order (strict)
1. Role-basedgetByRole('button', { name: 'Submit' })
2. Label-basedgetByLabel('Email'), getByPlaceholder('search…')
3. Test IDgetByTestId('submit-payment')
4. Text contentgetByText('Sign in', { exact: true })
5. CSS selector — only if the element has a stable, semantic class
6. XPath — never. EVAN will refuse and ask for a test ID instead.
The hierarchy reflects how brittle each strategy is when the codebase changes. Roles survive refactors, classes don't.
Why role-based wins
A role-based locator works as long as the element remains accessible. It survives:
·CSS class renames
·DOM structure changes
·Component library upgrades
·Visual redesigns
It only breaks when the element's semantic role changes — which is exactly when the testshould fail because user behavior has changed.
Test ID hygiene
When EVAN falls back to test IDs, it follows a strict naming convention to keep them auditable:
·Lowercase, hyphenated
·Scope-prefixed: checkout/submit, not just submit
·Stable across builds (no hashes, no auto-generated suffixes)
Disambiguation
When multiple elements match a locator (three Submit buttons on the page), EVAN does not chain .nth(0). Instead, it widens the locator with semantic context: page.getByRole('form', { name: 'Login' }).getByRole('button', { name: 'Submit' }).
.nth() chains are a code smell. They imply the test is coupled to render order, which is exactly the kind of coupling that breaks on refactor.
What it produces
A single Locator expression and a one-line rationale comment explaining why this strategy was chosen over the next-best option. The rationale lives in the page object so future engineers can see the reasoning.