eslint-plugin-testing-library
Version:
ESLint plugin to follow best practices and anticipate common mistakes when writing tests with Testing Library
355 lines (274 loc) • 107 kB
Markdown
<div align="center">
<a href="https://eslint.org/">
<img width="150" height="150" src="https://raw.githubusercontent.com/eslint/eslint/main/docs/src/static/favicon.png">
</a>
<a href="https://testing-library.com/">
<img width="150" height="150" src="https://raw.githubusercontent.com/testing-library/dom-testing-library/master/other/octopus.png">
</a>
<h1>eslint-plugin-testing-library</h1>
<p>ESLint plugin to follow best practices and anticipate common mistakes when writing tests with Testing Library</p>
</div>
---
[![Package version][version-badge]][version-url]
[![eslint-remote-tester][eslint-remote-tester-badge]][eslint-remote-tester-workflow]
[![eslint-plugin-testing-library][package-health-badge]][package-health-url]
[](https://codecov.io/gh/testing-library/eslint-plugin-testing-library)
[![MIT License][license-badge]][license-url]
<br />
[](https://github.com/semantic-release/semantic-release)
[![PRs Welcome][pr-badge]][pr-url]
[![All Contributors][all-contributors-badge]](#contributors-)
## Prerequisites
To use this plugin, you must have [Node.js](https://nodejs.org/en/) (`^18.18.0`, `^20.9.0`, or `>=21.1.0`) installed.
## Installation
You'll first need to [install ESLint](https://eslint.org/docs/latest/use/getting-started).
Next, install `eslint-plugin-testing-library`:
```shell
$ pnpm add --save-dev eslint-plugin-testing-library
# or
$ npm install --save-dev eslint-plugin-testing-library
# or
$ yarn add --dev eslint-plugin-testing-library
```
**Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `eslint-plugin-testing-library` globally.
## Migrating
You can find detailed guides for migrating `eslint-plugin-testing-library` in the [migration guide docs](docs/migration-guides):
- [Migration guide for v4](docs/migration-guides/v4.md)
- [Migration guide for v5](docs/migration-guides/v5.md)
- [Migration guide for v6](docs/migration-guides/v6.md)
- [Migration guide for v7](docs/migration-guides/v7.md)
## Usage
Add `testing-library` to the plugins section of your `.eslintrc.js` configuration file. You can omit the `eslint-plugin-` prefix:
```js
module.exports = {
plugins: ['testing-library'],
};
```
Then configure the rules you want to use within `rules` property of your `.eslintrc`:
```js
module.exports = {
rules: {
'testing-library/await-async-queries': 'error',
'testing-library/no-await-sync-queries': 'error',
'testing-library/no-debugging-utils': 'warn',
'testing-library/no-dom-import': 'off',
},
};
```
### Run the plugin only against test files
With the default setup mentioned before, `eslint-plugin-testing-library` will be run against your whole codebase. If you want to run this plugin only against your tests files, you have the following options:
#### ESLint `overrides`
One way of restricting ESLint config by file patterns is by using [ESLint `overrides`](https://eslint.org/docs/user-guide/configuring/configuration-files#configuration-based-on-glob-patterns).
Assuming you are using the same pattern for your test files as [Jest by default](https://jestjs.io/docs/configuration#testmatch-arraystring), the following config would run `eslint-plugin-testing-library` only against your test files:
```js
// .eslintrc.js
module.exports = {
// 1) Here we have our usual config which applies to the whole project, so we don't put testing-library preset here.
extends: ['airbnb', 'plugin:prettier/recommended'],
// 2) We load other plugins than eslint-plugin-testing-library globally if we want to.
plugins: ['react-hooks'],
overrides: [
{
// 3) Now we enable eslint-plugin-testing-library rules or preset only for matching testing files!
files: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
extends: ['plugin:testing-library/react'],
},
],
};
```
#### ESLint Cascading and Hierarchy
Another approach for customizing ESLint config by paths is through [ESLint Cascading and Hierarchy](https://eslint.org/docs/user-guide/configuring/configuration-files#cascading-and-hierarchy). This is useful if all your tests are placed under the same folder, so you can place there another `.eslintrc` where you enable `eslint-plugin-testing-library` for applying it only to the files under such folder, rather than enabling it on your global `.eslintrc` which would apply to your whole project.
## Shareable configurations
> [!NOTE]
>
> `eslint.config.js` compatible versions of configs are available prefixed with
> `flat/`, though most of the plugin documentation still currently uses
> `.eslintrc` syntax.
>
> Refer to the
> [ESLint documentation on the new configuration file format](https://eslint.org/docs/latest/use/configure/configuration-files-new)
> for more.
This plugin exports several recommended configurations that enforce good practices for specific Testing Library packages.
You can find more info about enabled rules in the [Supported Rules section](#supported-rules), under the `Configurations` column.
Since each one of these configurations is aimed at a particular Testing Library package, they are not extendable between them, so you should use only one of them at once per `.eslintrc` file. For example, if you want to enable recommended configuration for React, you don't need to combine it somehow with DOM one:
```js
// ❌ Don't do this
module.exports = {
extends: ['plugin:testing-library/dom', 'plugin:testing-library/react'],
};
```
```js
// ✅ Just do this instead
module.exports = {
extends: ['plugin:testing-library/react'],
};
```
### DOM Testing Library
Enforces recommended rules for DOM Testing Library.
To enable this configuration use the `extends` property in your
`.eslintrc.js` config file:
```js
module.exports = {
extends: ['plugin:testing-library/dom'],
};
```
To enable this configuration with `eslint.config.js`, use
`testingLibrary.configs['flat/dom']`:
```js
const testingLibrary = require('eslint-plugin-testing-library');
module.exports = [
{
files: [
/* glob matching your test files */
],
...testingLibrary.configs['flat/dom'],
},
];
```
### Angular
Enforces recommended rules for Angular Testing Library.
To enable this configuration use the `extends` property in your
`.eslintrc.js` config file:
```js
module.exports = {
extends: ['plugin:testing-library/angular'],
};
```
To enable this configuration with `eslint.config.js`, use
`testingLibrary.configs['flat/angular']`:
```js
const testingLibrary = require('eslint-plugin-testing-library');
module.exports = [
{
files: [
/* glob matching your test files */
],
...testingLibrary.configs['flat/angular'],
},
];
```
### React
Enforces recommended rules for React Testing Library.
To enable this configuration use the `extends` property in your
`.eslintrc.js` config file:
```js
module.exports = {
extends: ['plugin:testing-library/react'],
};
```
To enable this configuration with `eslint.config.js`, use
`testingLibrary.configs['flat/react']`:
```js
const testingLibrary = require('eslint-plugin-testing-library');
module.exports = [
{
files: [
/* glob matching your test files */
],
...testingLibrary.configs['flat/react'],
},
];
```
### Vue
Enforces recommended rules for Vue Testing Library.
To enable this configuration use the `extends` property in your
`.eslintrc.js` config file:
```js
module.exports = {
extends: ['plugin:testing-library/vue'],
};
```
To enable this configuration with `eslint.config.js`, use
`testingLibrary.configs['flat/vue']`:
```js
const testingLibrary = require('eslint-plugin-testing-library');
module.exports = [
{
files: [
/* glob matching your test files */
],
...testingLibrary.configs['flat/vue'],
},
];
```
### Svelte
Enforces recommended rules for Svelte Testing Library.
To enable this configuration use the `extends` property in your
`.eslintrc.js` config file:
```js
module.exports = {
extends: ['plugin:testing-library/svelte'],
};
```
To enable this configuration with `eslint.config.js`, use
`testingLibrary.configs['flat/svelte']`:
```js
const testingLibrary = require('eslint-plugin-testing-library');
module.exports = [
{
files: [
/* glob matching your test files */
],
...testingLibrary.configs['flat/svelte'],
},
];
```
### Marko
Enforces recommended rules for Marko Testing Library.
To enable this configuration use the `extends` property in your
`.eslintrc.js` config file:
```js
module.exports = {
extends: ['plugin:testing-library/marko'],
};
```
To enable this configuration with `eslint.config.js`, use
`testingLibrary.configs['flat/marko']`:
```js
const testingLibrary = require('eslint-plugin-testing-library');
module.exports = [
{
files: [
/* glob matching your test files */
],
...testingLibrary.configs['flat/marko'],
},
];
```
## Supported Rules
> Remember that all rules from this plugin are prefixed by `"testing-library/"`
<!-- begin auto-generated rules list -->
💼 Configurations enabled in.\
⚠️ Configurations set to warn in.\
 Set in the `angular` configuration.\
 Set in the `dom` configuration.\
 Set in the `marko` configuration.\
 Set in the `react` configuration.\
 Set in the `svelte` configuration.\
 Set in the `vue` configuration.\
🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).
| Name | Description | 💼 | ⚠️ | 🔧 |
| :------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-- |
| [await-async-events](docs/rules/await-async-events.md) | Enforce promises from async event methods are handled |       | | 🔧 |
| [await-async-queries](docs/rules/await-async-queries.md) | Enforce promises from async queries to be handled |       | | 🔧 |
| [await-async-utils](docs/rules/await-async-utils.md) | Enforce promises from async utils to be awaited properly |       | | 🔧 |
| [consistent-data-testid](docs/rules/consistent-data-testid.md) | Ensures consistent usage of `data-testid` | | | |
| [no-await-sync-events](docs/rules/no-await-sync-events.md) | Disallow unnecessary `await` for sync events |    | | |
| [no-await-sync-queries](docs/rules/no-await-sync-queries.md) | Disallow unnecessary `await` for sync queries |       | | 🔧 |
| [no-container](docs/rules/no-container.md) | Disallow the use of `container` methods |      | | |
| [no-debugging-utils](docs/rules/no-debugging-utils.md) | Disallow the use of debugging utilities like `debug` | |      | |
| [no-dom-import](docs/rules/no-dom-import.md) | Disallow importing from DOM Testing Library |      | | 🔧 |
| [no-global-regexp-flag-in-query](docs/rules/no-global-regexp-flag-in-query.md) | Disallow the use of the global RegExp flag (/g) in queries |       | | 🔧 |
| [no-manual-cleanup](docs/rules/no-manual-cleanup.md) | Disallow the use of `cleanup` |    | | |
| [no-node-access](docs/rules/no-node-access.md) | Disallow direct Node access |       | | |
| [no-promise-in-fire-event](docs/rules/no-promise-in-fire-event.md) | Disallow the use of promises passed to a `fireEvent` method |       | | |
| [no-render-in-lifecycle](docs/rules/no-render-in-lifecycle.md) | Disallow the use of `render` in testing frameworks setup functions |      | | |
| [no-test-id-queries](docs/rules/no-test-id-queries.md) | Ensure no `data-testid` queries are used | | | |
| [no-unnecessary-act](docs/rules/no-unnecessary-act.md) | Disallow wrapping Testing Library utils or empty callbacks in `act` |   | | |
| [no-wait-for-multiple-assertions](docs/rules/no-wait-for-multiple-assertions.md) | Disallow the use of multiple `expect` calls inside `waitFor` |       | | 🔧 |
| [no-wait-for-side-effects](docs/rules/no-wait-for-side-effects.md) | Disallow the use of side effects in `waitFor` |       | | 🔧 |
| [no-wait-for-snapshot](docs/rules/no-wait-for-snapshot.md) | Ensures no snapshot is generated inside of a `waitFor` call |       | | |
| [prefer-explicit-assert](docs/rules/prefer-explicit-assert.md) | Suggest using explicit assertions rather than standalone queries | | | |
| [prefer-find-by](docs/rules/prefer-find-by.md) | Suggest using `find(All)By*` query instead of `waitFor` + `get(All)By*` to wait for elements |       | | 🔧 |
| [prefer-implicit-assert](docs/rules/prefer-implicit-assert.md) | Suggest using implicit assertions for getBy* & findBy* queries | | | |
| [prefer-presence-queries](docs/rules/prefer-presence-queries.md) | Ensure appropriate `get*`/`query*` queries are used with their respective matchers |      ![badge-vue](https://img.shields.io/badge/-Vue-black?style=flat-square&logo=vue.js&logoC