e2e: name: 'OK' matches as a substring, so random test data can collide with the modal button #253

Closed
opened 2026-09-01 08:57:08 -05:00 by bermudalamb · 0 comments
Owner

Found while verifying merged main after #223 and #241. This is the real cause of at least part of the admin-save flakiness that #245 worked around by skipping a test, and that #241 attributed to parallel contention.

AdminInventory.confirmButton is:

this.confirmButton = page.getByRole('button', { name: 'OK' });

Playwright's name option matches case-insensitively, as a substring, unless exact: true is passed. So it matches any button whose accessible name merely contains "ok".

The actual failure from a full serial run on main:

Error: locator.click: Error: strict mode violation:
getByRole('button', { name: 'OK' }) resolved to 2 elements:
    1) aka getByRole('button', { name: 'Freed rmtiq9okg22k9e' })
    2) aka getByRole('button', { name: 'OK', exact: true })

A leftover "Freed …" toast from admin-reserved-items was still on screen, and the random suffix rmtiq9okg22k9e happens to contain ok. uniqueSuffix() produces base36, so roughly one suffix in a few hundred contains the sequence — which is exactly the profile of a test that fails every so often for no reason anyone can reproduce.

Note this is not contention: it reproduced with workers: 1, serially, on a fresh database. It needs only a leftover toast and an unlucky suffix, so it survives the #241 fix untouched. Three tests failed this way in one run and none in the next.

The fix is exact: true on that locator.

There is a wider version of the same exposure — 15 or so role locators use short names without exact, including 'All', 'Save', 'Close', 'Delete'. Only very short targets realistically collide with random base36, so 'OK' and 'All' are the ones that matter; the rest would need a collision in deliberately-chosen test data rather than a random suffix. I would rather fix the demonstrated one and the one other short target than change fifteen locators speculatively, since substring matching is load-bearing in some of them.

Found while verifying merged `main` after #223 and #241. This is the real cause of at least part of the admin-save flakiness that #245 worked around by skipping a test, and that #241 attributed to parallel contention. `AdminInventory.confirmButton` is: ```ts this.confirmButton = page.getByRole('button', { name: 'OK' }); ``` Playwright's `name` option matches **case-insensitively, as a substring**, unless `exact: true` is passed. So it matches any button whose accessible name merely contains "ok". The actual failure from a full serial run on `main`: ``` Error: locator.click: Error: strict mode violation: getByRole('button', { name: 'OK' }) resolved to 2 elements: 1) aka getByRole('button', { name: 'Freed rmtiq9okg22k9e' }) 2) aka getByRole('button', { name: 'OK', exact: true }) ``` A leftover "Freed …" toast from `admin-reserved-items` was still on screen, and the random suffix `rmtiq9okg22k9e` happens to contain `ok`. `uniqueSuffix()` produces base36, so roughly one suffix in a few hundred contains the sequence — which is exactly the profile of a test that fails every so often for no reason anyone can reproduce. Note this is **not** contention: it reproduced with `workers: 1`, serially, on a fresh database. It needs only a leftover toast and an unlucky suffix, so it survives the #241 fix untouched. Three tests failed this way in one run and none in the next. The fix is `exact: true` on that locator. There is a wider version of the same exposure — 15 or so role locators use short names without `exact`, including `'All'`, `'Save'`, `'Close'`, `'Delete'`. Only very short targets realistically collide with random base36, so `'OK'` and `'All'` are the ones that matter; the rest would need a collision in deliberately-chosen test data rather than a random suffix. I would rather fix the demonstrated one and the one other short target than change fifteen locators speculatively, since substring matching is load-bearing in some of them.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bermudalamb/redefined-designs#253