From 4dc7caa86b880d7b762a5df23f4ec736a548b502 Mon Sep 17 00:00:00 2001 From: Gareth Jones Date: Mon, 12 Aug 2024 04:13:52 +1200 Subject: [PATCH] feat: add support for flat config (#923) --- .eslint-doc-generatorrc.js | 7 +++ README.md | 90 +++++++++++++++++++++++++++++++++ lib/configs/index.ts | 2 +- lib/index.ts | 41 ++++++++++++++- tests/index.test.ts | 5 ++ tools/generate-configs/index.ts | 5 +- 6 files changed, 145 insertions(+), 5 deletions(-) diff --git a/.eslint-doc-generatorrc.js b/.eslint-doc-generatorrc.js index bc908b2a..00e04ede 100644 --- a/.eslint-doc-generatorrc.js +++ b/.eslint-doc-generatorrc.js @@ -3,6 +3,13 @@ const prettierConfig = require('./.prettierrc.js'); /** @type {import('eslint-doc-generator').GenerateOptions} */ const config = { + ignoreConfig: [ + 'flat/angular', + 'flat/dom', + 'flat/marko', + 'flat/react', + 'flat/vue', + ], postprocess: (content) => prettier.format(content, { ...prettierConfig, parser: 'markdown' }), }; diff --git a/README.md b/README.md index 2199abdd..62ca1b11 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,16 @@ Another approach for customizing ESLint config by paths is through [ESLint Casca ## 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. @@ -140,6 +150,22 @@ module.exports = { }; ``` +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. @@ -153,6 +179,22 @@ module.exports = { }; ``` +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. @@ -166,6 +208,22 @@ module.exports = { }; ``` +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. @@ -179,6 +237,22 @@ module.exports = { }; ``` +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'], + }, +]; +``` + ### Marko Enforces recommended rules for Marko Testing Library. @@ -192,6 +266,22 @@ module.exports = { }; ``` +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/"` diff --git a/lib/configs/index.ts b/lib/configs/index.ts index c36314e8..15bcc709 100644 --- a/lib/configs/index.ts +++ b/lib/configs/index.ts @@ -8,7 +8,7 @@ import { SupportedTestingFramework, } from '../utils'; -export type LinterConfigRules = Record; +export type LinterConfigRules = Pick, 'rules'>; const configsDir = __dirname; diff --git a/lib/index.ts b/lib/index.ts index c270f91d..bfcdfb12 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,7 +1,44 @@ +import type { TSESLint } from '@typescript-eslint/utils'; + import configs from './configs'; import rules from './rules'; +import { SupportedTestingFramework } from './utils'; + +// we can't natively import package.json as tsc will copy it into dist/ +const { + name: packageName, + version: packageVersion, + // eslint-disable-next-line @typescript-eslint/no-var-requires +} = require('../package.json') as { name: string; version: string }; -export = { - configs, +const plugin = { + meta: { + name: packageName, + version: packageVersion, + }, + // ugly cast for now to keep TypeScript happy since + // we don't have types for flat config yet + configs: {} as Record< + SupportedTestingFramework | `flat/${SupportedTestingFramework}`, + Pick, 'rules'> + >, rules, }; + +plugin.configs = { + ...configs, + ...(Object.fromEntries( + Object.entries(configs).map(([framework, config]) => [ + `flat/${framework}`, + { + plugins: { 'testing-library': plugin }, + rules: config.rules, + }, + ]) + ) as Record< + `flat/${SupportedTestingFramework}`, + Pick, 'rules'> & { plugins: unknown } + >), +}; + +export = plugin; diff --git a/tests/index.test.ts b/tests/index.test.ts index 6788a479..68cfb521 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -52,6 +52,11 @@ it('should export configs that refer to actual rules', () => { 'react', 'vue', 'marko', + 'flat/dom', + 'flat/angular', + 'flat/react', + 'flat/vue', + 'flat/marko', ]); const allConfigRules = Object.values(allConfigs) .map((config) => Object.keys(config.rules)) diff --git a/tools/generate-configs/index.ts b/tools/generate-configs/index.ts index 87c773c2..ef5f1abc 100644 --- a/tools/generate-configs/index.ts +++ b/tools/generate-configs/index.ts @@ -1,4 +1,5 @@ -import { type LinterConfigRules } from '../../lib/configs'; +import { type TSESLint } from '@typescript-eslint/utils'; + import rules from '../../lib/rules'; import { SUPPORTED_TESTING_FRAMEWORKS, @@ -11,7 +12,7 @@ const RULE_NAME_PREFIX = 'testing-library/'; const getRecommendedRulesForTestingFramework = ( framework: SupportedTestingFramework -): LinterConfigRules => +): Record => Object.entries(rules) .filter( ([