Side Effect In A waitFor Callback
ID |
javascript.side_effect_in_wait_for |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
async, reliability, testing |
Description
Reports a fireEvent, userEvent or render call inside a waitFor callback.
waitFor polls its callback — on a timer and again on every DOM mutation — until it stops throwing or the timeout expires. The callback is therefore run an unknown number of times, and it must only observe.
Queries are deliberately not reported: screen.getByText(…) inside the callback is what waitFor is for. Only the calls that change the page are a defect.
Rationale
// Bad
await waitFor(() => {
fireEvent.click(button); // dispatched once per poll
expect(counter).toHaveTextContent('1');
});
-
The effect is applied on every attempt, so ten clicks are dispatched where the test meant one and the assertion is measured against a page the test never described.
-
The effect usually causes the very mutation that schedules the next poll, so the callback drives its own re-entry.
-
The test then either times out or passes for a reason unrelated to the behaviour under test, and both outcomes change with machine speed.
-
Nothing in the failure message mentions the extra dispatches, so the usual response is to raise the timeout, which makes it slower and no more correct.