eslint-plugin-jest 24.2.1 → 24.3.3

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/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ ## [24.3.3](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.2...v24.3.3) (2021-04-02)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **no-duplicate-hooks:** support `describe.each` ([#797](https://github.com/jest-community/eslint-plugin-jest/issues/797)) ([243cb4f](https://github.com/jest-community/eslint-plugin-jest/commit/243cb4f970e40aa195a3bffa0528dbdbfef7c4f5)), closes [#642](https://github.com/jest-community/eslint-plugin-jest/issues/642)
7
+ * **prefer-expect-assertions:** support `.each` ([#798](https://github.com/jest-community/eslint-plugin-jest/issues/798)) ([f758243](https://github.com/jest-community/eslint-plugin-jest/commit/f75824359f2242f53997c59c238d83a59badeea3)), closes [#676](https://github.com/jest-community/eslint-plugin-jest/issues/676)
8
+
9
+ ## [24.3.2](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.1...v24.3.2) (2021-03-16)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **consistent-test-it:** properly handle `describe.each` ([#796](https://github.com/jest-community/eslint-plugin-jest/issues/796)) ([035bd30](https://github.com/jest-community/eslint-plugin-jest/commit/035bd30af43f1215e65bf1b26c2ef2e6d174d3c8)), closes [#795](https://github.com/jest-community/eslint-plugin-jest/issues/795)
15
+
16
+ ## [24.3.1](https://github.com/jest-community/eslint-plugin-jest/compare/v24.3.0...v24.3.1) (2021-03-13)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * **no-focused-tests:** report on `skip` instead of `concurrent` ([#791](https://github.com/jest-community/eslint-plugin-jest/issues/791)) ([2b65b49](https://github.com/jest-community/eslint-plugin-jest/commit/2b65b491cea2c956e4ba314a809915b9ec62933b))
22
+
23
+ # [24.3.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.2.1...v24.3.0) (2021-03-13)
24
+
25
+
26
+ ### Features
27
+
28
+ * **unbound-method:** create rule ([#765](https://github.com/jest-community/eslint-plugin-jest/issues/765)) ([b1f4ed3](https://github.com/jest-community/eslint-plugin-jest/commit/b1f4ed3f6bb0264fdefb5138ba913fa2bacc725c))
29
+
1
30
  ## [24.2.1](https://github.com/jest-community/eslint-plugin-jest/compare/v24.2.0...v24.2.1) (2021-03-10)
2
31
 
3
32
 
package/README.md CHANGED
@@ -128,7 +128,7 @@ installations requiring long-term consistency.
128
128
 
129
129
  ## Rules
130
130
 
131
- <!-- begin rules list -->
131
+ <!-- begin base rules list -->
132
132
 
133
133
  | Rule | Description | Configurations | Fixable |
134
134
  | ---------------------------------------------------------------------------- | --------------------------------------------------------------- | ---------------- | ------------ |
@@ -173,7 +173,32 @@ installations requiring long-term consistency.
173
173
  | [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Enforce having return statement when testing with promises | ![recommended][] | |
174
174
  | [valid-title](docs/rules/valid-title.md) | Enforce valid titles | ![recommended][] | ![fixable][] |
175
175
 
176
- <!-- end rules list -->
176
+ <!-- end base rules list -->
177
+
178
+ ## TypeScript Rules
179
+
180
+ In addition to the above rules, this plugin also includes a few advanced rules
181
+ that are powered by type-checking information provided by TypeScript.
182
+
183
+ In order to use these rules, you must be using `@typescript-eslint/parser` &
184
+ adjust your eslint config as outlined
185
+ [here](https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/TYPED_LINTING.md)
186
+
187
+ Note that unlike the type-checking rules in `@typescript-eslint/eslint-plugin`,
188
+ the rules here will fallback to doing nothing if type information is not
189
+ available, meaning its safe to include them in shared configs that could be used
190
+ on JavaScript and TypeScript projects.
191
+
192
+ Also note that `unbound-method` depends on `@typescript-eslint/eslint-plugin`,
193
+ as it extends the original `unbound-method` rule from that plugin.
194
+
195
+ <!-- begin type rules list -->
196
+
197
+ | Rule | Description | Configurations | Fixable |
198
+ | ---------------------------------------------- | ------------------------------------------------------------- | -------------- | ------- |
199
+ | [unbound-method](docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope | | |
200
+
201
+ <!-- end type rules list -->
177
202
 
178
203
  ## Credit
179
204
 
@@ -0,0 +1,54 @@
1
+ # Enforces unbound methods are called with their expected scope (`unbound-method`)
2
+
3
+ ## Rule Details
4
+
5
+ This rule extends the base [`@typescript-eslint/unbound-method`][original-rule]
6
+ rule, meaning you must depend on `@typescript-eslint/eslint-plugin` for it to
7
+ work. It adds support for understanding when it's ok to pass an unbound method
8
+ to `expect` calls.
9
+
10
+ See the [`@typescript-eslint` documentation][original-rule] for more details on
11
+ the `unbound-method` rule.
12
+
13
+ Note that while this rule requires type information to work, it will fail
14
+ silently when not available allowing you to safely enable it on projects that
15
+ are not using TypeScript.
16
+
17
+ ## How to use
18
+
19
+ ```json5
20
+ {
21
+ parser: '@typescript-eslint/parser',
22
+ parserOptions: {
23
+ project: 'tsconfig.json',
24
+ ecmaVersion: 2020,
25
+ sourceType: 'module',
26
+ },
27
+ overrides: [
28
+ {
29
+ files: ['test/**'],
30
+ extends: ['jest'],
31
+ rules: {
32
+ // you should turn the original rule off *only* for test files
33
+ '@typescript-eslint/unbound-method': 'off',
34
+ 'jest/unbound-method': 'error',
35
+ },
36
+ },
37
+ ],
38
+ rules: {
39
+ '@typescript-eslint/unbound-method': 'error',
40
+ },
41
+ }
42
+ ```
43
+
44
+ This rule should be applied to your test files in place of the original rule,
45
+ which should be applied to the rest of your codebase.
46
+
47
+ ## Options
48
+
49
+ See [`@typescript-eslint/unbound-method`][original-rule] options.
50
+
51
+ <sup>Taken with ❤️ [from `@typescript-eslint` core][original-rule]</sup>
52
+
53
+ [original-rule]:
54
+ https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/unbound-method.md
@@ -90,7 +90,7 @@ var _default = (0, _utils.createRule)({
90
90
  },
91
91
 
92
92
  'CallExpression:exit'(node) {
93
- if ((0, _utils.isDescribe)(node)) {
93
+ if ((0, _utils.isDescribe)(node) && !(0, _utils.isEachCall)(node)) {
94
94
  describeNestingLevel--;
95
95
  }
96
96
  }
@@ -17,9 +17,7 @@ const findNodeNameAndArgument = node => {
17
17
  }
18
18
 
19
19
  if ((0, _utils.isEachCall)(node)) {
20
- var _node$parent;
21
-
22
- if (((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) === _experimentalUtils.AST_NODE_TYPES.CallExpression && hasStringAsFirstArgument(node.parent)) {
20
+ if (node.parent.arguments.length > 0 && (0, _utils.isStringNode)(node.parent.arguments[0])) {
23
21
  return [node.callee.object.name, node.parent.arguments[0]];
24
22
  }
25
23
 
@@ -55,7 +55,7 @@ var _default = (0, _utils.createRule)({
55
55
  },
56
56
 
57
57
  'CallExpression:exit'(node) {
58
- if ((0, _utils.isDescribe)(node)) {
58
+ if ((0, _utils.isDescribe)(node) && !(0, _utils.isEachCall)(node)) {
59
59
  hookContexts.pop();
60
60
  }
61
61
  }
@@ -63,7 +63,7 @@ var _default = (0, _utils.createRule)({
63
63
  if (calleeObject.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isCallToTestOnlyFunction(calleeObject)) {
64
64
  context.report({
65
65
  messageId: 'focusedTest',
66
- node: calleeObject.property,
66
+ node: isConcurrentExpression(calleeObject) ? callee.property : calleeObject.property,
67
67
  suggest: [{
68
68
  messageId: 'suggestRemoveFocus',
69
69
 
@@ -55,12 +55,24 @@ var _default = (0, _utils.createRule)({
55
55
 
56
56
  create(context, [options]) {
57
57
  return {
58
- 'CallExpression[callee.name=/^(it|test)$/][arguments.1.body.body]'(node) {
59
- if (options.onlyFunctionsWithAsyncKeyword && !node.arguments[1].async) {
58
+ CallExpression(node) {
59
+ if (!(0, _utils.isTestCase)(node)) {
60
60
  return;
61
61
  }
62
62
 
63
- const testFuncBody = node.arguments[1].body.body;
63
+ const args = (0, _utils.isEachCall)(node) ? node.parent.arguments : node.arguments;
64
+
65
+ if (args.length < 2) {
66
+ return;
67
+ }
68
+
69
+ const [, testFn] = args;
70
+
71
+ if (!(0, _utils.isFunction)(testFn) || testFn.body.type !== _experimentalUtils.AST_NODE_TYPES.BlockStatement || options.onlyFunctionsWithAsyncKeyword && !testFn.async) {
72
+ return;
73
+ }
74
+
75
+ const testFuncBody = testFn.body.body;
64
76
 
65
77
  if (!isFirstLineExprStmt(testFuncBody)) {
66
78
  context.report({
@@ -68,7 +80,7 @@ var _default = (0, _utils.createRule)({
68
80
  node,
69
81
  suggest: suggestions.map(([messageId, text]) => ({
70
82
  messageId,
71
- fix: fixer => fixer.insertTextBeforeRange([node.arguments[1].body.range[0] + 1, node.arguments[1].body.range[1]], text)
83
+ fix: fixer => fixer.insertTextBeforeRange([testFn.body.range[0] + 1, testFn.body.range[1]], text)
72
84
  }))
73
85
  });
74
86
  return;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _utils = require("./utils");
9
+
10
+ const toThrowMatchers = ['toThrow', 'toThrowError', 'toThrowErrorMatchingSnapshot', 'toThrowErrorMatchingInlineSnapshot'];
11
+
12
+ const isJestExpectToThrowCall = node => {
13
+ if (!(0, _utils.isExpectCall)(node)) {
14
+ return false;
15
+ }
16
+
17
+ const {
18
+ matcher
19
+ } = (0, _utils.parseExpectCall)(node);
20
+
21
+ if (!matcher) {
22
+ return false;
23
+ }
24
+
25
+ return !toThrowMatchers.includes(matcher.name);
26
+ };
27
+
28
+ const baseRule = (() => {
29
+ try {
30
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
31
+ const TSESLintPlugin = require('@typescript-eslint/eslint-plugin');
32
+
33
+ return TSESLintPlugin.rules['unbound-method'];
34
+ } catch (e) {
35
+ const error = e;
36
+
37
+ if (error.code === 'MODULE_NOT_FOUND') {
38
+ return null;
39
+ }
40
+
41
+ throw error;
42
+ }
43
+ })();
44
+
45
+ const tryCreateBaseRule = context => {
46
+ try {
47
+ return baseRule === null || baseRule === void 0 ? void 0 : baseRule.create(context);
48
+ } catch {
49
+ return null;
50
+ }
51
+ };
52
+
53
+ var _default = (0, _utils.createRule)({
54
+ defaultOptions: [{
55
+ ignoreStatic: false
56
+ }],
57
+ ...baseRule,
58
+ name: __filename,
59
+ meta: {
60
+ messages: {
61
+ unbound: 'This rule requires `@typescript-eslint/eslint-plugin`'
62
+ },
63
+ schema: [],
64
+ type: 'problem',
65
+ ...(baseRule === null || baseRule === void 0 ? void 0 : baseRule.meta),
66
+ docs: {
67
+ category: 'Best Practices',
68
+ description: 'Enforces unbound methods are called with their expected scope',
69
+ requiresTypeChecking: true,
70
+ ...(baseRule === null || baseRule === void 0 ? void 0 : baseRule.meta.docs),
71
+ recommended: false
72
+ }
73
+ },
74
+
75
+ create(context) {
76
+ const baseSelectors = tryCreateBaseRule(context);
77
+
78
+ if (!baseSelectors) {
79
+ return {};
80
+ }
81
+
82
+ let inExpectToThrowCall = false;
83
+ return { ...baseSelectors,
84
+
85
+ CallExpression(node) {
86
+ inExpectToThrowCall = isJestExpectToThrowCall(node);
87
+ },
88
+
89
+ 'CallExpression:exit'(node) {
90
+ if (inExpectToThrowCall && isJestExpectToThrowCall(node)) {
91
+ inExpectToThrowCall = false;
92
+ }
93
+ },
94
+
95
+ MemberExpression(node) {
96
+ var _baseSelectors$Member;
97
+
98
+ if (inExpectToThrowCall) {
99
+ return;
100
+ }
101
+
102
+ (_baseSelectors$Member = baseSelectors.MemberExpression) === null || _baseSelectors$Member === void 0 ? void 0 : _baseSelectors$Member.call(baseSelectors, node);
103
+ }
104
+
105
+ };
106
+ }
107
+
108
+ });
109
+
110
+ exports.default = _default;
@@ -403,18 +403,22 @@ exports.isTestCase = isTestCase;
403
403
 
404
404
  const isDescribe = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.Identifier && DescribeAlias.hasOwnProperty(node.callee.name) || node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && node.callee.object.type === _experimentalUtils.AST_NODE_TYPES.Identifier && DescribeAlias.hasOwnProperty(node.callee.object.name) && node.callee.property.type === _experimentalUtils.AST_NODE_TYPES.Identifier && DescribeProperty.hasOwnProperty(node.callee.property.name) || node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression && node.callee.tag.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && node.callee.tag.object.type === _experimentalUtils.AST_NODE_TYPES.Identifier && DescribeAlias.hasOwnProperty(node.callee.tag.object.name);
405
405
  /**
406
- * Checks if the given node` is a call to `<describe|test|it>.each(...)`.
407
- * If `true`, the code must look like `<method>.each(...)`.
406
+ * Checks if the given node` is a call to `<describe|test|it>.each(...)()`.
407
+ * If `true`, the code must look like `<method>.each(...)()`.
408
408
  *
409
409
  * @param {JestFunctionCallExpression<DescribeAlias | TestCaseName>} node
410
410
  *
411
- * @return {node is JestFunctionCallExpressionWithMemberExpressionCallee<DescribeAlias | TestCaseName, DescribeProperty.each | TestCaseProperty.each>}
411
+ * @return {node is JestFunctionCallExpressionWithMemberExpressionCallee<DescribeAlias | TestCaseName, DescribeProperty.each | TestCaseProperty.each> & {parent: TSESTree.CallExpression}}
412
412
  */
413
413
 
414
414
 
415
415
  exports.isDescribe = isDescribe;
416
416
 
417
- const isEachCall = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isSupportedAccessor(node.callee.property, DescribeProperty.each);
417
+ const isEachCall = node => {
418
+ var _node$parent;
419
+
420
+ return ((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && isSupportedAccessor(node.callee.property, DescribeProperty.each);
421
+ };
418
422
  /**
419
423
  * Gets the arguments of the given `JestFunctionCallExpression`.
420
424
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-jest",
3
- "version": "24.2.1",
3
+ "version": "24.3.3",
4
4
  "description": "Eslint rules for Jest",
5
5
  "keywords": [
6
6
  "eslint",
@@ -62,7 +62,8 @@
62
62
  "displayName": "test",
63
63
  "testEnvironment": "node",
64
64
  "testPathIgnorePatterns": [
65
- "<rootDir>/lib/.*"
65
+ "<rootDir>/lib/.*",
66
+ "<rootDir>/src/rules/__tests__/fixtures/*"
66
67
  ]
67
68
  },
68
69
  {
@@ -107,7 +108,7 @@
107
108
  "eslint-plugin-import": "^2.20.2",
108
109
  "eslint-plugin-node": "^11.0.0",
109
110
  "eslint-plugin-prettier": "^3.0.0",
110
- "husky": "^5.1.3",
111
+ "husky": "^6.0.0",
111
112
  "is-ci": "^3.0.0",
112
113
  "jest": "^26.0.1",
113
114
  "jest-runner-eslint": "^0.10.0",
@@ -121,8 +122,14 @@
121
122
  "typescript": "^4.0.0"
122
123
  },
123
124
  "peerDependencies": {
125
+ "@typescript-eslint/eslint-plugin": ">= 4",
124
126
  "eslint": ">=5"
125
127
  },
128
+ "peerDependenciesMeta": {
129
+ "@typescript-eslint/eslint-plugin": {
130
+ "optional": true
131
+ }
132
+ },
126
133
  "engines": {
127
134
  "node": ">=10"
128
135
  },