eslint-plugin-jest 25.6.0 → 25.7.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/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # [25.7.0](https://github.com/jest-community/eslint-plugin-jest/compare/v25.6.0...v25.7.0) (2022-01-15)
2
+
3
+
4
+ ### Features
5
+
6
+ * create `prefer-equality-matcher` rule ([#1016](https://github.com/jest-community/eslint-plugin-jest/issues/1016)) ([341353b](https://github.com/jest-community/eslint-plugin-jest/commit/341353bc7d57685cc5e0b31501d6ca336a0dbaf0))
7
+ * **valid-expect:** support `asyncMatchers` option and default to `jest-extended` matchers ([#1018](https://github.com/jest-community/eslint-plugin-jest/issues/1018)) ([c82205a](https://github.com/jest-community/eslint-plugin-jest/commit/c82205a73a4e8de315a2ad4d413b146e27c14a34))
8
+
1
9
  # [25.6.0](https://github.com/jest-community/eslint-plugin-jest/compare/v25.5.0...v25.6.0) (2022-01-15)
2
10
 
3
11
 
package/README.md CHANGED
@@ -178,6 +178,7 @@ installations requiring long-term consistency.
178
178
  | [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests | | |
179
179
  | [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` | | |
180
180
  | [prefer-comparison-matcher](docs/rules/prefer-comparison-matcher.md) | Suggest using the built-in comparison matchers | | ![fixable][] |
181
+ | [prefer-equality-matcher](docs/rules/prefer-equality-matcher.md) | Suggest using the built-in equality matchers | | ![suggest][] |
181
182
  | [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | ![suggest][] |
182
183
  | [prefer-expect-resolves](docs/rules/prefer-expect-resolves.md) | Prefer `await expect(...).resolves` over `expect(await ...)` syntax | | ![fixable][] |
183
184
  | [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md) | Suggest having hooks before any test cases | | |
@@ -0,0 +1,29 @@
1
+ # Suggest using the built-in equality matchers (`prefer-equality-matcher`)
2
+
3
+ Jest has built-in matchers for expecting equality which allow for more readable
4
+ tests and error messages if an expectation fails.
5
+
6
+ ## Rule details
7
+
8
+ This rule checks for _strict_ equality checks (`===` & `!==`) in tests that
9
+ could be replaced with one of the following built-in equality matchers:
10
+
11
+ - `toBe`
12
+ - `toEqual`
13
+ - `toStrictEqual`
14
+
15
+ Examples of **incorrect** code for this rule:
16
+
17
+ ```js
18
+ expect(x === 5).toBe(true);
19
+ expect(name === 'Carl').not.toEqual(true);
20
+ expect(myObj !== thatObj).toStrictEqual(true);
21
+ ```
22
+
23
+ Examples of **correct** code for this rule:
24
+
25
+ ```js
26
+ expect(x).toBe(5);
27
+ expect(name).not.toEqual('Carl');
28
+ expect(myObj).toStrictEqual(thatObj);
29
+ ```
@@ -38,6 +38,11 @@ This rule is enabled by default.
38
38
  type: 'boolean',
39
39
  default: false,
40
40
  },
41
+ asyncMatchers: {
42
+ type: 'array',
43
+ items: { type: 'string' },
44
+ default: ['toResolve', 'toReject'],
45
+ },
41
46
  minArgs: {
42
47
  type: 'number',
43
48
  minimum: 1,
@@ -78,6 +83,14 @@ test('test1', async () => {
78
83
  test('test2', () => expect(Promise.resolve(2)).resolves.toBe(2));
79
84
  ```
80
85
 
86
+ ### `asyncMatchers`
87
+
88
+ Allows specifying which matchers return promises, and so should be considered
89
+ async when checking if an `expect` should be returned or awaited.
90
+
91
+ By default, this has a list of all the async matchers provided by
92
+ `jest-extended` (namely, `toResolve` and `toReject`).
93
+
81
94
  ### `minArgs` & `maxArgs`
82
95
 
83
96
  Enforces the minimum and maximum number of arguments that `expect` can take, and
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _experimentalUtils = require("@typescript-eslint/experimental-utils");
9
+
10
+ var _utils = require("./utils");
11
+
12
+ const isBooleanLiteral = node => node.type === _experimentalUtils.AST_NODE_TYPES.Literal && typeof node.value === 'boolean';
13
+
14
+ /**
15
+ * Checks if the given `ParsedExpectMatcher` is a call to one of the equality matchers,
16
+ * with a boolean literal as the sole argument.
17
+ *
18
+ * @example javascript
19
+ * toBe(true);
20
+ * toEqual(false);
21
+ *
22
+ * @param {ParsedExpectMatcher} matcher
23
+ *
24
+ * @return {matcher is ParsedBooleanEqualityMatcher}
25
+ */
26
+ const isBooleanEqualityMatcher = matcher => (0, _utils.isParsedEqualityMatcherCall)(matcher) && isBooleanLiteral((0, _utils.followTypeAssertionChain)(matcher.arguments[0]));
27
+
28
+ var _default = (0, _utils.createRule)({
29
+ name: __filename,
30
+ meta: {
31
+ docs: {
32
+ category: 'Best Practices',
33
+ description: 'Suggest using the built-in equality matchers',
34
+ recommended: false,
35
+ suggestion: true
36
+ },
37
+ messages: {
38
+ useEqualityMatcher: 'Prefer using one of the equality matchers instead',
39
+ suggestEqualityMatcher: 'Use `{{ equalityMatcher }}`'
40
+ },
41
+ hasSuggestions: true,
42
+ type: 'suggestion',
43
+ schema: []
44
+ },
45
+ defaultOptions: [],
46
+
47
+ create(context) {
48
+ return {
49
+ CallExpression(node) {
50
+ if (!(0, _utils.isExpectCall)(node)) {
51
+ return;
52
+ }
53
+
54
+ const {
55
+ expect: {
56
+ arguments: [comparison],
57
+ range: [, expectCallEnd]
58
+ },
59
+ matcher,
60
+ modifier
61
+ } = (0, _utils.parseExpectCall)(node);
62
+
63
+ if (!matcher || (comparison === null || comparison === void 0 ? void 0 : comparison.type) !== _experimentalUtils.AST_NODE_TYPES.BinaryExpression || comparison.operator !== '===' && comparison.operator !== '!==' || !isBooleanEqualityMatcher(matcher)) {
64
+ return;
65
+ }
66
+
67
+ const matcherValue = (0, _utils.followTypeAssertionChain)(matcher.arguments[0]).value; // we need to negate the expectation if the current expected
68
+ // value is itself negated by the "not" modifier
69
+
70
+ const addNotModifier = (comparison.operator === '!==' ? !matcherValue : matcherValue) === !!modifier;
71
+
72
+ const buildFixer = equalityMatcher => fixer => {
73
+ const sourceCode = context.getSourceCode();
74
+ return [// replace the comparison argument with the left-hand side of the comparison
75
+ 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 ? `.${_utils.ModifierName.not}.${equalityMatcher}` : `.${equalityMatcher}`), // replace the matcher argument with the right-hand side of the comparison
77
+ fixer.replaceText(matcher.arguments[0], sourceCode.getText(comparison.right))];
78
+ };
79
+
80
+ context.report({
81
+ messageId: 'useEqualityMatcher',
82
+ suggest: ['toBe', 'toEqual', 'toStrictEqual'].map(equalityMatcher => ({
83
+ messageId: 'suggestEqualityMatcher',
84
+ data: {
85
+ equalityMatcher
86
+ },
87
+ fix: buildFixer(equalityMatcher)
88
+ })),
89
+ node: (modifier || matcher).node.property
90
+ });
91
+ }
92
+
93
+ };
94
+ }
95
+
96
+ });
97
+
98
+ exports.default = _default;
@@ -71,6 +71,8 @@ const promiseArrayExceptionKey = ({
71
71
  end
72
72
  }) => `${start.line}:${start.column}-${end.line}:${end.column}`;
73
73
 
74
+ const defaultAsyncMatchers = ['toReject', 'toResolve'];
75
+
74
76
  var _default = (0, _utils.createRule)({
75
77
  name: __filename,
76
78
  meta: {
@@ -96,6 +98,12 @@ var _default = (0, _utils.createRule)({
96
98
  type: 'boolean',
97
99
  default: false
98
100
  },
101
+ asyncMatchers: {
102
+ type: 'array',
103
+ items: {
104
+ type: 'string'
105
+ }
106
+ },
99
107
  minArgs: {
100
108
  type: 'number',
101
109
  minimum: 1
@@ -110,12 +118,14 @@ var _default = (0, _utils.createRule)({
110
118
  },
111
119
  defaultOptions: [{
112
120
  alwaysAwait: false,
121
+ asyncMatchers: defaultAsyncMatchers,
113
122
  minArgs: 1,
114
123
  maxArgs: 1
115
124
  }],
116
125
 
117
126
  create(context, [{
118
127
  alwaysAwait,
128
+ asyncMatchers = defaultAsyncMatchers,
119
129
  minArgs = 1,
120
130
  maxArgs = 1
121
131
  }]) {
@@ -225,8 +235,9 @@ var _default = (0, _utils.createRule)({
225
235
  }
226
236
 
227
237
  const parentNode = matcher.node.parent;
238
+ const shouldBeAwaited = modifier && modifier.name !== _utils.ModifierName.not || asyncMatchers.includes(matcher.name);
228
239
 
229
- if (!parentNode.parent || !modifier || modifier.name === _utils.ModifierName.not) {
240
+ if (!parentNode.parent || !shouldBeAwaited) {
230
241
  return;
231
242
  }
232
243
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-jest",
3
- "version": "25.6.0",
3
+ "version": "25.7.0",
4
4
  "description": "Eslint rules for Jest",
5
5
  "keywords": [
6
6
  "eslint",