testing-library / testing-library/eslint-plugin-testing-library
prefer-presence-queries autofix leaves queryBy* in destructure while rewriting call site to getBy*, producing a ReferenceError
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1.1k
- Forks
- 168
- Avg merge
- 15h 44m
- Merged PRs (30d)
- 14
Description
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
eslint-plugin-testing-library: 7.16.2 (first appeared in 7.4.0 when autofix was added via #1020)eslint: 9.x- Node: 22.x
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
- #916 — the issue that requested autofixability (the resulting fix is incomplete)
- #1020 — the PR that implemented the autofix
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run the minimal reproduction with eslint --fix to observe the call-site rewrite. Inspect the prefer-presence-queries autofix, especially the “CallExpression Identifier” selector and the related ObjectPattern in the VariableDeclarator; done means both the destructure binding and call site use getByRole without producing a ReferenceError.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- eslint, javascript, typescript
- Domain
- testing-qa, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100