## TL;DR

Never select by dynamic IDs. Use stable attributes (`data-testid`), partial-match selectors (`[id^='prefix-']`), or role locators, and push back on the app to add test hooks.

## Error

```text
(Not an error; a selector strategy. Symptom: selectors with IDs like `id="ember123"` break every run.)
```

## Steps

1. Confirm the ID is dynamic: reload and compare. Expected: it changes.
2. Replace with a stable attribute: ask for `data-testid` or use an existing stable attribute. Expected: the durable fix.
3. If stuck, use prefix matching: `[id^='user-form-']`. Expected: works but fragile; document it.
4. Prefer role or text locators that ignore the ID entirely. Expected: the robust alternative.
5. Lint against bare dynamic-ID selectors. Expected: no new ones.

## When to use

- Framework-generated IDs (Ember, auto-increment).
- Any ID that changes between runs.

## When not to use

- Stable IDs (use them directly).
- You control the app (add test IDs instead).

## Tool compatibility

- Any framework; attribute selectors everywhere.

## Variant phrasings

### Dynamic ID selector workaround

The tactical fix; stable attributes are the strategy.

### Ember generated ID testing

The classic case; test IDs are the answer.

## Why it happens

Frameworks generate IDs for internal bookkeeping. They are explicitly unstable across renders.

## Edge cases

- Prefix matching breaks when the prefix scheme changes; treat as tech debt.
- Some dynamic IDs embed the record ID, which is actually useful; extract it deliberately.
- ARIA attributes are stable alternatives when test IDs are unavailable.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_kxg6DSbNgAZTAacqSRPSmg
