Skip to content

prefer-presence-queries autofix leaves queryBy* in destructure while rewriting call site to getBy*, producing a ReferenceError #1359

Description

@OzTK

Describe the bug

The prefer-presence-queries autofix (introduced in v7.4.0, #1020) only rewrites the Identifier at the call site inside expect(), but does not update the corresponding ObjectPattern destructure binding. This produces syntactically valid but broken code — getByRole is called but was never declared, causing a ReferenceError at runtime.

Minimal reproducible example

// broken.test.js — BEFORE eslint --fix
it('example', () => {
  const { queryByRole } = render(something());
  expect(queryByRole('alert')).toBeInTheDocument(); // ← fires prefer-presence-queries
});
// broken.test.js — AFTER eslint --fix
it('example', () => {
  const { queryByRole } = render(something()); // ← destructure untouched, now unused
  expect(getByRole('alert')).toBeInTheDocument(); // ← getByRole is NOT IN SCOPE → ReferenceError
});

Steps to reproduce

mkdir repro && cd repro
npm init -y
npm install eslint eslint-plugin-testing-library
// eslint.config.mjs
import testingLibrary from 'eslint-plugin-testing-library';
export default [{
  files: ['**/*.test.js'],
  plugins: { 'testing-library': testingLibrary },
  rules: { 'testing-library/prefer-presence-queries': 'error' },
}];
// broken.test.js
it('example', () => {
  const { queryByRole } = render(something());
  expect(queryByRole('alert')).toBeInTheDocument();
});
npx eslint --fix broken.test.js
cat broken.test.js

Output after fix:

it('example', () => {
  const { queryByRole } = render(something()); // ← not updated
  expect(getByRole('alert')).toBeInTheDocument(); // ← not in scope → ReferenceError at runtime
});

Expected behavior

The fix should update both the destructure binding and the call site:

it('example', () => {
  const { getByRole } = render(something()); // ← updated
  expect(getByRole('alert')).toBeInTheDocument(); // ← correct
});

Versions

Root cause

The fixer targets the Identifier node matched by the "CallExpression Identifier" selector — the identifier at the call site inside expect(). It does not walk up the scope to find and update the ObjectPattern in the VariableDeclarator that originally destructured the same query from the render result.

Related

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions