Skip to content

no-wait-for-side-effects: side effects not detected via userEvent.setup() instances and when wrapped in void #1370

Description

@kinaz-xxr

Have you read the Troubleshooting section?

Yes

Plugin version

v7.16.2

ESLint version

v9.39.2

Node.js version

v22.20.0

Bug description

no-wait-for-side-effects misses side effects inside waitFor in two
independent cases:

1. Aliased userEvent (userEvent.setup() instances). The rule only
recognizes side effects spelled userEvent.* (or the import alias). With the
user-event v14 recommended pattern — const user = userEvent.setup() and
calling methods on the instance — nothing is reported, so the rule is silent
for the most common modern usage. Cause: side effects are resolved by
identifier name via isUserEventUtil (node.name === userEventName), so the
identifier user never matches. The plugin already has an alias-aware helper
for exactly this case — isUserEventMethod with userEventSetupVars tracking,
used by await-async-events and no-await-sync-events — but this rule doesn't
use it. Same class of gap previously fixed for other rules in #812 and #758.

2. void-wrapped side effects. A statement like
void userEvent.click(el) is not reported even with the plain userEvent
name — this also hides void fireEvent.*(...) and void render(...). Cause:
getPropertyIdentifierNode unwraps member/call/chain/await expressions but has
no UnaryExpression case, so void x returns null and the statement is
skipped. await unwrapping was added for this rule in #1008; void needs the
same treatment.

The two combine: void user.click(el) is missed for both reasons.

Steps to reproduce

  1. Enable testing-library/no-wait-for-side-effects (config below).
  2. Lint this spec:
import { waitFor, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

const el = document.body;

test('direct userEvent — reported', async () => {
  await waitFor(async () => {
    await userEvent.click(el); // ✅ reported
  });
});

test('fireEvent — reported', async () => {
  await waitFor(() => {
    fireEvent.click(el); // ✅ reported
  });
});

test('bug 1: setup() instance — NOT reported', async () => {
  const user = userEvent.setup();
  await waitFor(async () => {
    await user.click(el); // ❌ silent (alias not matched)
  });
});

test('bug 2: void-wrapped, real userEvent name — NOT reported', async () => {
  await waitFor(() => {
    void userEvent.click(el); // ❌ silent (void not unwrapped)
  });
});

test('bugs 1+2 combined — NOT reported', async () => {
  const user = userEvent.setup();
  await waitFor(() => {
    void user.click(el); // ❌ silent
  });
});
  1. Only the first two tests are flagged. The user.click and
    void userEvent.click statements pass silently, even though they are the
    same side effects.

Error output/screenshots

Actual output (fresh project, only eslint + this plugin installed):

repro.spec.js
   8:5  error  Avoid using side effects within `waitFor` callback  testing-library/no-wait-for-side-effects
  14:5  error  Avoid using side effects within `waitFor` callback  testing-library/no-wait-for-side-effects

✖ 2 problems (2 errors, 0 warnings)

Expected: the same noSideEffectsWaitFor error on the three unreported
statements (await user.click(el), void userEvent.click(el),
void user.click(el)).

callback body reported?
await waitFor(async () => { await userEvent.click(el) }) ✅ error
await waitFor(() => { fireEvent.click(el) }) ✅ error
await waitFor(async () => { await user.click(el) }) ❌ silent
await waitFor(() => { void userEvent.click(el) }) ❌ silent
await waitFor(() => { void user.click(el) }) ❌ silent

### ESLint configuration


```js
// eslint.config.js
import testingLibrary from 'eslint-plugin-testing-library';

export default [
  {
    files: ['**/*.spec.js'],
    plugins: { 'testing-library': testingLibrary },
    rules: {
      'testing-library/no-wait-for-side-effects': 'error',
    },
  },
];

Rule(s) affected

testing-library/no-wait-for-side-effects, there might be more

Anything else?

No response

Do you want to submit a pull request to fix this bug?

Yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriagePending to be triaged by a maintainer

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions