diff --git a/README.md b/README.md
index 80790dceb..2a5a5cecb 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ yarn add --dev eslint eslint-plugin-jest
**Note:** If you installed ESLint globally then you must also install
`eslint-plugin-jest` globally.
-## Usage
+## Usage (legacy: `.eslintrc*`)
Add `jest` to the plugins section of your `.eslintrc` configuration file. You
can omit the `eslint-plugin-` prefix:
@@ -59,7 +59,7 @@ doing:
This is included in all configs shared by this plugin, so can be omitted if
extending them.
-#### Aliased Jest globals
+### Aliased Jest globals
You can tell this plugin about any global Jests you have aliased using the
`globalAliases` setting:
@@ -143,7 +143,64 @@ module.exports = {
};
```
-## Shareable configurations
+## Usage (new: `eslint.config.js`)
+
+From [`v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), eslint
+announced a new config system. In the new system, `.eslintrc*` is no longer
+used. `eslint.config.js` would be the default config file name.
+
+And from [`v8.23.0`](https://github.com/eslint/eslint/releases/tag/v8.23.0),
+eslint CLI starts to look up `eslint.config.js`. **So, if your eslint is
+`>=8.23.0`, you're 100% ready to use the new config system.**
+
+You might want to check out the official blog posts,
+
+-
+-
+-
+
+and the
+[official docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new).
+
+The default export of `eslint-plugin-jest` is a plugin object.
+
+```js
+import jest from 'eslint-plugin-jest';
+import jestGlobals from 'eslint-plugin-jest/globals';
+
+export default [
+ {
+ // A config for source code (non-test files)
+ files: ['**/*.test.{js,jsx}'],
+ // ...
+ },
+ // --- snip ---
+ {
+ // The config in case you use jest snapshot test
+ files: ['**/*.snap'],
+ plugins: {
+ jest,
+ },
+ processor: 'jest/.snap',
+ },
+ {
+ // A config for test files (non-source-code)
+ files: ['**/*.test.{js,jsx}'],
+ languageOptions: {
+ globals: jestGlobals,
+ },
+ plugins: {
+ jest,
+ },
+ rules: {
+ // rules you want
+ 'jest/better-regex': 'warn',
+ },
+ },
+];
+```
+
+## Shareable configurations (legacy: `.eslintrc*`)
### Recommended
@@ -193,6 +250,39 @@ While the `recommended` and `style` configurations only change in major versions
the `all` configuration may change in any release and is thus unsuited for
installations requiring long-term consistency.
+## Shareable configurations (new: `eslint.config.js`)
+
+If you use the new config system (`eslint.config.js`), there're 3 shareable
+configs.
+
+- `eslint-plugin-jest/all`
+- `eslint-plugin-jest/recommended`
+- `eslint-plugin-jest/style`
+
+**Note**: Shareable configs will enable the
+[`languageOptions.globals`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuration-objects).
+
+In the new config system, `plugin:` protocol(e.g. `plugin:jest/recommended`) is
+no longer valid. As eslint does not automatically import the preset config
+(shareable config), you explicitly do it by yourself.
+
+**Note**: The new plugin object does not have `configs` property as well.
+
+```js
+import jest from 'eslint-plugin-jest/all';
+
+export default [
+ {
+ // A config for source code (non-test files)
+ files: ['**/*.test.{js,jsx}'],
+ // ...
+ },
+ // --- snip ---
+ ...jest, // This is not a plugin object, but a shareable config object(array)
+ // --- snip ---
+];
+```
+
## Rules
diff --git a/package.json b/package.json
index 6e7463721..502cb4901 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,19 @@
"email": "hello@jkimbo.com",
"url": "jkimbo.com"
},
- "main": "lib/",
+ "main": "lib/legacy.js",
+ "exports": {
+ ".": {
+ "import": "./lib/index.js",
+ "require": "./lib/legacy.js"
+ },
+ "./new": "./lib/index.js",
+ "./all": "./lib/configs/all.js",
+ "./recommended": "./lib/configs/recommended.js",
+ "./style": "./lib/configs/style.js",
+ "./globals": "./lib/globals.json",
+ "./globals.json": "./lib/globals.json"
+ },
"files": [
"docs/",
"lib/"
diff --git a/src/__tests__/rules.test.ts b/src/__tests__/rules.test.ts
index a8c66cc18..d973f552d 100644
--- a/src/__tests__/rules.test.ts
+++ b/src/__tests__/rules.test.ts
@@ -1,6 +1,6 @@
import { existsSync } from 'fs';
import { resolve } from 'path';
-import plugin from '../';
+import plugin from '../legacy';
const numberOfRules = 50;
const ruleNames = Object.keys(plugin.rules);
diff --git a/src/configs/all.ts b/src/configs/all.ts
new file mode 100644
index 000000000..c77d5cbb1
--- /dev/null
+++ b/src/configs/all.ts
@@ -0,0 +1,26 @@
+import globals from '../globals.json';
+import jest from '../index';
+import legacy from '../legacy';
+
+export default [
+ {
+ files: ['**/*.snap'],
+ plugins: {
+ jest,
+ },
+ processor: 'jest/.snap',
+ },
+ {
+ files: [
+ '**/*.{test,spec}.{js,cjs,mjs,jsx,ts,tsx}',
+ '**/__tests__/*.{js,cjs,mjs,jsx,ts,tsx}',
+ ],
+ languageOptions: {
+ globals,
+ },
+ plugins: {
+ jest,
+ },
+ rules: legacy.configs.all.rules,
+ },
+];
diff --git a/src/configs/recommended.ts b/src/configs/recommended.ts
new file mode 100644
index 000000000..24c9a87fc
--- /dev/null
+++ b/src/configs/recommended.ts
@@ -0,0 +1,12 @@
+import legacy from '../legacy';
+import all from './all';
+
+const [snap, test] = all;
+
+export default [
+ snap,
+ {
+ ...test,
+ rules: legacy.configs.recommended.rules,
+ },
+];
diff --git a/src/configs/style.ts b/src/configs/style.ts
new file mode 100644
index 000000000..66d66136d
--- /dev/null
+++ b/src/configs/style.ts
@@ -0,0 +1,12 @@
+import legacy from '../legacy';
+import all from './all';
+
+const [snap, test] = all;
+
+export default [
+ snap,
+ {
+ ...test,
+ rules: legacy.configs.style.rules,
+ },
+];
diff --git a/src/index.ts b/src/index.ts
index 06e45e2e1..2e363e5f5 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,87 +1,6 @@
-import { readdirSync } from 'fs';
-import { join, parse } from 'path';
-import type { TSESLint } from '@typescript-eslint/utils';
-import globals from './globals.json';
-import * as snapshotProcessor from './processors/snapshot-processor';
+import legacy from './legacy';
-type RuleModule = TSESLint.RuleModule & {
- meta: Required, 'docs'>>;
-};
-
-// v5 of `@typescript-eslint/experimental-utils` removed this
-declare module '@typescript-eslint/utils/dist/ts-eslint/Rule' {
- export interface RuleMetaDataDocs {
- category: 'Best Practices' | 'Possible Errors';
- }
-}
-
-// copied from https://github.com/babel/babel/blob/d8da63c929f2d28c401571e2a43166678c555bc4/packages/babel-helpers/src/helpers.js#L602-L606
-/* istanbul ignore next */
-const interopRequireDefault = (obj: any): { default: any } =>
- obj && obj.__esModule ? obj : { default: obj };
-
-const importDefault = (moduleName: string) =>
- // eslint-disable-next-line @typescript-eslint/no-require-imports
- interopRequireDefault(require(moduleName)).default;
-
-const rulesDir = join(__dirname, 'rules');
-const excludedFiles = ['__tests__', 'detectJestVersion', 'utils'];
-
-const rules = readdirSync(rulesDir)
- .map(rule => parse(rule).name)
- .filter(rule => !excludedFiles.includes(rule))
- .reduce>(
- (acc, curr) => ({
- ...acc,
- [curr]: importDefault(join(rulesDir, curr)) as RuleModule,
- }),
- {},
- );
-
-const recommendedRules = Object.entries(rules)
- .filter(([, rule]) => rule.meta.docs.recommended)
- .reduce(
- (acc, [name, rule]) => ({
- ...acc,
- [`jest/${name}`]: rule.meta.docs.recommended,
- }),
- {},
- );
-
-const allRules = Object.entries(rules)
- .filter(([, rule]) => !rule.meta.deprecated)
- .reduce(
- (acc, [name]) => ({
- ...acc,
- [`jest/${name}`]: 'error',
- }),
- {},
- );
-
-const createConfig = (rules: Record) => ({
- plugins: ['jest'],
- env: { 'jest/globals': true },
- rules,
-});
-
-export = {
- configs: {
- all: createConfig(allRules),
- recommended: createConfig(recommendedRules),
- style: createConfig({
- 'jest/no-alias-methods': 'warn',
- 'jest/prefer-to-be': 'error',
- 'jest/prefer-to-contain': 'error',
- 'jest/prefer-to-have-length': 'error',
- }),
- },
- environments: {
- globals: {
- globals,
- },
- },
- processors: {
- '.snap': snapshotProcessor,
- },
- rules,
+export default {
+ rules: legacy.rules,
+ processors: legacy.processors,
};
diff --git a/src/legacy.ts b/src/legacy.ts
new file mode 100644
index 000000000..06e45e2e1
--- /dev/null
+++ b/src/legacy.ts
@@ -0,0 +1,87 @@
+import { readdirSync } from 'fs';
+import { join, parse } from 'path';
+import type { TSESLint } from '@typescript-eslint/utils';
+import globals from './globals.json';
+import * as snapshotProcessor from './processors/snapshot-processor';
+
+type RuleModule = TSESLint.RuleModule & {
+ meta: Required, 'docs'>>;
+};
+
+// v5 of `@typescript-eslint/experimental-utils` removed this
+declare module '@typescript-eslint/utils/dist/ts-eslint/Rule' {
+ export interface RuleMetaDataDocs {
+ category: 'Best Practices' | 'Possible Errors';
+ }
+}
+
+// copied from https://github.com/babel/babel/blob/d8da63c929f2d28c401571e2a43166678c555bc4/packages/babel-helpers/src/helpers.js#L602-L606
+/* istanbul ignore next */
+const interopRequireDefault = (obj: any): { default: any } =>
+ obj && obj.__esModule ? obj : { default: obj };
+
+const importDefault = (moduleName: string) =>
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
+ interopRequireDefault(require(moduleName)).default;
+
+const rulesDir = join(__dirname, 'rules');
+const excludedFiles = ['__tests__', 'detectJestVersion', 'utils'];
+
+const rules = readdirSync(rulesDir)
+ .map(rule => parse(rule).name)
+ .filter(rule => !excludedFiles.includes(rule))
+ .reduce>(
+ (acc, curr) => ({
+ ...acc,
+ [curr]: importDefault(join(rulesDir, curr)) as RuleModule,
+ }),
+ {},
+ );
+
+const recommendedRules = Object.entries(rules)
+ .filter(([, rule]) => rule.meta.docs.recommended)
+ .reduce(
+ (acc, [name, rule]) => ({
+ ...acc,
+ [`jest/${name}`]: rule.meta.docs.recommended,
+ }),
+ {},
+ );
+
+const allRules = Object.entries(rules)
+ .filter(([, rule]) => !rule.meta.deprecated)
+ .reduce(
+ (acc, [name]) => ({
+ ...acc,
+ [`jest/${name}`]: 'error',
+ }),
+ {},
+ );
+
+const createConfig = (rules: Record) => ({
+ plugins: ['jest'],
+ env: { 'jest/globals': true },
+ rules,
+});
+
+export = {
+ configs: {
+ all: createConfig(allRules),
+ recommended: createConfig(recommendedRules),
+ style: createConfig({
+ 'jest/no-alias-methods': 'warn',
+ 'jest/prefer-to-be': 'error',
+ 'jest/prefer-to-contain': 'error',
+ 'jest/prefer-to-have-length': 'error',
+ }),
+ },
+ environments: {
+ globals: {
+ globals,
+ },
+ },
+ processors: {
+ '.snap': snapshotProcessor,
+ },
+ rules,
+};
diff --git a/tools/regenerate-docs.ts b/tools/regenerate-docs.ts
index af0f4bd72..2e81cc2d2 100644
--- a/tools/regenerate-docs.ts
+++ b/tools/regenerate-docs.ts
@@ -5,7 +5,7 @@ import * as path from 'path';
import type { JSONSchema, TSESLint } from '@typescript-eslint/utils';
import prettier, { Options } from 'prettier';
import { prettier as prettierRC } from '../package.json';
-import plugin from '../src/index';
+import plugin from '../src/legacy';
import { getRuleNoticeLines } from './rule-notices';
// Marker so that rule doc header (title/notices) can be automatically updated.
diff --git a/tools/rule-notices.ts b/tools/rule-notices.ts
index d73a09605..08d545002 100644
--- a/tools/rule-notices.ts
+++ b/tools/rule-notices.ts
@@ -1,4 +1,4 @@
-import plugin from '../src';
+import plugin from '../src/legacy';
enum MESSAGE_TYPE {
CONFIGS = 'configs',