# Locators (Humand E2E)

Use accessibility-first locators by default. Treat `data-testid` as fallback, not first choice.

## Priority order

1. `getByRole`
2. `getByLabel`
3. `getByText`
4. `getByPlaceholder` / `getByTitle` / `getByAltText`
5. `getByTestId` (fallback)
6. CSS/XPath only when nothing else is viable

## Humand rules

- UI language is English (`locale: 'en'` in `playwright.config.ts`, `i18nextLng` set to `en` in auth setup).
- Prefer resilient regex for text that may vary slightly:
  - `page.getByRole('button', { name: /create competency/i })`
- Avoid class-based selectors for MUI-generated markup.
- Keep raw locator details inside page objects, not in test files.
- Verify the actual accessibility tree before assuming `getByRole` works for tabs or custom controls.
- Scope drawer and slide-in inputs under `[role="presentation"]` when the page contains duplicate fields.
- If the UI renders raw i18n keys, prefer a regex that matches both the key and the translated label.

## Good examples

```ts
page.getByRole('button', { name: /create competency/i });
page.getByRole('button', { name: /save/i });
page.getByPlaceholder('Name');
page.getByText('Competencies', { exact: true }).first();
```

## `data-testid` fallback

Use when:

- the element has no stable accessible role/name
- translated labels vary too much
- custom controls are hard to target semantically

Naming convention:

`{module}-{component}-{element}`

Examples:

- `goals-cycle-new-button`
- `auth-login-submit-button`

## Anti-patterns

- `page.locator('.MuiButton-root.some-random-class')`
- brittle nth-child selectors in tests
- hardcoded selector duplication across tests and page objects
- guessing selectors for collapsed or icon-only regions without MCP inspection
