eslint-plugin-jest 26.7.0 → 26.8.7
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 +9 -1
- package/lib/rules/max-expects.js +10 -4
- package/lib/rules/no-alias-methods.js +7 -10
- package/lib/rules/no-conditional-expect.js +9 -3
- package/lib/rules/no-interpolation-in-snapshots.js +4 -12
- package/lib/rules/no-large-snapshots.js +5 -13
- package/lib/rules/no-restricted-matchers.js +26 -48
- package/lib/rules/no-standalone-expect.js +11 -5
- package/lib/rules/prefer-called-with.js +12 -10
- package/lib/rules/prefer-comparison-matcher.js +26 -33
- package/lib/rules/prefer-equality-matcher.js +28 -35
- package/lib/rules/prefer-expect-assertions.js +88 -71
- package/lib/rules/prefer-expect-resolves.js +18 -4
- package/lib/rules/prefer-mock-promise-shorthand.js +1 -1
- package/lib/rules/prefer-snapshot-hint.js +18 -21
- package/lib/rules/prefer-strict-equal.js +7 -5
- package/lib/rules/prefer-to-be.js +28 -37
- package/lib/rules/prefer-to-contain.js +25 -30
- package/lib/rules/prefer-to-have-length.js +16 -8
- package/lib/rules/require-to-throw-message.js +8 -8
- package/lib/rules/unbound-method.js +16 -33
- package/lib/rules/utils/index.js +0 -13
- package/lib/rules/utils/misc.js +64 -3
- package/lib/rules/utils/parseJestFnCall.js +132 -21
- package/lib/rules/valid-expect-in-promise.js +14 -37
- package/lib/rules/valid-expect.js +72 -60
- package/package.json +25 -29
- package/lib/rules/utils/parseExpectCall.js +0 -145
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<a href="https://eslint.org/">
|
|
3
|
-
<img
|
|
3
|
+
<img height="150" src="https://eslint.org/assets/images/logo/eslint-logo-color.svg">
|
|
4
4
|
</a>
|
|
5
5
|
<a href="https://facebook.github.io/jest/">
|
|
6
6
|
<img width="150" height="150" vspace="" hspace="25" src="https://jestjs.io/img/jest.png">
|
|
@@ -282,6 +282,14 @@ as it extends the original `unbound-method` rule from that plugin.
|
|
|
282
282
|
|
|
283
283
|
## Related Projects
|
|
284
284
|
|
|
285
|
+
### eslint-plugin-jest-extended
|
|
286
|
+
|
|
287
|
+
This is a sister plugin to `eslint-plugin-jest` that provides support for the
|
|
288
|
+
matchers provided by
|
|
289
|
+
[`jest-extended`](https://github.com/jest-community/jest-extended).
|
|
290
|
+
|
|
291
|
+
https://github.com/jest-community/eslint-plugin-jest-extended
|
|
292
|
+
|
|
285
293
|
### eslint-plugin-jest-formatting
|
|
286
294
|
|
|
287
295
|
This project aims to provide formatting rules (auto-fixable where possible) to
|
package/lib/rules/max-expects.js
CHANGED
|
@@ -41,7 +41,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
41
41
|
}]) {
|
|
42
42
|
let count = 0;
|
|
43
43
|
|
|
44
|
-
const
|
|
44
|
+
const maybeResetCount = node => {
|
|
45
45
|
var _node$parent;
|
|
46
46
|
|
|
47
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']);
|
|
@@ -52,11 +52,17 @@ var _default = (0, _utils2.createRule)({
|
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
return {
|
|
55
|
-
FunctionExpression:
|
|
56
|
-
|
|
55
|
+
FunctionExpression: maybeResetCount,
|
|
56
|
+
'FunctionExpression:exit': maybeResetCount,
|
|
57
|
+
ArrowFunctionExpression: maybeResetCount,
|
|
58
|
+
'ArrowFunctionExpression:exit': maybeResetCount,
|
|
57
59
|
|
|
58
60
|
CallExpression(node) {
|
|
59
|
-
|
|
61
|
+
var _jestFnCall$head$node;
|
|
62
|
+
|
|
63
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
64
|
+
|
|
65
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect' || ((_jestFnCall$head$node = jestFnCall.head.node.parent) === null || _jestFnCall$head$node === void 0 ? void 0 : _jestFnCall$head$node.type) === _utils.AST_NODE_TYPES.MemberExpression) {
|
|
60
66
|
return;
|
|
61
67
|
}
|
|
62
68
|
|
|
@@ -41,19 +41,16 @@ var _default = (0, _utils.createRule)({
|
|
|
41
41
|
};
|
|
42
42
|
return {
|
|
43
43
|
CallExpression(node) {
|
|
44
|
-
|
|
44
|
+
const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
|
|
45
|
+
|
|
46
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
|
|
45
47
|
return;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
const {
|
|
49
51
|
matcher
|
|
50
|
-
} =
|
|
51
|
-
|
|
52
|
-
if (!matcher) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const alias = matcher.name;
|
|
52
|
+
} = jestFnCall;
|
|
53
|
+
const alias = (0, _utils.getAccessorValue)(matcher);
|
|
57
54
|
|
|
58
55
|
if (alias in methodNames) {
|
|
59
56
|
const canonical = methodNames[alias];
|
|
@@ -63,8 +60,8 @@ var _default = (0, _utils.createRule)({
|
|
|
63
60
|
alias,
|
|
64
61
|
canonical
|
|
65
62
|
},
|
|
66
|
-
node: matcher
|
|
67
|
-
fix: fixer => [(0, _utils.replaceAccessorFixer)(fixer, matcher
|
|
63
|
+
node: matcher,
|
|
64
|
+
fix: fixer => [(0, _utils.replaceAccessorFixer)(fixer, matcher, canonical)]
|
|
68
65
|
});
|
|
69
66
|
}
|
|
70
67
|
}
|
|
@@ -47,7 +47,13 @@ var _default = (0, _utils2.createRule)({
|
|
|
47
47
|
},
|
|
48
48
|
|
|
49
49
|
CallExpression(node) {
|
|
50
|
-
|
|
50
|
+
var _parseJestFnCall;
|
|
51
|
+
|
|
52
|
+
const {
|
|
53
|
+
type: jestFnCallType
|
|
54
|
+
} = (_parseJestFnCall = (0, _utils2.parseJestFnCall)(node, context)) !== null && _parseJestFnCall !== void 0 ? _parseJestFnCall : {};
|
|
55
|
+
|
|
56
|
+
if (jestFnCallType === 'test') {
|
|
51
57
|
inTestCase = true;
|
|
52
58
|
}
|
|
53
59
|
|
|
@@ -55,14 +61,14 @@ var _default = (0, _utils2.createRule)({
|
|
|
55
61
|
inPromiseCatch = true;
|
|
56
62
|
}
|
|
57
63
|
|
|
58
|
-
if (inTestCase &&
|
|
64
|
+
if (inTestCase && jestFnCallType === 'expect' && conditionalDepth > 0) {
|
|
59
65
|
context.report({
|
|
60
66
|
messageId: 'conditionalExpect',
|
|
61
67
|
node
|
|
62
68
|
});
|
|
63
69
|
}
|
|
64
70
|
|
|
65
|
-
if (inPromiseCatch &&
|
|
71
|
+
if (inPromiseCatch && jestFnCallType === 'expect') {
|
|
66
72
|
context.report({
|
|
67
73
|
messageId: 'conditionalExpect',
|
|
68
74
|
node
|
|
@@ -28,23 +28,15 @@ var _default = (0, _utils2.createRule)({
|
|
|
28
28
|
create(context) {
|
|
29
29
|
return {
|
|
30
30
|
CallExpression(node) {
|
|
31
|
-
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
31
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
matcher
|
|
37
|
-
} = (0, _utils2.parseExpectCall)(node);
|
|
38
|
-
|
|
39
|
-
if (!matcher) {
|
|
33
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
|
|
40
34
|
return;
|
|
41
35
|
}
|
|
42
36
|
|
|
43
|
-
if (['toMatchInlineSnapshot', 'toThrowErrorMatchingInlineSnapshot'].includes(
|
|
44
|
-
var _matcher$arguments;
|
|
45
|
-
|
|
37
|
+
if (['toMatchInlineSnapshot', 'toThrowErrorMatchingInlineSnapshot'].includes((0, _utils2.getAccessorValue)(jestFnCall.matcher))) {
|
|
46
38
|
// Check all since the optional 'propertyMatchers' argument might be present
|
|
47
|
-
|
|
39
|
+
jestFnCall.args.forEach(argument => {
|
|
48
40
|
if (argument.type === _utils.AST_NODE_TYPES.TemplateLiteral && argument.expressions.length > 0) {
|
|
49
41
|
context.report({
|
|
50
42
|
messageId: 'noInterpolation',
|
|
@@ -26,7 +26,7 @@ const reportOnViolation = (context, node, {
|
|
|
26
26
|
|
|
27
27
|
let isAllowed = false;
|
|
28
28
|
|
|
29
|
-
if (node.type === _utils.AST_NODE_TYPES.ExpressionStatement && 'left' in node.expression && (0, _utils2.
|
|
29
|
+
if (node.type === _utils.AST_NODE_TYPES.ExpressionStatement && 'left' in node.expression && node.expression.left.type === _utils.AST_NODE_TYPES.MemberExpression && (0, _utils2.isSupportedAccessor)(node.expression.left.property)) {
|
|
30
30
|
const fileName = context.getFilename();
|
|
31
31
|
const allowedSnapshotsInFile = allowedSnapshots[fileName];
|
|
32
32
|
|
|
@@ -100,24 +100,16 @@ var _default = (0, _utils2.createRule)({
|
|
|
100
100
|
|
|
101
101
|
return {
|
|
102
102
|
CallExpression(node) {
|
|
103
|
-
|
|
103
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
104
104
|
|
|
105
|
-
if (
|
|
105
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
|
|
106
106
|
return;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
matcher
|
|
111
|
-
} = (0, _utils2.parseExpectCall)(node);
|
|
112
|
-
|
|
113
|
-
if ((matcher === null || matcher === void 0 ? void 0 : matcher.node.parent.type) !== _utils.AST_NODE_TYPES.CallExpression) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (['toMatchInlineSnapshot', 'toThrowErrorMatchingInlineSnapshot'].includes(matcher.name) && (_matcher$arguments = matcher.arguments) !== null && _matcher$arguments !== void 0 && _matcher$arguments.length) {
|
|
109
|
+
if (['toMatchInlineSnapshot', 'toThrowErrorMatchingInlineSnapshot'].includes((0, _utils2.getAccessorValue)(jestFnCall.matcher)) && jestFnCall.args.length) {
|
|
118
110
|
var _options$inlineMaxSiz;
|
|
119
111
|
|
|
120
|
-
reportOnViolation(context,
|
|
112
|
+
reportOnViolation(context, jestFnCall.args[0], { ...options,
|
|
121
113
|
maxSize: (_options$inlineMaxSiz = options.inlineMaxSize) !== null && _options$inlineMaxSiz !== void 0 ? _options$inlineMaxSiz : options.maxSize
|
|
122
114
|
});
|
|
123
115
|
}
|
|
@@ -30,65 +30,43 @@ var _default = (0, _utils.createRule)({
|
|
|
30
30
|
defaultOptions: [{}],
|
|
31
31
|
|
|
32
32
|
create(context, [restrictedChains]) {
|
|
33
|
-
const reportIfRestricted = (loc, chain) => {
|
|
34
|
-
if (!(chain in restrictedChains)) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const message = restrictedChains[chain];
|
|
39
|
-
context.report({
|
|
40
|
-
messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
|
|
41
|
-
data: {
|
|
42
|
-
message,
|
|
43
|
-
chain
|
|
44
|
-
},
|
|
45
|
-
loc
|
|
46
|
-
});
|
|
47
|
-
return true;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
33
|
return {
|
|
51
34
|
CallExpression(node) {
|
|
52
|
-
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
35
|
+
const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
|
|
55
36
|
|
|
56
|
-
|
|
57
|
-
matcher,
|
|
58
|
-
modifier
|
|
59
|
-
} = (0, _utils.parseExpectCall)(node);
|
|
60
|
-
|
|
61
|
-
if (matcher && reportIfRestricted(matcher.node.property.loc, matcher.name)) {
|
|
37
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
|
|
62
38
|
return;
|
|
63
39
|
}
|
|
64
40
|
|
|
65
|
-
|
|
66
|
-
if (reportIfRestricted(modifier.node.property.loc, modifier.name)) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
41
|
+
const permutations = [jestFnCall.members];
|
|
69
42
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
end: modifier.negation.property.loc.end
|
|
74
|
-
}, `${modifier.name}.not`)) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
43
|
+
if (jestFnCall.members.length > 2) {
|
|
44
|
+
permutations.push([jestFnCall.members[0], jestFnCall.members[1]]);
|
|
45
|
+
permutations.push([jestFnCall.members[1], jestFnCall.members[2]]);
|
|
78
46
|
}
|
|
79
47
|
|
|
80
|
-
if (
|
|
81
|
-
|
|
48
|
+
if (jestFnCall.members.length > 1) {
|
|
49
|
+
permutations.push(...jestFnCall.members.map(nod => [nod]));
|
|
50
|
+
}
|
|
82
51
|
|
|
83
|
-
|
|
84
|
-
|
|
52
|
+
for (const permutation of permutations) {
|
|
53
|
+
const chain = permutation.map(nod => (0, _utils.getAccessorValue)(nod)).join('.');
|
|
54
|
+
|
|
55
|
+
if (chain in restrictedChains) {
|
|
56
|
+
const message = restrictedChains[chain];
|
|
57
|
+
context.report({
|
|
58
|
+
messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
|
|
59
|
+
data: {
|
|
60
|
+
message,
|
|
61
|
+
chain
|
|
62
|
+
},
|
|
63
|
+
loc: {
|
|
64
|
+
start: permutation[0].loc.start,
|
|
65
|
+
end: permutation[permutation.length - 1].loc.end
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
break;
|
|
85
69
|
}
|
|
86
|
-
|
|
87
|
-
chain += `.${matcher.name}`;
|
|
88
|
-
reportIfRestricted({
|
|
89
|
-
start: modifier.node.property.loc.start,
|
|
90
|
-
end: matcher.node.property.loc.end
|
|
91
|
-
}, chain);
|
|
92
70
|
}
|
|
93
71
|
}
|
|
94
72
|
|
|
@@ -73,11 +73,17 @@ var _default = (0, _utils2.createRule)({
|
|
|
73
73
|
|
|
74
74
|
const isCustomTestBlockFunction = node => additionalTestBlockFunctions.includes((0, _utils2.getNodeName)(node) || '');
|
|
75
75
|
|
|
76
|
-
const isTestBlock = node => (0, _utils2.isTypeOfJestFnCall)(node, context, ['test']) || isCustomTestBlockFunction(node);
|
|
77
|
-
|
|
78
76
|
return {
|
|
79
77
|
CallExpression(node) {
|
|
80
|
-
|
|
78
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
79
|
+
|
|
80
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'expect') {
|
|
81
|
+
var _jestFnCall$head$node;
|
|
82
|
+
|
|
83
|
+
if (((_jestFnCall$head$node = jestFnCall.head.node.parent) === null || _jestFnCall$head$node === void 0 ? void 0 : _jestFnCall$head$node.type) === _utils.AST_NODE_TYPES.MemberExpression && jestFnCall.members.length === 1 && !['assertions', 'hasAssertions'].includes((0, _utils2.getAccessorValue)(jestFnCall.members[0]))) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
const parent = callStack[callStack.length - 1];
|
|
82
88
|
|
|
83
89
|
if (!parent || parent === _utils2.DescribeAlias.describe) {
|
|
@@ -90,7 +96,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
90
96
|
return;
|
|
91
97
|
}
|
|
92
98
|
|
|
93
|
-
if (
|
|
99
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'test' || isCustomTestBlockFunction(node)) {
|
|
94
100
|
callStack.push('test');
|
|
95
101
|
}
|
|
96
102
|
|
|
@@ -102,7 +108,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
102
108
|
'CallExpression:exit'(node) {
|
|
103
109
|
const top = callStack[callStack.length - 1];
|
|
104
110
|
|
|
105
|
-
if (top === 'test' &&
|
|
111
|
+
if (top === 'test' && ((0, _utils2.isTypeOfJestFnCall)(node, context, ['test']) || isCustomTestBlockFunction(node)) && node.callee.type !== _utils.AST_NODE_TYPES.MemberExpression || top === 'template' && node.callee.type === _utils.AST_NODE_TYPES.TaggedTemplateExpression) {
|
|
106
112
|
callStack.pop();
|
|
107
113
|
}
|
|
108
114
|
},
|
|
@@ -26,26 +26,28 @@ var _default = (0, _utils.createRule)({
|
|
|
26
26
|
create(context) {
|
|
27
27
|
return {
|
|
28
28
|
CallExpression(node) {
|
|
29
|
-
|
|
29
|
+
const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
|
|
30
|
+
|
|
31
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
|
|
30
32
|
return;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
modifier,
|
|
35
|
-
matcher
|
|
36
|
-
} = (0, _utils.parseExpectCall)(node);
|
|
37
|
-
|
|
38
|
-
if (!matcher || (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.not || modifier !== null && modifier !== void 0 && modifier.negation) {
|
|
35
|
+
if (jestFnCall.modifiers.some(nod => (0, _utils.getAccessorValue)(nod) === 'not')) {
|
|
39
36
|
return;
|
|
40
37
|
}
|
|
41
38
|
|
|
42
|
-
|
|
39
|
+
const {
|
|
40
|
+
matcher
|
|
41
|
+
} = jestFnCall;
|
|
42
|
+
const matcherName = (0, _utils.getAccessorValue)(matcher);
|
|
43
|
+
|
|
44
|
+
if (['toBeCalled', 'toHaveBeenCalled'].includes(matcherName)) {
|
|
43
45
|
context.report({
|
|
44
46
|
data: {
|
|
45
|
-
matcherName
|
|
47
|
+
matcherName
|
|
46
48
|
},
|
|
47
49
|
messageId: 'preferCalledWith',
|
|
48
|
-
node: matcher
|
|
50
|
+
node: matcher
|
|
49
51
|
});
|
|
50
52
|
}
|
|
51
53
|
}
|
|
@@ -9,22 +9,6 @@ var _utils = require("@typescript-eslint/utils");
|
|
|
9
9
|
|
|
10
10
|
var _utils2 = require("./utils");
|
|
11
11
|
|
|
12
|
-
const isBooleanLiteral = node => node.type === _utils.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, _utils2.isParsedEqualityMatcherCall)(matcher) && isBooleanLiteral((0, _utils2.followTypeAssertionChain)(matcher.arguments[0]));
|
|
27
|
-
|
|
28
12
|
const isString = node => {
|
|
29
13
|
return (0, _utils2.isStringNode)(node) || node.type === _utils.AST_NODE_TYPES.TemplateLiteral;
|
|
30
14
|
};
|
|
@@ -91,27 +75,36 @@ var _default = (0, _utils2.createRule)({
|
|
|
91
75
|
create(context) {
|
|
92
76
|
return {
|
|
93
77
|
CallExpression(node) {
|
|
94
|
-
|
|
78
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
79
|
+
|
|
80
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect' || jestFnCall.args.length === 0) {
|
|
95
81
|
return;
|
|
96
82
|
}
|
|
97
83
|
|
|
98
84
|
const {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
85
|
+
parent: expect
|
|
86
|
+
} = jestFnCall.head.node;
|
|
87
|
+
|
|
88
|
+
if ((expect === null || expect === void 0 ? void 0 : expect.type) !== _utils.AST_NODE_TYPES.CallExpression) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const {
|
|
93
|
+
arguments: [comparison],
|
|
94
|
+
range: [, expectCallEnd]
|
|
95
|
+
} = expect;
|
|
96
|
+
const {
|
|
97
|
+
matcher
|
|
98
|
+
} = jestFnCall;
|
|
99
|
+
const matcherArg = (0, _utils2.getFirstMatcherArg)(jestFnCall);
|
|
106
100
|
|
|
107
|
-
if (
|
|
101
|
+
if ((comparison === null || comparison === void 0 ? void 0 : comparison.type) !== _utils.AST_NODE_TYPES.BinaryExpression || isComparingToString(comparison) || !_utils2.EqualityMatcher.hasOwnProperty((0, _utils2.getAccessorValue)(matcher)) || !(0, _utils2.isBooleanLiteral)(matcherArg)) {
|
|
108
102
|
return;
|
|
109
103
|
}
|
|
110
104
|
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const preferredMatcher = determineMatcher(comparison.operator, (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]).value === !!negation);
|
|
105
|
+
const [modifier] = jestFnCall.modifiers;
|
|
106
|
+
const hasNot = jestFnCall.modifiers.some(nod => (0, _utils2.getAccessorValue)(nod) === 'not');
|
|
107
|
+
const preferredMatcher = determineMatcher(comparison.operator, matcherArg.value === hasNot);
|
|
115
108
|
|
|
116
109
|
if (!preferredMatcher) {
|
|
117
110
|
return;
|
|
@@ -121,18 +114,18 @@ var _default = (0, _utils2.createRule)({
|
|
|
121
114
|
fix(fixer) {
|
|
122
115
|
const sourceCode = context.getSourceCode(); // preserve the existing modifier if it's not a negation
|
|
123
116
|
|
|
124
|
-
const modifierText = modifier && (
|
|
117
|
+
const modifierText = modifier && (0, _utils2.getAccessorValue)(modifier) !== 'not' ? `.${(0, _utils2.getAccessorValue)(modifier)}` : '';
|
|
125
118
|
return [// replace the comparison argument with the left-hand side of the comparison
|
|
126
119
|
fixer.replaceText(comparison, sourceCode.getText(comparison.left)), // replace the current matcher & modifier with the preferred matcher
|
|
127
|
-
fixer.replaceTextRange([expectCallEnd, matcher.
|
|
128
|
-
fixer.replaceText(
|
|
120
|
+
fixer.replaceTextRange([expectCallEnd, matcher.parent.range[1]], `${modifierText}.${preferredMatcher}`), // replace the matcher argument with the right-hand side of the comparison
|
|
121
|
+
fixer.replaceText(matcherArg, sourceCode.getText(comparison.right))];
|
|
129
122
|
},
|
|
130
123
|
|
|
131
124
|
messageId: 'useToBeComparison',
|
|
132
125
|
data: {
|
|
133
126
|
preferredMatcher
|
|
134
127
|
},
|
|
135
|
-
node: matcher
|
|
128
|
+
node: matcher
|
|
136
129
|
});
|
|
137
130
|
}
|
|
138
131
|
|
|
@@ -9,22 +9,6 @@ var _utils = require("@typescript-eslint/utils");
|
|
|
9
9
|
|
|
10
10
|
var _utils2 = require("./utils");
|
|
11
11
|
|
|
12
|
-
const isBooleanLiteral = node => node.type === _utils.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, _utils2.isParsedEqualityMatcherCall)(matcher) && isBooleanLiteral((0, _utils2.followTypeAssertionChain)(matcher.arguments[0]));
|
|
27
|
-
|
|
28
12
|
var _default = (0, _utils2.createRule)({
|
|
29
13
|
name: __filename,
|
|
30
14
|
meta: {
|
|
@@ -47,35 +31,44 @@ var _default = (0, _utils2.createRule)({
|
|
|
47
31
|
create(context) {
|
|
48
32
|
return {
|
|
49
33
|
CallExpression(node) {
|
|
50
|
-
|
|
34
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
35
|
+
|
|
36
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect' || jestFnCall.args.length === 0) {
|
|
51
37
|
return;
|
|
52
38
|
}
|
|
53
39
|
|
|
54
40
|
const {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
41
|
+
parent: expect
|
|
42
|
+
} = jestFnCall.head.node;
|
|
43
|
+
|
|
44
|
+
if ((expect === null || expect === void 0 ? void 0 : expect.type) !== _utils.AST_NODE_TYPES.CallExpression) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const {
|
|
49
|
+
arguments: [comparison],
|
|
50
|
+
range: [, expectCallEnd]
|
|
51
|
+
} = expect;
|
|
52
|
+
const {
|
|
53
|
+
matcher
|
|
54
|
+
} = jestFnCall;
|
|
55
|
+
const matcherArg = (0, _utils2.getFirstMatcherArg)(jestFnCall);
|
|
56
|
+
|
|
57
|
+
if ((comparison === null || comparison === void 0 ? void 0 : comparison.type) !== _utils.AST_NODE_TYPES.BinaryExpression || comparison.operator !== '===' && comparison.operator !== '!==' || !_utils2.EqualityMatcher.hasOwnProperty((0, _utils2.getAccessorValue)(matcher)) || !(0, _utils2.isBooleanLiteral)(matcherArg)) {
|
|
64
58
|
return;
|
|
65
59
|
}
|
|
66
60
|
|
|
67
|
-
const matcherValue =
|
|
68
|
-
const
|
|
69
|
-
|
|
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
|
|
61
|
+
const matcherValue = matcherArg.value;
|
|
62
|
+
const [modifier] = jestFnCall.modifiers;
|
|
63
|
+
const hasNot = jestFnCall.modifiers.some(nod => (0, _utils2.getAccessorValue)(nod) === 'not'); // we need to negate the expectation if the current expected
|
|
71
64
|
// value is itself negated by the "not" modifier
|
|
72
65
|
|
|
73
|
-
const addNotModifier = (comparison.operator === '!==' ? !matcherValue : matcherValue) ===
|
|
66
|
+
const addNotModifier = (comparison.operator === '!==' ? !matcherValue : matcherValue) === hasNot;
|
|
74
67
|
|
|
75
68
|
const buildFixer = equalityMatcher => fixer => {
|
|
76
69
|
const sourceCode = context.getSourceCode(); // preserve the existing modifier if it's not a negation
|
|
77
70
|
|
|
78
|
-
let modifierText = modifier && (
|
|
71
|
+
let modifierText = modifier && (0, _utils2.getAccessorValue)(modifier) !== 'not' ? `.${(0, _utils2.getAccessorValue)(modifier)}` : '';
|
|
79
72
|
|
|
80
73
|
if (addNotModifier) {
|
|
81
74
|
modifierText += `.${_utils2.ModifierName.not}`;
|
|
@@ -83,8 +76,8 @@ var _default = (0, _utils2.createRule)({
|
|
|
83
76
|
|
|
84
77
|
return [// replace the comparison argument with the left-hand side of the comparison
|
|
85
78
|
fixer.replaceText(comparison, sourceCode.getText(comparison.left)), // replace the current matcher & modifier with the preferred matcher
|
|
86
|
-
fixer.replaceTextRange([expectCallEnd, matcher.
|
|
87
|
-
fixer.replaceText(
|
|
79
|
+
fixer.replaceTextRange([expectCallEnd, matcher.parent.range[1]], `${modifierText}.${equalityMatcher}`), // replace the matcher argument with the right-hand side of the comparison
|
|
80
|
+
fixer.replaceText(matcherArg, sourceCode.getText(comparison.right))];
|
|
88
81
|
};
|
|
89
82
|
|
|
90
83
|
context.report({
|
|
@@ -96,7 +89,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
96
89
|
},
|
|
97
90
|
fix: buildFixer(equalityMatcher)
|
|
98
91
|
})),
|
|
99
|
-
node: matcher
|
|
92
|
+
node: matcher
|
|
100
93
|
});
|
|
101
94
|
}
|
|
102
95
|
|