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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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