eslint-plugin-jest 26.5.1 → 26.6.0

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
@@ -201,6 +201,7 @@ installations requiring long-term consistency.
201
201
  | ---------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------- | ------------ |
202
202
  | [consistent-test-it](docs/rules/consistent-test-it.md) | Have control over `test` and `it` usages | | ![fixable][] |
203
203
  | [expect-expect](docs/rules/expect-expect.md) | Enforce assertion to be made in a test body | ![recommended][] | |
204
+ | [max-expects](docs/rules/max-expects.md) | Enforces a maximum number assertion calls in a test body | | |
204
205
  | [max-nested-describe](docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls | | |
205
206
  | [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods | ![style][] | ![fixable][] |
206
207
  | [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests | ![recommended][] | |
@@ -267,9 +268,9 @@ as it extends the original `unbound-method` rule from that plugin.
267
268
 
268
269
  <!-- begin type rules list -->
269
270
 
270
- | Rule | Description | Configurations | Fixable |
271
- | ---------------------------------------------- | ------------------------------------------------------------- | -------------- | ------- |
272
- | [unbound-method](docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope | | |
271
+ | Rule | Description | Configurations | Fixable |
272
+ | ---------------------------------------------- | ------------------------------------------------------------ | -------------- | ------- |
273
+ | [unbound-method](docs/rules/unbound-method.md) | Enforce unbound methods are called with their expected scope | | |
273
274
 
274
275
  <!-- end type rules list -->
275
276
 
@@ -0,0 +1,74 @@
1
+ # Enforces a maximum number assertion calls in a test body (`max-expects`)
2
+
3
+ As more assertions are made, there is a possible tendency for the test to be
4
+ more likely to mix multiple objectives. To avoid this, this rule reports when
5
+ the maximum number of assertions is exceeded.
6
+
7
+ ## Rule Details
8
+
9
+ This rule enforces a maximum number of `expect()` calls.
10
+
11
+ The following patterns are considered warnings (with the default option of
12
+ `{ "max": 5 } `):
13
+
14
+ ```js
15
+ test('should not pass', () => {
16
+ expect(true).toBeDefined();
17
+ expect(true).toBeDefined();
18
+ expect(true).toBeDefined();
19
+ expect(true).toBeDefined();
20
+ expect(true).toBeDefined();
21
+ expect(true).toBeDefined();
22
+ });
23
+
24
+ it('should not pass', () => {
25
+ expect(true).toBeDefined();
26
+ expect(true).toBeDefined();
27
+ expect(true).toBeDefined();
28
+ expect(true).toBeDefined();
29
+ expect(true).toBeDefined();
30
+ expect(true).toBeDefined();
31
+ });
32
+ ```
33
+
34
+ The following patterns are **not** considered warnings (with the default option
35
+ of `{ "max": 5 } `):
36
+
37
+ ```js
38
+ test('shout pass');
39
+
40
+ test('shout pass', () => {});
41
+
42
+ test.skip('shout pass', () => {});
43
+
44
+ test('should pass', function () {
45
+ expect(true).toBeDefined();
46
+ });
47
+
48
+ test('should pass', () => {
49
+ expect(true).toBeDefined();
50
+ expect(true).toBeDefined();
51
+ expect(true).toBeDefined();
52
+ expect(true).toBeDefined();
53
+ expect(true).toBeDefined();
54
+ });
55
+ ```
56
+
57
+ ## Options
58
+
59
+ ```json
60
+ {
61
+ "jest/max-expects": [
62
+ "error",
63
+ {
64
+ "max": 5
65
+ }
66
+ ]
67
+ }
68
+ ```
69
+
70
+ ### `max`
71
+
72
+ Enforces a maximum number of `expect()`.
73
+
74
+ This has a default value of `5`.
@@ -130,4 +130,4 @@ describe('foo', () => {
130
130
 
131
131
  ## Further Reading
132
132
 
133
- - [Order of execution of describe and test blocks](https://jestjs.io/docs/setup-teardown#order-of-execution-of-describe-and-test-blocks)
133
+ - [Order of Execution](https://jestjs.io/docs/setup-teardown#order-of-execution)
@@ -1,4 +1,4 @@
1
- # Enforces unbound methods are called with their expected scope (`unbound-method`)
1
+ # Enforce unbound methods are called with their expected scope (`unbound-method`)
2
2
 
3
3
  ## Rule Details
4
4
 
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _utils = require("@typescript-eslint/utils");
9
+
10
+ var _utils2 = require("./utils");
11
+
12
+ var _default = (0, _utils2.createRule)({
13
+ name: __filename,
14
+ meta: {
15
+ docs: {
16
+ category: 'Best Practices',
17
+ description: 'Enforces a maximum number assertion calls in a test body',
18
+ recommended: false
19
+ },
20
+ messages: {
21
+ exceededMaxAssertion: 'Too many assertion calls ({{ count }}). Maximum allowed is {{ max }}.'
22
+ },
23
+ type: 'suggestion',
24
+ schema: [{
25
+ type: 'object',
26
+ properties: {
27
+ max: {
28
+ type: 'integer',
29
+ minimum: 1
30
+ }
31
+ },
32
+ additionalProperties: false
33
+ }]
34
+ },
35
+ defaultOptions: [{
36
+ max: 5
37
+ }],
38
+
39
+ create(context, [{
40
+ max
41
+ }]) {
42
+ let count = 0;
43
+
44
+ const onFunctionExpressionEnter = node => {
45
+ var _node$parent;
46
+
47
+ const isTestFn = ((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) !== _utils.AST_NODE_TYPES.CallExpression || (0, _utils2.isTypeOfJestFnCall)(node.parent, context, ['test']);
48
+
49
+ if (isTestFn) {
50
+ count = 0;
51
+ }
52
+ };
53
+
54
+ return {
55
+ FunctionExpression: onFunctionExpressionEnter,
56
+ ArrowFunctionExpression: onFunctionExpressionEnter,
57
+
58
+ CallExpression(node) {
59
+ if (!(0, _utils2.isExpectCall)(node)) {
60
+ return;
61
+ }
62
+
63
+ count += 1;
64
+
65
+ if (count > max) {
66
+ context.report({
67
+ node,
68
+ messageId: 'exceededMaxAssertion',
69
+ data: {
70
+ count,
71
+ max
72
+ }
73
+ });
74
+ }
75
+ }
76
+
77
+ };
78
+ }
79
+
80
+ });
81
+
82
+ exports.default = _default;
@@ -108,7 +108,10 @@ var _default = (0, _utils2.createRule)({
108
108
  return;
109
109
  }
110
110
 
111
- const preferredMatcher = determineMatcher(comparison.operator, (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]).value === !!modifier);
111
+ const negation = modifier !== null && modifier !== void 0 && modifier.negation ? {
112
+ node: modifier.negation
113
+ } : (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils2.ModifierName.not ? modifier : null;
114
+ const preferredMatcher = determineMatcher(comparison.operator, (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]).value === !!negation);
112
115
 
113
116
  if (!preferredMatcher) {
114
117
  return;
@@ -116,10 +119,12 @@ var _default = (0, _utils2.createRule)({
116
119
 
117
120
  context.report({
118
121
  fix(fixer) {
119
- const sourceCode = context.getSourceCode();
122
+ const sourceCode = context.getSourceCode(); // preserve the existing modifier if it's not a negation
123
+
124
+ const modifierText = modifier && (modifier === null || modifier === void 0 ? void 0 : modifier.node) !== (negation === null || negation === void 0 ? void 0 : negation.node) ? `.${modifier.name}` : '';
120
125
  return [// replace the comparison argument with the left-hand side of the comparison
121
126
  fixer.replaceText(comparison, sourceCode.getText(comparison.left)), // replace the current matcher & modifier with the preferred matcher
122
- fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], `.${preferredMatcher}`), // replace the matcher argument with the right-hand side of the comparison
127
+ fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], `${modifierText}.${preferredMatcher}`), // replace the matcher argument with the right-hand side of the comparison
123
128
  fixer.replaceText(matcher.arguments[0], sourceCode.getText(comparison.right))];
124
129
  },
125
130
 
@@ -127,7 +132,7 @@ var _default = (0, _utils2.createRule)({
127
132
  data: {
128
133
  preferredMatcher
129
134
  },
130
- node: (modifier || matcher).node.property
135
+ node: (negation || matcher).node.property
131
136
  });
132
137
  }
133
138
 
@@ -64,16 +64,26 @@ var _default = (0, _utils2.createRule)({
64
64
  return;
65
65
  }
66
66
 
67
- const matcherValue = (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]).value; // we need to negate the expectation if the current expected
67
+ const matcherValue = (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]).value;
68
+ const negation = modifier !== null && modifier !== void 0 && modifier.negation ? {
69
+ node: modifier.negation
70
+ } : (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils2.ModifierName.not ? modifier : null; // we need to negate the expectation if the current expected
68
71
  // value is itself negated by the "not" modifier
69
72
 
70
- const addNotModifier = (comparison.operator === '!==' ? !matcherValue : matcherValue) === !!modifier;
73
+ const addNotModifier = (comparison.operator === '!==' ? !matcherValue : matcherValue) === !!negation;
71
74
 
72
75
  const buildFixer = equalityMatcher => fixer => {
73
- const sourceCode = context.getSourceCode();
76
+ const sourceCode = context.getSourceCode(); // preserve the existing modifier if it's not a negation
77
+
78
+ let modifierText = modifier && (modifier === null || modifier === void 0 ? void 0 : modifier.node) !== (negation === null || negation === void 0 ? void 0 : negation.node) ? `.${modifier.name}` : '';
79
+
80
+ if (addNotModifier) {
81
+ modifierText += `.${_utils2.ModifierName.not}`;
82
+ }
83
+
74
84
  return [// replace the comparison argument with the left-hand side of the comparison
75
85
  fixer.replaceText(comparison, sourceCode.getText(comparison.left)), // replace the current matcher & modifier with the preferred matcher
76
- fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], addNotModifier ? `.${_utils2.ModifierName.not}.${equalityMatcher}` : `.${equalityMatcher}`), // replace the matcher argument with the right-hand side of the comparison
86
+ fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], `${modifierText}.${equalityMatcher}`), // replace the matcher argument with the right-hand side of the comparison
77
87
  fixer.replaceText(matcher.arguments[0], sourceCode.getText(comparison.right))];
78
88
  };
79
89
 
@@ -86,7 +96,7 @@ var _default = (0, _utils2.createRule)({
86
96
  },
87
97
  fix: buildFixer(equalityMatcher)
88
98
  })),
89
- node: (modifier || matcher).node.property
99
+ node: (negation || matcher).node.property
90
100
  });
91
101
  }
92
102
 
@@ -60,7 +60,9 @@ var _default = (0, _utils.createRule)({
60
60
  name: __filename,
61
61
  meta: {
62
62
  messages: {
63
+ // eslint-disable-next-line eslint-plugin/no-unused-message-ids
63
64
  unbound: DEFAULT_MESSAGE,
65
+ // eslint-disable-next-line eslint-plugin/no-unused-message-ids
64
66
  unboundWithoutThisAnnotation: DEFAULT_MESSAGE
65
67
  },
66
68
  schema: [],
@@ -68,7 +70,7 @@ var _default = (0, _utils.createRule)({
68
70
  ...(baseRule === null || baseRule === void 0 ? void 0 : baseRule.meta),
69
71
  docs: {
70
72
  category: 'Best Practices',
71
- description: 'Enforces unbound methods are called with their expected scope',
73
+ description: 'Enforce unbound methods are called with their expected scope',
72
74
  requiresTypeChecking: true,
73
75
  ...(baseRule === null || baseRule === void 0 ? void 0 : baseRule.meta.docs),
74
76
  recommended: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-jest",
3
- "version": "26.5.1",
3
+ "version": "26.6.0",
4
4
  "description": "ESLint rules for Jest",
5
5
  "keywords": [
6
6
  "eslint",
@@ -104,12 +104,12 @@
104
104
  "eslint-config-prettier": "^8.3.0",
105
105
  "eslint-plugin-eslint-comments": "^3.1.2",
106
106
  "eslint-plugin-eslint-config": "^2.0.0",
107
- "eslint-plugin-eslint-plugin": "^4.0.1",
107
+ "eslint-plugin-eslint-plugin": "^5.0.0",
108
108
  "eslint-plugin-import": "^2.25.1",
109
109
  "eslint-plugin-node": "^11.0.0",
110
110
  "eslint-plugin-prettier": "^3.4.1",
111
- "eslint-remote-tester": "^2.1.3",
112
- "eslint-remote-tester-repositories": "^0.0.5",
111
+ "eslint-remote-tester": "^3.0.0",
112
+ "eslint-remote-tester-repositories": "~0.0.5",
113
113
  "husky": "^7.0.2",
114
114
  "is-ci": "^3.0.0",
115
115
  "jest": "^28.0.0",
@@ -156,9 +156,7 @@
156
156
  ]
157
157
  },
158
158
  "resolutions": {
159
- "@semantic-release/npm/npm": "7.20.6",
160
- "@typescript-eslint/experimental-utils": "^5.0.0",
161
- "fsevents/node-gyp": "^7.0.0"
159
+ "@typescript-eslint/experimental-utils": "^5.0.0"
162
160
  },
163
161
  "packageManager": "yarn@3.2.1"
164
162
  }