ESLint plugin to follow best practices and anticipate common mistakes when writing tests with Testing Library
npx @tessl/cli install tessl/npm-eslint-plugin-testing-library@7.6.0ESLint Plugin Testing Library is a comprehensive ESLint plugin that provides best practices enforcement and common mistake prevention for Testing Library usage across multiple JavaScript testing frameworks including React, Vue, Angular, Svelte, and Marko.
npm install --save-dev eslint-plugin-testing-library// CommonJS (legacy configuration)
module.exports = {
plugins: ['testing-library'],
extends: ['plugin:testing-library/react'], // or dom, angular, vue, svelte, marko
rules: {
'testing-library/await-async-queries': 'error',
'testing-library/no-debugging-utils': 'warn'
}
};For ESLint v9+ flat config:
import testingLibrary from 'eslint-plugin-testing-library';
export default [
{
plugins: {
'testing-library': testingLibrary
},
rules: {
'testing-library/await-async-queries': 'error',
'testing-library/no-debugging-utils': 'warn'
}
},
// Or use preset configurations
testingLibrary.configs['flat/react']
];// .eslintrc.js (legacy configuration)
module.exports = {
extends: ['plugin:testing-library/react'],
rules: {
// Override specific rules
'testing-library/no-debugging-utils': 'warn',
'testing-library/prefer-screen-queries': 'error'
}
};For framework-specific usage:
// React Testing Library
extends: ['plugin:testing-library/react']
// Vue Testing Library
extends: ['plugin:testing-library/vue']
// Angular Testing Library
extends: ['plugin:testing-library/angular']
// DOM Testing Library
extends: ['plugin:testing-library/dom']
// Svelte Testing Library
extends: ['plugin:testing-library/svelte']
// Marko Testing Library
extends: ['plugin:testing-library/marko']Core plugin object providing ESLint integration with metadata, rules, and framework-specific configurations.
interface Plugin {
meta: {
name: string;
version: string;
};
configs: {
angular: Linter.LegacyConfig;
dom: Linter.LegacyConfig;
marko: Linter.LegacyConfig;
react: Linter.LegacyConfig;
svelte: Linter.LegacyConfig;
vue: Linter.LegacyConfig;
'flat/angular': Linter.FlatConfig;
'flat/dom': Linter.FlatConfig;
'flat/marko': Linter.FlatConfig;
'flat/react': Linter.FlatConfig;
'flat/svelte': Linter.FlatConfig;
'flat/vue': Linter.FlatConfig;
};
rules: {
[key: string]: Rule.RuleModule;
};
}28 comprehensive ESLint rules that enforce Testing Library best practices across async/await patterns, query selection, DOM access, testing patterns, user interactions, assertions, and naming conventions.
interface RuleModule {
meta: {
type: 'problem' | 'suggestion' | 'layout';
docs: {
description: string;
category: string;
recommended: boolean;
url: string;
};
fixable?: 'code' | 'whitespace';
schema: JSONSchema4 | JSONSchema4[];
};
create: (context: RuleContext) => RuleListener;
}Rule Categories:
await-async-queries, await-async-utils, no-await-sync-queries, etc.prefer-find-by, prefer-screen-queries, no-test-id-queries, etc.no-container, no-node-access, no-dom-importno-debugging-utils, no-manual-cleanup, no-unnecessary-act, etc.prefer-user-event, no-promise-in-fire-eventprefer-explicit-assert, prefer-implicit-assertconsistent-data-testid, render-result-naming-conventionimport type { Linter, Rule } from 'eslint';
// Main plugin export structure
interface Plugin {
meta: {
name: string;
version: string;
};
configs: {
angular: Linter.LegacyConfig;
dom: Linter.LegacyConfig;
marko: Linter.LegacyConfig;
react: Linter.LegacyConfig;
svelte: Linter.LegacyConfig;
vue: Linter.LegacyConfig;
'flat/angular': Linter.FlatConfig;
'flat/dom': Linter.FlatConfig;
'flat/marko': Linter.FlatConfig;
'flat/react': Linter.FlatConfig;
'flat/svelte': Linter.FlatConfig;
'flat/vue': Linter.FlatConfig;
};
rules: {
[key: string]: Rule.RuleModule;
};
}
// Supported testing frameworks
type SupportedTestingFramework = 'dom' | 'angular' | 'react' | 'vue' | 'svelte' | 'marko';