Flaky-UI Dojo
Five widgets engineered to break naive tests: random latency, a spinner that lies, DOM nodes that get replaced under your locator, debounced results, and an optimistic save that can roll back. If your spec needs waitForTimeout, the dojo has already won.
Trap 1 · The lying spinner
The spinner can disappear before the rows render. Waiting for spinner-gone is not the same as waiting for data.
Trap 2 · Detach and re-attach
Every click destroys and rebuilds this card after a delay. A stored element handle goes stale; a locator re-resolves.
Trap 3 · Debounced search
Results update 500ms after the last keystroke. Assert the result count, not the keystroke.
8 results
Trap 4 · Optimistic rollback
The toggle flips instantly, then the fake server answers 700-1400ms later, and one time in four it says no and flips it back.
Trap 5 · The late-enabled button
Ticking the box starts a background check; Submit enables 300-1500ms later. Click too early and nothing happens.
Drills
- Load orders and assert exactly 4 rows appear, without ever waiting on the spinner. Run it 10 times with stable mode off; it must pass 10/10.
- Click the counter 5 times and assert it reads 5. The naive version with a stored
elementHandlethrows; explain why yours does not. - Type
puneand assert the count reaches 1, then clear and assert it returns to 8, using only web-first assertions. - Turn the optimistic toggle on and write an assertion that passes only when the save truly succeeded, and a second spec that handles the rollback path with
expect().toPass(). - Accept the terms and submit, no
waitForTimeoutallowed: Playwright's actionability checks should carry the wait for you.