@vitest/eslint-plugin 1.1.12 → 1.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -106,6 +106,39 @@ export default [
106
106
  ]
107
107
  ```
108
108
 
109
+ ### Shareable configurations
110
+
111
+ #### Recommended
112
+ This plugin exports a recommended configuration that enforces good testing practices.
113
+
114
+ To enable this configuration with `eslint.config.js`, use `vitest.configs.recommended`:
115
+
116
+ ```js
117
+ import vitest from "@vitest/eslint-plugin";
118
+
119
+ export default [
120
+ {
121
+ files: ["tests/**"], // or any other pattern
122
+ ...vitest.configs.recommended,
123
+ }
124
+ ]
125
+ ```
126
+
127
+
128
+ #### All
129
+ If you want to enable all rules instead of only some you can do so by adding the all configuration to your `eslint.config.js` config file:
130
+
131
+ ```js
132
+ import vitest from "@vitest/eslint-plugin";
133
+
134
+ export default [
135
+ {
136
+ files: ["tests/**"], // or any other pattern
137
+ ...vitest.configs.all,
138
+ }
139
+ ]
140
+ ```
141
+
109
142
  ### Rules
110
143
 
111
144
  <!-- begin auto-generated rules list -->
@@ -122,11 +155,11 @@ export default [
122
155
  | :----------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------- | :- | :- | :- | :- | :- |
123
156
  | [consistent-test-filename](docs/rules/consistent-test-filename.md) | require .spec test file pattern | | 🌐 | | | |
124
157
  | [consistent-test-it](docs/rules/consistent-test-it.md) | enforce using test or it but not both | | 🌐 | 🔧 | | |
125
- | [expect-expect](docs/rules/expect-expect.md) | enforce having expectation in test body | ✅ | | | | |
158
+ | [expect-expect](docs/rules/expect-expect.md) | enforce having expectation in test body | ✅ | 🌐 | | | |
126
159
  | [max-expects](docs/rules/max-expects.md) | enforce a maximum number of expect per test | | 🌐 | | | |
127
160
  | [max-nested-describe](docs/rules/max-nested-describe.md) | require describe block to be less than set max value or default value | | 🌐 | | | |
128
161
  | [no-alias-methods](docs/rules/no-alias-methods.md) | disallow alias methods | | 🌐 | 🔧 | | |
129
- | [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | disallow commented out tests | ✅ | | | | |
162
+ | [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | disallow commented out tests | ✅ | 🌐 | | | |
130
163
  | [no-conditional-expect](docs/rules/no-conditional-expect.md) | disallow conditional expects | | 🌐 | | | |
131
164
  | [no-conditional-in-test](docs/rules/no-conditional-in-test.md) | disallow conditional tests | | 🌐 | | | |
132
165
  | [no-conditional-tests](docs/rules/no-conditional-tests.md) | disallow conditional tests | | 🌐 | | | |
@@ -135,8 +168,8 @@ export default [
135
168
  | [no-duplicate-hooks](docs/rules/no-duplicate-hooks.md) | disallow duplicate hooks and teardown hooks | | 🌐 | | | |
136
169
  | [no-focused-tests](docs/rules/no-focused-tests.md) | disallow focused tests | | 🌐 | 🔧 | | |
137
170
  | [no-hooks](docs/rules/no-hooks.md) | disallow setup and teardown hooks | | 🌐 | | | |
138
- | [no-identical-title](docs/rules/no-identical-title.md) | disallow identical titles | ✅ | | 🔧 | | |
139
- | [no-import-node-test](docs/rules/no-import-node-test.md) | disallow importing `node:test` | ✅ | | 🔧 | | |
171
+ | [no-identical-title](docs/rules/no-identical-title.md) | disallow identical titles | ✅ | 🌐 | 🔧 | | |
172
+ | [no-import-node-test](docs/rules/no-import-node-test.md) | disallow importing `node:test` | ✅ | 🌐 | 🔧 | | |
140
173
  | [no-interpolation-in-snapshots](docs/rules/no-interpolation-in-snapshots.md) | disallow string interpolation in snapshots | | 🌐 | 🔧 | | |
141
174
  | [no-large-snapshots](docs/rules/no-large-snapshots.md) | disallow large snapshots | | 🌐 | | | |
142
175
  | [no-mocks-import](docs/rules/no-mocks-import.md) | disallow importing from __mocks__ directory | | 🌐 | | | |
@@ -167,12 +200,13 @@ export default [
167
200
  | [prefer-todo](docs/rules/prefer-todo.md) | enforce using `test.todo` | | 🌐 | 🔧 | | |
168
201
  | [prefer-vi-mocked](docs/rules/prefer-vi-mocked.md) | Prefer `vi.mocked()` over `fn as Mock` | | 🌐 | 🔧 | | |
169
202
  | [require-hook](docs/rules/require-hook.md) | require setup and teardown to be within a hook | | 🌐 | | | |
170
- | [require-local-test-context-for-concurrent-snapshots](docs/rules/require-local-test-context-for-concurrent-snapshots.md) | require local Test Context for concurrent snapshot tests | ✅ | | | | |
203
+ | [require-local-test-context-for-concurrent-snapshots](docs/rules/require-local-test-context-for-concurrent-snapshots.md) | require local Test Context for concurrent snapshot tests | ✅ | 🌐 | | | |
171
204
  | [require-to-throw-message](docs/rules/require-to-throw-message.md) | require toThrow() to be called with an error message | | 🌐 | | | |
172
205
  | [require-top-level-describe](docs/rules/require-top-level-describe.md) | enforce that all tests are in a top-level describe | | 🌐 | | | |
173
- | [valid-describe-callback](docs/rules/valid-describe-callback.md) | enforce valid describe callback | ✅ | | | | |
174
- | [valid-expect](docs/rules/valid-expect.md) | enforce valid `expect()` usage | ✅ | | 🔧 | | |
175
- | [valid-title](docs/rules/valid-title.md) | enforce valid titles | ✅ | | 🔧 | | |
206
+ | [valid-describe-callback](docs/rules/valid-describe-callback.md) | enforce valid describe callback | ✅ | 🌐 | | | |
207
+ | [valid-expect](docs/rules/valid-expect.md) | enforce valid `expect()` usage | ✅ | 🌐 | 🔧 | | |
208
+ | [valid-title](docs/rules/valid-title.md) | enforce valid titles | ✅ | 🌐 | 🔧 | | |
209
+ | [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | require promises that have expectations in their chain to be valid | | 🌐 | | | |
176
210
 
177
211
  <!-- end auto-generated rules list -->
178
212
 
package/dist/index.cjs CHANGED
@@ -23,7 +23,7 @@ function _interopNamespaceCompat(e) {
23
23
  const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
24
24
  const ts__default = /*#__PURE__*/_interopDefaultCompat(ts);
25
25
 
26
- const version = "1.1.11";
26
+ const version = "1.1.13";
27
27
 
28
28
  function createEslintRule(rule) {
29
29
  const createRule = utils.ESLintUtils.RuleCreator(
@@ -3377,6 +3377,19 @@ const paramsLocation = (params) => {
3377
3377
  end: last.loc.end
3378
3378
  };
3379
3379
  };
3380
+ const hasNonEachMembersAndParams = (vitestFnCall, functionExpression) => {
3381
+ return vitestFnCall.members.every((s) => getAccessorValue(s) !== "each") && functionExpression.params.length;
3382
+ };
3383
+ const reportUnexpectedReturnInDescribe = (blockStatement, context) => {
3384
+ blockStatement.body.forEach((node) => {
3385
+ if (node.type !== utils.AST_NODE_TYPES.ReturnStatement)
3386
+ return;
3387
+ context.report({
3388
+ messageId: "unexpectedReturnInDescribe",
3389
+ node
3390
+ });
3391
+ });
3392
+ };
3380
3393
  const validDescribeCallback = createEslintRule({
3381
3394
  name: RULE_NAME$i,
3382
3395
  meta: {
@@ -3408,42 +3421,53 @@ const validDescribeCallback = createEslintRule({
3408
3421
  loc: node.loc
3409
3422
  });
3410
3423
  }
3411
- const [, callback] = node.arguments;
3412
- if (!callback) {
3424
+ const [, arg2, arg3] = node.arguments;
3425
+ if (!arg2) {
3413
3426
  context.report({
3414
3427
  messageId: "nameAndCallback",
3415
3428
  loc: paramsLocation(node.arguments)
3416
3429
  });
3417
3430
  return;
3418
3431
  }
3419
- if (!isFunction(callback)) {
3432
+ if (!isFunction(arg2)) {
3433
+ if (arg3 && isFunction(arg3)) {
3434
+ if (hasNonEachMembersAndParams(vitestFnCall, arg3)) {
3435
+ context.report({
3436
+ messageId: "unexpectedDescribeArgument",
3437
+ node: arg3
3438
+ });
3439
+ }
3440
+ if (arg3.body.type === utils.AST_NODE_TYPES.CallExpression) {
3441
+ context.report({
3442
+ messageId: "unexpectedReturnInDescribe",
3443
+ node: arg3
3444
+ });
3445
+ }
3446
+ if (arg3.body.type === utils.AST_NODE_TYPES.BlockStatement) {
3447
+ reportUnexpectedReturnInDescribe(arg3.body, context);
3448
+ }
3449
+ return;
3450
+ }
3420
3451
  context.report({
3421
3452
  messageId: "secondArgumentMustBeFunction",
3422
3453
  loc: paramsLocation(node.arguments)
3423
3454
  });
3424
3455
  return;
3425
3456
  }
3426
- if (vitestFnCall.members.every((s) => getAccessorValue(s) !== "each") && callback.params.length) {
3457
+ if (hasNonEachMembersAndParams(vitestFnCall, arg2)) {
3427
3458
  context.report({
3428
3459
  messageId: "unexpectedDescribeArgument",
3429
- node: callback
3460
+ node: arg2
3430
3461
  });
3431
3462
  }
3432
- if (callback.body.type === utils.AST_NODE_TYPES.CallExpression) {
3463
+ if (arg2.body.type === utils.AST_NODE_TYPES.CallExpression) {
3433
3464
  context.report({
3434
3465
  messageId: "unexpectedReturnInDescribe",
3435
- node: callback
3466
+ node: arg2
3436
3467
  });
3437
3468
  }
3438
- if (callback.body.type === utils.AST_NODE_TYPES.BlockStatement) {
3439
- callback.body.body.forEach((node2) => {
3440
- if (node2.type === utils.AST_NODE_TYPES.ReturnStatement) {
3441
- context.report({
3442
- messageId: "unexpectedReturnInDescribe",
3443
- node: node2
3444
- });
3445
- }
3446
- });
3469
+ if (arg2.body.type === utils.AST_NODE_TYPES.BlockStatement) {
3470
+ reportUnexpectedReturnInDescribe(arg2.body, context);
3447
3471
  }
3448
3472
  }
3449
3473
  };
@@ -4842,7 +4866,15 @@ const allRules = {
4842
4866
  [RULE_NAME$4]: "warn",
4843
4867
  [RULE_NAME$3]: "warn",
4844
4868
  [RULE_NAME$2]: "warn",
4845
- [RULE_NAME]: "warn"
4869
+ [RULE_NAME]: "warn",
4870
+ [RULE_NAME$U]: "warn",
4871
+ [RULE_NAME$X]: "warn",
4872
+ [RULE_NAME$M]: "warn",
4873
+ [RULE_NAME$x]: "warn",
4874
+ [RULE_NAME$w]: "warn",
4875
+ [RULE_NAME$i]: "warn",
4876
+ [RULE_NAME$e]: "warn",
4877
+ [RULE_NAME$K]: "warn"
4846
4878
  };
4847
4879
  const recommended = {
4848
4880
  [RULE_NAME$U]: "error",
package/dist/index.d.cts CHANGED
@@ -153,6 +153,14 @@ declare const plugin: {
153
153
  readonly "vitest/padding-around-expect-groups": "warn";
154
154
  readonly "vitest/padding-around-test-blocks": "warn";
155
155
  readonly "vitest/valid-expect-in-promise": "warn";
156
+ readonly "vitest/expect-expect": "warn";
157
+ readonly "vitest/no-identical-title": "warn";
158
+ readonly "vitest/no-commented-out-tests": "warn";
159
+ readonly "vitest/valid-title": "warn";
160
+ readonly "vitest/valid-expect": "warn";
161
+ readonly "vitest/valid-describe-callback": "warn";
162
+ readonly "vitest/require-local-test-context-for-concurrent-snapshots": "warn";
163
+ readonly "vitest/no-import-node-test": "warn";
156
164
  };
157
165
  };
158
166
  env: {
package/dist/index.d.mts CHANGED
@@ -153,6 +153,14 @@ declare const plugin: {
153
153
  readonly "vitest/padding-around-expect-groups": "warn";
154
154
  readonly "vitest/padding-around-test-blocks": "warn";
155
155
  readonly "vitest/valid-expect-in-promise": "warn";
156
+ readonly "vitest/expect-expect": "warn";
157
+ readonly "vitest/no-identical-title": "warn";
158
+ readonly "vitest/no-commented-out-tests": "warn";
159
+ readonly "vitest/valid-title": "warn";
160
+ readonly "vitest/valid-expect": "warn";
161
+ readonly "vitest/valid-describe-callback": "warn";
162
+ readonly "vitest/require-local-test-context-for-concurrent-snapshots": "warn";
163
+ readonly "vitest/no-import-node-test": "warn";
156
164
  };
157
165
  };
158
166
  env: {
package/dist/index.d.ts CHANGED
@@ -153,6 +153,14 @@ declare const plugin: {
153
153
  readonly "vitest/padding-around-expect-groups": "warn";
154
154
  readonly "vitest/padding-around-test-blocks": "warn";
155
155
  readonly "vitest/valid-expect-in-promise": "warn";
156
+ readonly "vitest/expect-expect": "warn";
157
+ readonly "vitest/no-identical-title": "warn";
158
+ readonly "vitest/no-commented-out-tests": "warn";
159
+ readonly "vitest/valid-title": "warn";
160
+ readonly "vitest/valid-expect": "warn";
161
+ readonly "vitest/valid-describe-callback": "warn";
162
+ readonly "vitest/require-local-test-context-for-concurrent-snapshots": "warn";
163
+ readonly "vitest/no-import-node-test": "warn";
156
164
  };
157
165
  };
158
166
  env: {
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import { isAbsolute, posix } from 'node:path';
4
4
  import ts from 'typescript';
5
5
  import { createRequire } from 'node:module';
6
6
 
7
- const version = "1.1.11";
7
+ const version = "1.1.13";
8
8
 
9
9
  function createEslintRule(rule) {
10
10
  const createRule = ESLintUtils.RuleCreator(
@@ -3358,6 +3358,19 @@ const paramsLocation = (params) => {
3358
3358
  end: last.loc.end
3359
3359
  };
3360
3360
  };
3361
+ const hasNonEachMembersAndParams = (vitestFnCall, functionExpression) => {
3362
+ return vitestFnCall.members.every((s) => getAccessorValue(s) !== "each") && functionExpression.params.length;
3363
+ };
3364
+ const reportUnexpectedReturnInDescribe = (blockStatement, context) => {
3365
+ blockStatement.body.forEach((node) => {
3366
+ if (node.type !== AST_NODE_TYPES.ReturnStatement)
3367
+ return;
3368
+ context.report({
3369
+ messageId: "unexpectedReturnInDescribe",
3370
+ node
3371
+ });
3372
+ });
3373
+ };
3361
3374
  const validDescribeCallback = createEslintRule({
3362
3375
  name: RULE_NAME$i,
3363
3376
  meta: {
@@ -3389,42 +3402,53 @@ const validDescribeCallback = createEslintRule({
3389
3402
  loc: node.loc
3390
3403
  });
3391
3404
  }
3392
- const [, callback] = node.arguments;
3393
- if (!callback) {
3405
+ const [, arg2, arg3] = node.arguments;
3406
+ if (!arg2) {
3394
3407
  context.report({
3395
3408
  messageId: "nameAndCallback",
3396
3409
  loc: paramsLocation(node.arguments)
3397
3410
  });
3398
3411
  return;
3399
3412
  }
3400
- if (!isFunction(callback)) {
3413
+ if (!isFunction(arg2)) {
3414
+ if (arg3 && isFunction(arg3)) {
3415
+ if (hasNonEachMembersAndParams(vitestFnCall, arg3)) {
3416
+ context.report({
3417
+ messageId: "unexpectedDescribeArgument",
3418
+ node: arg3
3419
+ });
3420
+ }
3421
+ if (arg3.body.type === AST_NODE_TYPES.CallExpression) {
3422
+ context.report({
3423
+ messageId: "unexpectedReturnInDescribe",
3424
+ node: arg3
3425
+ });
3426
+ }
3427
+ if (arg3.body.type === AST_NODE_TYPES.BlockStatement) {
3428
+ reportUnexpectedReturnInDescribe(arg3.body, context);
3429
+ }
3430
+ return;
3431
+ }
3401
3432
  context.report({
3402
3433
  messageId: "secondArgumentMustBeFunction",
3403
3434
  loc: paramsLocation(node.arguments)
3404
3435
  });
3405
3436
  return;
3406
3437
  }
3407
- if (vitestFnCall.members.every((s) => getAccessorValue(s) !== "each") && callback.params.length) {
3438
+ if (hasNonEachMembersAndParams(vitestFnCall, arg2)) {
3408
3439
  context.report({
3409
3440
  messageId: "unexpectedDescribeArgument",
3410
- node: callback
3441
+ node: arg2
3411
3442
  });
3412
3443
  }
3413
- if (callback.body.type === AST_NODE_TYPES.CallExpression) {
3444
+ if (arg2.body.type === AST_NODE_TYPES.CallExpression) {
3414
3445
  context.report({
3415
3446
  messageId: "unexpectedReturnInDescribe",
3416
- node: callback
3447
+ node: arg2
3417
3448
  });
3418
3449
  }
3419
- if (callback.body.type === AST_NODE_TYPES.BlockStatement) {
3420
- callback.body.body.forEach((node2) => {
3421
- if (node2.type === AST_NODE_TYPES.ReturnStatement) {
3422
- context.report({
3423
- messageId: "unexpectedReturnInDescribe",
3424
- node: node2
3425
- });
3426
- }
3427
- });
3450
+ if (arg2.body.type === AST_NODE_TYPES.BlockStatement) {
3451
+ reportUnexpectedReturnInDescribe(arg2.body, context);
3428
3452
  }
3429
3453
  }
3430
3454
  };
@@ -4823,7 +4847,15 @@ const allRules = {
4823
4847
  [RULE_NAME$4]: "warn",
4824
4848
  [RULE_NAME$3]: "warn",
4825
4849
  [RULE_NAME$2]: "warn",
4826
- [RULE_NAME]: "warn"
4850
+ [RULE_NAME]: "warn",
4851
+ [RULE_NAME$U]: "warn",
4852
+ [RULE_NAME$X]: "warn",
4853
+ [RULE_NAME$M]: "warn",
4854
+ [RULE_NAME$x]: "warn",
4855
+ [RULE_NAME$w]: "warn",
4856
+ [RULE_NAME$i]: "warn",
4857
+ [RULE_NAME$e]: "warn",
4858
+ [RULE_NAME$K]: "warn"
4827
4859
  };
4828
4860
  const recommended = {
4829
4861
  [RULE_NAME$U]: "error",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitest/eslint-plugin",
3
- "version": "1.1.12",
3
+ "version": "1.1.14",
4
4
  "license": "MIT",
5
5
  "description": "Eslint plugin for vitest",
6
6
  "repository": "vitest-dev/eslint-plugin-vitest",
@@ -29,24 +29,24 @@
29
29
  "dist"
30
30
  ],
31
31
  "devDependencies": {
32
- "@stylistic/eslint-plugin": "^2.10.1",
32
+ "@stylistic/eslint-plugin": "^2.11.0",
33
33
  "@types/eslint": "^9.6.1",
34
- "@types/mocha": "^10.0.9",
35
- "@types/node": "^20.17.6",
34
+ "@types/mocha": "^10.0.10",
35
+ "@types/node": "^20.17.9",
36
36
  "@typescript-eslint/eslint-plugin": "8.0.0",
37
37
  "@typescript-eslint/parser": "8.0.0",
38
38
  "@typescript-eslint/rule-tester": "8.0.0",
39
- "@vitest/eslint-plugin": "^1.1.8",
39
+ "@vitest/eslint-plugin": "^1.1.12",
40
40
  "bumpp": "^9.8.1",
41
41
  "concurrently": "^8.2.2",
42
- "eslint": "^9.14.0",
42
+ "eslint": "^9.16.0",
43
43
  "eslint-doc-generator": "^1.7.1",
44
- "eslint-plugin-eslint-plugin": "^6.3.1",
44
+ "eslint-plugin-eslint-plugin": "^6.3.2",
45
45
  "eslint-remote-tester": "^4.0.1",
46
46
  "eslint-remote-tester-repositories": "^2.0.0",
47
47
  "importx": "^0.3.11",
48
48
  "tsx": "^4.19.2",
49
- "typescript": "^5.6.3",
49
+ "typescript": "^5.7.2",
50
50
  "unbuild": "^2.0.0",
51
51
  "vitest": "^1.6.0"
52
52
  },