eslint-plugin-jest 26.7.0 → 26.8.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/lib/rules/max-expects.js +1 -1
- 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 +9 -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 +4 -2
- package/lib/rules/prefer-expect-resolves.js +18 -4
- 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 -31
- package/lib/rules/utils/index.js +0 -13
- package/lib/rules/utils/misc.js +64 -3
- package/lib/rules/utils/parseJestFnCall.js +118 -21
- package/lib/rules/valid-expect-in-promise.js +14 -37
- package/lib/rules/valid-expect.js +72 -60
- package/package.json +24 -28
- package/lib/rules/utils/parseExpectCall.js +0 -145
package/lib/rules/max-expects.js
CHANGED
|
@@ -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,15 @@ 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
|
+
var _parseJestFnCall;
|
|
79
|
+
|
|
80
|
+
const {
|
|
81
|
+
type: jestFnCallType
|
|
82
|
+
} = (_parseJestFnCall = (0, _utils2.parseJestFnCall)(node, context)) !== null && _parseJestFnCall !== void 0 ? _parseJestFnCall : {};
|
|
83
|
+
|
|
84
|
+
if (jestFnCallType === 'expect') {
|
|
81
85
|
const parent = callStack[callStack.length - 1];
|
|
82
86
|
|
|
83
87
|
if (!parent || parent === _utils2.DescribeAlias.describe) {
|
|
@@ -90,7 +94,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
90
94
|
return;
|
|
91
95
|
}
|
|
92
96
|
|
|
93
|
-
if (
|
|
97
|
+
if (jestFnCallType === 'test' || isCustomTestBlockFunction(node)) {
|
|
94
98
|
callStack.push('test');
|
|
95
99
|
}
|
|
96
100
|
|
|
@@ -102,7 +106,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
102
106
|
'CallExpression:exit'(node) {
|
|
103
107
|
const top = callStack[callStack.length - 1];
|
|
104
108
|
|
|
105
|
-
if (top === 'test' &&
|
|
109
|
+
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
110
|
callStack.pop();
|
|
107
111
|
}
|
|
108
112
|
},
|
|
@@ -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
|
|
|
@@ -116,12 +116,14 @@ var _default = (0, _utils2.createRule)({
|
|
|
116
116
|
'ForOfStatement:exit': exitForLoop,
|
|
117
117
|
|
|
118
118
|
CallExpression(node) {
|
|
119
|
-
|
|
119
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
120
|
+
|
|
121
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'test') {
|
|
120
122
|
inTestCaseCall = true;
|
|
121
123
|
return;
|
|
122
124
|
}
|
|
123
125
|
|
|
124
|
-
if ((0
|
|
126
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'expect' && inTestCaseCall) {
|
|
125
127
|
if (inForLoop) {
|
|
126
128
|
hasExpectInLoop = true;
|
|
127
129
|
}
|
|
@@ -27,15 +27,29 @@ var _default = (0, _utils2.createRule)({
|
|
|
27
27
|
defaultOptions: [],
|
|
28
28
|
create: context => ({
|
|
29
29
|
CallExpression(node) {
|
|
30
|
-
const
|
|
30
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
31
31
|
|
|
32
|
-
if ((
|
|
32
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const {
|
|
37
|
+
parent
|
|
38
|
+
} = jestFnCall.head.node;
|
|
39
|
+
|
|
40
|
+
if ((parent === null || parent === void 0 ? void 0 : parent.type) !== _utils.AST_NODE_TYPES.CallExpression) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const [awaitNode] = parent.arguments;
|
|
45
|
+
|
|
46
|
+
if ((awaitNode === null || awaitNode === void 0 ? void 0 : awaitNode.type) === _utils.AST_NODE_TYPES.AwaitExpression) {
|
|
33
47
|
context.report({
|
|
34
|
-
node:
|
|
48
|
+
node: awaitNode,
|
|
35
49
|
messageId: 'expectResolves',
|
|
36
50
|
|
|
37
51
|
fix(fixer) {
|
|
38
|
-
return [fixer.insertTextBefore(
|
|
52
|
+
return [fixer.insertTextBefore(parent, 'await '), fixer.removeRange([awaitNode.range[0], awaitNode.argument.range[0]]), fixer.insertTextAfter(parent, '.resolves')];
|
|
39
53
|
}
|
|
40
54
|
|
|
41
55
|
});
|
|
@@ -8,28 +8,25 @@ exports.default = void 0;
|
|
|
8
8
|
var _utils = require("./utils");
|
|
9
9
|
|
|
10
10
|
const snapshotMatchers = ['toMatchSnapshot', 'toThrowErrorMatchingSnapshot'];
|
|
11
|
+
const snapshotMatcherNames = snapshotMatchers;
|
|
11
12
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const isSnapshotMatcherWithoutHint = matcher => {
|
|
17
|
-
if (!matcher.arguments || matcher.arguments.length === 0) {
|
|
13
|
+
const isSnapshotMatcherWithoutHint = expectFnCall => {
|
|
14
|
+
if (expectFnCall.args.length === 0) {
|
|
18
15
|
return true;
|
|
19
16
|
} // this matcher only supports one argument which is the hint
|
|
20
17
|
|
|
21
18
|
|
|
22
|
-
if (matcher
|
|
23
|
-
return
|
|
19
|
+
if (!(0, _utils.isSupportedAccessor)(expectFnCall.matcher, 'toMatchSnapshot')) {
|
|
20
|
+
return expectFnCall.args.length !== 1;
|
|
24
21
|
} // if we're being passed two arguments,
|
|
25
22
|
// the second one should be the hint
|
|
26
23
|
|
|
27
24
|
|
|
28
|
-
if (
|
|
25
|
+
if (expectFnCall.args.length === 2) {
|
|
29
26
|
return false;
|
|
30
27
|
}
|
|
31
28
|
|
|
32
|
-
const [arg] =
|
|
29
|
+
const [arg] = expectFnCall.args; // the first argument to `toMatchSnapshot` can be _either_ a snapshot hint or
|
|
33
30
|
// an object with asymmetric matchers, so we can't just assume that the first
|
|
34
31
|
// argument is a hint when it's by itself.
|
|
35
32
|
|
|
@@ -67,7 +64,7 @@ var _default = (0, _utils.createRule)({
|
|
|
67
64
|
if (isSnapshotMatcherWithoutHint(snapshotMatcher)) {
|
|
68
65
|
context.report({
|
|
69
66
|
messageId: 'missingHint',
|
|
70
|
-
node: snapshotMatcher.
|
|
67
|
+
node: snapshotMatcher.matcher
|
|
71
68
|
});
|
|
72
69
|
}
|
|
73
70
|
}
|
|
@@ -115,24 +112,24 @@ var _default = (0, _utils.createRule)({
|
|
|
115
112
|
},
|
|
116
113
|
|
|
117
114
|
CallExpression(node) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
115
|
+
const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
|
|
116
|
+
|
|
117
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
|
|
118
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'describe' || (jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'test') {
|
|
119
|
+
depths.push(expressionDepth);
|
|
120
|
+
expressionDepth = 0;
|
|
121
|
+
}
|
|
122
122
|
|
|
123
|
-
if (!(0, _utils.isExpectCall)(node)) {
|
|
124
123
|
return;
|
|
125
124
|
}
|
|
126
125
|
|
|
127
|
-
const
|
|
128
|
-
matcher
|
|
129
|
-
} = (0, _utils.parseExpectCall)(node);
|
|
126
|
+
const matcherName = (0, _utils.getAccessorValue)(jestFnCall.matcher);
|
|
130
127
|
|
|
131
|
-
if (!
|
|
128
|
+
if (!snapshotMatcherNames.includes(matcherName)) {
|
|
132
129
|
return;
|
|
133
130
|
}
|
|
134
131
|
|
|
135
|
-
snapshotMatchers.push(
|
|
132
|
+
snapshotMatchers.push(jestFnCall);
|
|
136
133
|
}
|
|
137
134
|
|
|
138
135
|
};
|