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
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getNodeChain = getNodeChain;
|
|
7
|
-
exports.scopeHasLocalReference = exports.parseJestFnCall = exports.isTypeOfJestFnCall = void 0;
|
|
7
|
+
exports.scopeHasLocalReference = exports.parseJestFnCallWithReason = exports.parseJestFnCall = exports.isTypeOfJestFnCall = void 0;
|
|
8
8
|
|
|
9
9
|
var _utils = require("@typescript-eslint/utils");
|
|
10
10
|
|
|
@@ -39,9 +39,10 @@ function getNodeChain(node) {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
const determineJestFnType = name => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
if (name === 'expect') {
|
|
43
|
+
return 'expect';
|
|
44
|
+
}
|
|
45
|
+
|
|
45
46
|
if (name === 'jest') {
|
|
46
47
|
return 'jest';
|
|
47
48
|
}
|
|
@@ -81,27 +82,23 @@ const resolvePossibleAliasedGlobal = (global, context) => {
|
|
|
81
82
|
};
|
|
82
83
|
|
|
83
84
|
const parseJestFnCall = (node, context) => {
|
|
84
|
-
|
|
85
|
+
const jestFnCall = parseJestFnCallWithReason(node, context);
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
// parsing e.g. x().y.z(), we'll incorrectly find & parse "x()" even though
|
|
88
|
-
// the full chain is not a valid jest function call chain
|
|
89
|
-
if (((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) === _utils.AST_NODE_TYPES.CallExpression || ((_node$parent2 = node.parent) === null || _node$parent2 === void 0 ? void 0 : _node$parent2.type) === _utils.AST_NODE_TYPES.MemberExpression) {
|
|
87
|
+
if (typeof jestFnCall === 'string') {
|
|
90
88
|
return null;
|
|
91
89
|
}
|
|
92
90
|
|
|
93
|
-
|
|
91
|
+
return jestFnCall;
|
|
92
|
+
};
|
|
94
93
|
|
|
95
|
-
|
|
96
|
-
return null;
|
|
97
|
-
} // check that every link in the chain except the last is a member expression
|
|
94
|
+
exports.parseJestFnCall = parseJestFnCall;
|
|
98
95
|
|
|
96
|
+
const parseJestFnCallWithReason = (node, context) => {
|
|
97
|
+
var _resolved$original, _node$parent2, _node$parent3;
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
var _nod$parent;
|
|
99
|
+
const chain = getNodeChain(node);
|
|
102
100
|
|
|
103
|
-
|
|
104
|
-
})) {
|
|
101
|
+
if (!(chain !== null && chain !== void 0 && chain.length)) {
|
|
105
102
|
return null;
|
|
106
103
|
}
|
|
107
104
|
|
|
@@ -127,21 +124,121 @@ const parseJestFnCall = (node, context) => {
|
|
|
127
124
|
const name = (_resolved$original = resolved.original) !== null && _resolved$original !== void 0 ? _resolved$original : resolved.local;
|
|
128
125
|
const links = [name, ...rest.map(link => (0, _utils2.getAccessorValue)(link))];
|
|
129
126
|
|
|
130
|
-
if (name !== 'jest' && !ValidJestFnCallChains.includes(links.join('.'))) {
|
|
127
|
+
if (name !== 'jest' && name !== 'expect' && !ValidJestFnCallChains.includes(links.join('.'))) {
|
|
131
128
|
return null;
|
|
132
129
|
}
|
|
133
130
|
|
|
134
|
-
|
|
131
|
+
const parsedJestFnCall = {
|
|
135
132
|
name,
|
|
136
|
-
type: determineJestFnType(name),
|
|
137
133
|
head: { ...resolved,
|
|
138
134
|
node: first
|
|
139
135
|
},
|
|
136
|
+
// every member node must have a member expression as their parent
|
|
137
|
+
// in order to be part of the call chain we're parsing
|
|
140
138
|
members: rest
|
|
141
139
|
};
|
|
140
|
+
const type = determineJestFnType(name);
|
|
141
|
+
|
|
142
|
+
if (type === 'expect') {
|
|
143
|
+
const result = parseJestExpectCall(parsedJestFnCall); // if the `expect` call chain is not valid, only report on the topmost node
|
|
144
|
+
// since all members in the chain are likely to get flagged for some reason
|
|
145
|
+
|
|
146
|
+
if (typeof result === 'string' && (0, _utils2.findTopMostCallExpression)(node) !== node) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (result === 'matcher-not-found') {
|
|
151
|
+
var _node$parent;
|
|
152
|
+
|
|
153
|
+
if (((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) === _utils.AST_NODE_TYPES.MemberExpression) {
|
|
154
|
+
return 'matcher-not-called';
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return result;
|
|
159
|
+
} // check that every link in the chain except the last is a member expression
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
if (chain.slice(0, chain.length - 1).some(nod => {
|
|
163
|
+
var _nod$parent;
|
|
164
|
+
|
|
165
|
+
return ((_nod$parent = nod.parent) === null || _nod$parent === void 0 ? void 0 : _nod$parent.type) !== _utils.AST_NODE_TYPES.MemberExpression;
|
|
166
|
+
})) {
|
|
167
|
+
return null;
|
|
168
|
+
} // ensure that we're at the "top" of the function call chain otherwise when
|
|
169
|
+
// parsing e.g. x().y.z(), we'll incorrectly find & parse "x()" even though
|
|
170
|
+
// the full chain is not a valid jest function call chain
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
if (((_node$parent2 = node.parent) === null || _node$parent2 === void 0 ? void 0 : _node$parent2.type) === _utils.AST_NODE_TYPES.CallExpression || ((_node$parent3 = node.parent) === null || _node$parent3 === void 0 ? void 0 : _node$parent3.type) === _utils.AST_NODE_TYPES.MemberExpression) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return { ...parsedJestFnCall,
|
|
178
|
+
type
|
|
179
|
+
};
|
|
142
180
|
};
|
|
143
181
|
|
|
144
|
-
exports.
|
|
182
|
+
exports.parseJestFnCallWithReason = parseJestFnCallWithReason;
|
|
183
|
+
|
|
184
|
+
const findModifiersAndMatcher = members => {
|
|
185
|
+
const modifiers = [];
|
|
186
|
+
|
|
187
|
+
for (const member of members) {
|
|
188
|
+
var _member$parent, _member$parent$parent;
|
|
189
|
+
|
|
190
|
+
// check if the member is being called, which means it is the matcher
|
|
191
|
+
// (and also the end of the entire "expect" call chain)
|
|
192
|
+
if (((_member$parent = member.parent) === null || _member$parent === void 0 ? void 0 : _member$parent.type) === _utils.AST_NODE_TYPES.MemberExpression && ((_member$parent$parent = member.parent.parent) === null || _member$parent$parent === void 0 ? void 0 : _member$parent$parent.type) === _utils.AST_NODE_TYPES.CallExpression) {
|
|
193
|
+
return {
|
|
194
|
+
matcher: member,
|
|
195
|
+
args: member.parent.parent.arguments,
|
|
196
|
+
modifiers
|
|
197
|
+
};
|
|
198
|
+
} // otherwise, it should be a modifier
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
const name = (0, _utils2.getAccessorValue)(member);
|
|
202
|
+
|
|
203
|
+
if (modifiers.length === 0) {
|
|
204
|
+
// the first modifier can be any of the three modifiers
|
|
205
|
+
if (!_utils2.ModifierName.hasOwnProperty(name)) {
|
|
206
|
+
return 'modifier-unknown';
|
|
207
|
+
}
|
|
208
|
+
} else if (modifiers.length === 1) {
|
|
209
|
+
// the second modifier can only be "not"
|
|
210
|
+
if (name !== _utils2.ModifierName.not) {
|
|
211
|
+
return 'modifier-unknown';
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const firstModifier = (0, _utils2.getAccessorValue)(modifiers[0]); // and the first modifier has to be either "resolves" or "rejects"
|
|
215
|
+
|
|
216
|
+
if (firstModifier !== _utils2.ModifierName.resolves && firstModifier !== _utils2.ModifierName.rejects) {
|
|
217
|
+
return 'modifier-unknown';
|
|
218
|
+
}
|
|
219
|
+
} else {
|
|
220
|
+
return 'modifier-unknown';
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
modifiers.push(member);
|
|
224
|
+
} // this will only really happen if there are no members
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
return 'matcher-not-found';
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const parseJestExpectCall = typelessParsedJestFnCall => {
|
|
231
|
+
const modifiersAndMatcher = findModifiersAndMatcher(typelessParsedJestFnCall.members);
|
|
232
|
+
|
|
233
|
+
if (typeof modifiersAndMatcher === 'string') {
|
|
234
|
+
return modifiersAndMatcher;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return { ...typelessParsedJestFnCall,
|
|
238
|
+
type: 'expect',
|
|
239
|
+
...modifiersAndMatcher
|
|
240
|
+
};
|
|
241
|
+
};
|
|
145
242
|
|
|
146
243
|
const describeImportDefAsImport = def => {
|
|
147
244
|
if (def.parent.type === _utils.AST_NODE_TYPES.TSImportEqualsDeclaration) {
|
|
@@ -29,29 +29,6 @@ const isPromiseChainCall = node => {
|
|
|
29
29
|
return false;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
const findTopMostCallExpression = node => {
|
|
33
|
-
let topMostCallExpression = node;
|
|
34
|
-
let {
|
|
35
|
-
parent
|
|
36
|
-
} = node;
|
|
37
|
-
|
|
38
|
-
while (parent) {
|
|
39
|
-
if (parent.type === _utils.AST_NODE_TYPES.CallExpression) {
|
|
40
|
-
topMostCallExpression = parent;
|
|
41
|
-
parent = parent.parent;
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (parent.type !== _utils.AST_NODE_TYPES.MemberExpression) {
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
parent = parent.parent;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return topMostCallExpression;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
32
|
const isTestCaseCallWithCallbackArg = (node, context) => {
|
|
56
33
|
const jestCallFn = (0, _utils2.parseJestFnCall)(node, context);
|
|
57
34
|
|
|
@@ -173,7 +150,7 @@ const getLeftMostCallExpression = call => {
|
|
|
173
150
|
*/
|
|
174
151
|
|
|
175
152
|
|
|
176
|
-
const isValueAwaitedOrReturned = (identifier, body) => {
|
|
153
|
+
const isValueAwaitedOrReturned = (identifier, body, context) => {
|
|
177
154
|
const {
|
|
178
155
|
name
|
|
179
156
|
} = identifier;
|
|
@@ -197,13 +174,13 @@ const isValueAwaitedOrReturned = (identifier, body) => {
|
|
|
197
174
|
}
|
|
198
175
|
|
|
199
176
|
const leftMostCall = getLeftMostCallExpression(node.expression);
|
|
177
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node.expression, context);
|
|
200
178
|
|
|
201
|
-
if ((0
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if ((modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils2.ModifierName.resolves || (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils2.ModifierName.rejects) {
|
|
179
|
+
if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'expect' && leftMostCall.arguments.length > 0 && (0, _utils2.isIdentifier)(leftMostCall.arguments[0], name)) {
|
|
180
|
+
if (jestFnCall.members.some(m => {
|
|
181
|
+
const v = (0, _utils2.getAccessorValue)(m);
|
|
182
|
+
return v === _utils2.ModifierName.resolves || v === _utils2.ModifierName.rejects;
|
|
183
|
+
})) {
|
|
207
184
|
return true;
|
|
208
185
|
}
|
|
209
186
|
}
|
|
@@ -228,7 +205,7 @@ const isValueAwaitedOrReturned = (identifier, body) => {
|
|
|
228
205
|
}
|
|
229
206
|
}
|
|
230
207
|
|
|
231
|
-
if (node.type === _utils.AST_NODE_TYPES.BlockStatement && isValueAwaitedOrReturned(identifier, node.body)) {
|
|
208
|
+
if (node.type === _utils.AST_NODE_TYPES.BlockStatement && isValueAwaitedOrReturned(identifier, node.body, context)) {
|
|
232
209
|
return true;
|
|
233
210
|
}
|
|
234
211
|
}
|
|
@@ -269,7 +246,7 @@ const isDirectlyWithinTestCaseCall = (node, context) => {
|
|
|
269
246
|
return false;
|
|
270
247
|
};
|
|
271
248
|
|
|
272
|
-
const isVariableAwaitedOrReturned = variable => {
|
|
249
|
+
const isVariableAwaitedOrReturned = (variable, context) => {
|
|
273
250
|
const body = findFirstBlockBodyUp(variable); // it's pretty much impossible for us to track destructuring assignments,
|
|
274
251
|
// so we return true to bailout gracefully
|
|
275
252
|
|
|
@@ -277,7 +254,7 @@ const isVariableAwaitedOrReturned = variable => {
|
|
|
277
254
|
return true;
|
|
278
255
|
}
|
|
279
256
|
|
|
280
|
-
return isValueAwaitedOrReturned(variable.id, body);
|
|
257
|
+
return isValueAwaitedOrReturned(variable.id, body, context);
|
|
281
258
|
};
|
|
282
259
|
|
|
283
260
|
var _default = (0, _utils2.createRule)({
|
|
@@ -324,7 +301,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
324
301
|
// an expect call, mark the deepest chain as having an expect call
|
|
325
302
|
|
|
326
303
|
|
|
327
|
-
if (chains.length > 0 && (0, _utils2.
|
|
304
|
+
if (chains.length > 0 && (0, _utils2.isTypeOfJestFnCall)(node, context, ['expect'])) {
|
|
328
305
|
chains[0] = true;
|
|
329
306
|
}
|
|
330
307
|
},
|
|
@@ -356,7 +333,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
356
333
|
|
|
357
334
|
const {
|
|
358
335
|
parent
|
|
359
|
-
} = findTopMostCallExpression(node); // if we don't have a parent (which is technically impossible at runtime)
|
|
336
|
+
} = (0, _utils2.findTopMostCallExpression)(node); // if we don't have a parent (which is technically impossible at runtime)
|
|
360
337
|
// or our parent is not directly within the test case, we stop checking
|
|
361
338
|
// because we're most likely in the body of a function being defined
|
|
362
339
|
// within the test, which we can't track
|
|
@@ -368,7 +345,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
368
345
|
switch (parent.type) {
|
|
369
346
|
case _utils.AST_NODE_TYPES.VariableDeclarator:
|
|
370
347
|
{
|
|
371
|
-
if (isVariableAwaitedOrReturned(parent)) {
|
|
348
|
+
if (isVariableAwaitedOrReturned(parent, context)) {
|
|
372
349
|
return;
|
|
373
350
|
}
|
|
374
351
|
|
|
@@ -377,7 +354,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
377
354
|
|
|
378
355
|
case _utils.AST_NODE_TYPES.AssignmentExpression:
|
|
379
356
|
{
|
|
380
|
-
if (parent.left.type === _utils.AST_NODE_TYPES.Identifier && isValueAwaitedOrReturned(parent.left, findFirstBlockBodyUp(parent))) {
|
|
357
|
+
if (parent.left.type === _utils.AST_NODE_TYPES.Identifier && isValueAwaitedOrReturned(parent.left, findFirstBlockBodyUp(parent), context)) {
|
|
381
358
|
return;
|
|
382
359
|
}
|
|
383
360
|
|
|
@@ -44,7 +44,7 @@ const getParentIfThenified = node => {
|
|
|
44
44
|
|
|
45
45
|
const grandParentNode = (_node$parent2 = node.parent) === null || _node$parent2 === void 0 ? void 0 : _node$parent2.parent;
|
|
46
46
|
|
|
47
|
-
if (grandParentNode && grandParentNode.type === _utils.AST_NODE_TYPES.CallExpression && (0, _utils2.
|
|
47
|
+
if (grandParentNode && grandParentNode.type === _utils.AST_NODE_TYPES.CallExpression && grandParentNode.callee.type === _utils.AST_NODE_TYPES.MemberExpression && (0, _utils2.isSupportedAccessor)(grandParentNode.callee.property) && ['then', 'catch'].includes((0, _utils2.getAccessorValue)(grandParentNode.callee.property)) && grandParentNode.parent) {
|
|
48
48
|
// Just in case `then`s are chained look one above.
|
|
49
49
|
return getParentIfThenified(grandParentNode);
|
|
50
50
|
}
|
|
@@ -64,8 +64,6 @@ const isAcceptableReturnNode = (node, allowReturn) => {
|
|
|
64
64
|
return [_utils.AST_NODE_TYPES.ArrowFunctionExpression, _utils.AST_NODE_TYPES.AwaitExpression].includes(node.type);
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
const isNoAssertionsParentNode = node => node.type === _utils.AST_NODE_TYPES.ExpressionStatement || node.type === _utils.AST_NODE_TYPES.AwaitExpression && node.parent !== undefined && node.parent.type === _utils.AST_NODE_TYPES.ExpressionStatement;
|
|
68
|
-
|
|
69
67
|
const promiseArrayExceptionKey = ({
|
|
70
68
|
start,
|
|
71
69
|
end
|
|
@@ -84,7 +82,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
84
82
|
messages: {
|
|
85
83
|
tooManyArgs: 'Expect takes at most {{ amount }} argument{{ s }}.',
|
|
86
84
|
notEnoughArgs: 'Expect requires at least {{ amount }} argument{{ s }}.',
|
|
87
|
-
modifierUnknown: 'Expect has
|
|
85
|
+
modifierUnknown: 'Expect has an unknown modifier.',
|
|
88
86
|
matcherNotFound: 'Expect must have a corresponding matcher call.',
|
|
89
87
|
matcherNotCalled: 'Matchers must be called to assert.',
|
|
90
88
|
asyncMustBeAwaited: 'Async assertions must be awaited{{ orReturned }}.',
|
|
@@ -144,28 +142,79 @@ var _default = (0, _utils2.createRule)({
|
|
|
144
142
|
|
|
145
143
|
const promiseArrayExceptionExists = loc => arrayExceptions.has(promiseArrayExceptionKey(loc));
|
|
146
144
|
|
|
145
|
+
const findTopMostMemberExpression = node => {
|
|
146
|
+
let topMostMemberExpression = node;
|
|
147
|
+
let {
|
|
148
|
+
parent
|
|
149
|
+
} = node;
|
|
150
|
+
|
|
151
|
+
while (parent) {
|
|
152
|
+
if (parent.type !== _utils.AST_NODE_TYPES.MemberExpression) {
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
topMostMemberExpression = parent;
|
|
157
|
+
parent = parent.parent;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return topMostMemberExpression;
|
|
161
|
+
};
|
|
162
|
+
|
|
147
163
|
return {
|
|
148
164
|
CallExpression(node) {
|
|
149
|
-
|
|
165
|
+
const jestFnCall = (0, _utils2.parseJestFnCallWithReason)(node, context);
|
|
166
|
+
|
|
167
|
+
if (typeof jestFnCall === 'string') {
|
|
168
|
+
var _node$parent3;
|
|
169
|
+
|
|
170
|
+
const reportingNode = ((_node$parent3 = node.parent) === null || _node$parent3 === void 0 ? void 0 : _node$parent3.type) === _utils.AST_NODE_TYPES.MemberExpression ? findTopMostMemberExpression(node.parent).property : node;
|
|
171
|
+
|
|
172
|
+
if (jestFnCall === 'matcher-not-found') {
|
|
173
|
+
context.report({
|
|
174
|
+
messageId: 'matcherNotFound',
|
|
175
|
+
node: reportingNode
|
|
176
|
+
});
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (jestFnCall === 'matcher-not-called') {
|
|
181
|
+
context.report({
|
|
182
|
+
messageId: (0, _utils2.isSupportedAccessor)(reportingNode) && _utils2.ModifierName.hasOwnProperty((0, _utils2.getAccessorValue)(reportingNode)) ? 'matcherNotFound' : 'matcherNotCalled',
|
|
183
|
+
node: reportingNode
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (jestFnCall === 'modifier-unknown') {
|
|
188
|
+
context.report({
|
|
189
|
+
messageId: 'modifierUnknown',
|
|
190
|
+
node: reportingNode
|
|
191
|
+
});
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return;
|
|
196
|
+
} else if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
|
|
150
197
|
return;
|
|
151
198
|
}
|
|
152
199
|
|
|
153
200
|
const {
|
|
154
|
-
expect
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
201
|
+
parent: expect
|
|
202
|
+
} = jestFnCall.head.node;
|
|
203
|
+
|
|
204
|
+
if ((expect === null || expect === void 0 ? void 0 : expect.type) !== _utils.AST_NODE_TYPES.CallExpression) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
158
207
|
|
|
159
208
|
if (expect.arguments.length < minArgs) {
|
|
160
|
-
const expectLength = (0, _utils2.getAccessorValue)(
|
|
209
|
+
const expectLength = (0, _utils2.getAccessorValue)(jestFnCall.head.node).length;
|
|
161
210
|
const loc = {
|
|
162
211
|
start: {
|
|
163
|
-
column:
|
|
164
|
-
line:
|
|
212
|
+
column: expect.loc.start.column + expectLength,
|
|
213
|
+
line: expect.loc.start.line
|
|
165
214
|
},
|
|
166
215
|
end: {
|
|
167
|
-
column:
|
|
168
|
-
line:
|
|
216
|
+
column: expect.loc.start.column + expectLength + 1,
|
|
217
|
+
line: expect.loc.start.line
|
|
169
218
|
}
|
|
170
219
|
};
|
|
171
220
|
context.report({
|
|
@@ -174,7 +223,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
174
223
|
amount: minArgs,
|
|
175
224
|
s: minArgs === 1 ? '' : 's'
|
|
176
225
|
},
|
|
177
|
-
node,
|
|
226
|
+
node: expect,
|
|
178
227
|
loc
|
|
179
228
|
});
|
|
180
229
|
}
|
|
@@ -185,7 +234,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
185
234
|
} = expect.arguments[maxArgs].loc;
|
|
186
235
|
const {
|
|
187
236
|
end
|
|
188
|
-
} = expect.arguments[
|
|
237
|
+
} = expect.arguments[expect.arguments.length - 1].loc;
|
|
189
238
|
const loc = {
|
|
190
239
|
start,
|
|
191
240
|
end: {
|
|
@@ -199,45 +248,18 @@ var _default = (0, _utils2.createRule)({
|
|
|
199
248
|
amount: maxArgs,
|
|
200
249
|
s: maxArgs === 1 ? '' : 's'
|
|
201
250
|
},
|
|
202
|
-
node,
|
|
251
|
+
node: expect,
|
|
203
252
|
loc
|
|
204
253
|
});
|
|
205
|
-
} // something was called on `expect()`
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (!matcher) {
|
|
209
|
-
if (modifier) {
|
|
210
|
-
context.report({
|
|
211
|
-
messageId: 'matcherNotFound',
|
|
212
|
-
node: modifier.node.property
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if ((0, _utils2.isExpectMember)(matcher.node.parent)) {
|
|
220
|
-
context.report({
|
|
221
|
-
messageId: 'modifierUnknown',
|
|
222
|
-
data: {
|
|
223
|
-
modifierName: matcher.name
|
|
224
|
-
},
|
|
225
|
-
node: matcher.node.property
|
|
226
|
-
});
|
|
227
|
-
return;
|
|
228
254
|
}
|
|
229
255
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const parentNode = matcher.node.parent;
|
|
238
|
-
const shouldBeAwaited = modifier && modifier.name !== _utils2.ModifierName.not || asyncMatchers.includes(matcher.name);
|
|
256
|
+
const {
|
|
257
|
+
matcher
|
|
258
|
+
} = jestFnCall;
|
|
259
|
+
const parentNode = matcher.parent.parent;
|
|
260
|
+
const shouldBeAwaited = jestFnCall.modifiers.some(nod => (0, _utils2.getAccessorValue)(nod) !== 'not') || asyncMatchers.includes((0, _utils2.getAccessorValue)(matcher));
|
|
239
261
|
|
|
240
|
-
if (!parentNode.parent || !shouldBeAwaited) {
|
|
262
|
+
if (!(parentNode !== null && parentNode !== void 0 && parentNode.parent) || !shouldBeAwaited) {
|
|
241
263
|
return;
|
|
242
264
|
}
|
|
243
265
|
/**
|
|
@@ -273,16 +295,6 @@ var _default = (0, _utils2.createRule)({
|
|
|
273
295
|
pushPromiseArrayException(finalNode.loc);
|
|
274
296
|
}
|
|
275
297
|
}
|
|
276
|
-
},
|
|
277
|
-
|
|
278
|
-
// nothing called on "expect()"
|
|
279
|
-
'CallExpression:exit'(node) {
|
|
280
|
-
if ((0, _utils2.isExpectCall)(node) && isNoAssertionsParentNode(node.parent)) {
|
|
281
|
-
context.report({
|
|
282
|
-
messageId: 'matcherNotFound',
|
|
283
|
-
node
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
298
|
}
|
|
287
299
|
|
|
288
300
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-jest",
|
|
3
|
-
"version": "26.
|
|
3
|
+
"version": "26.8.0",
|
|
4
4
|
"description": "ESLint rules for Jest",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -21,16 +21,16 @@
|
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
23
|
"build": "babel --extensions .js,.ts src --out-dir lib --copy-files && rimraf lib/__tests__ 'lib/**/__tests__'",
|
|
24
|
+
"_postinstall": "is-ci || husky install",
|
|
24
25
|
"lint": "eslint . --ignore-pattern '!.eslintrc.js' --ext js,ts",
|
|
25
26
|
"prepack": "rimraf lib && yarn build",
|
|
27
|
+
"prepublishOnly": "pinst --disable",
|
|
26
28
|
"prettier:check": "prettier --check 'docs/**/*.md' README.md '.github/**' package.json tsconfig.json src/globals.json .yarnrc.yml",
|
|
27
29
|
"prettier:write": "prettier --write 'docs/**/*.md' README.md '.github/**' package.json tsconfig.json src/globals.json .yarnrc.yml",
|
|
30
|
+
"postpublish": "pinst --enable",
|
|
28
31
|
"test": "jest",
|
|
29
32
|
"tools:regenerate-docs": "ts-node -T tools/regenerate-docs",
|
|
30
|
-
"typecheck": "tsc -p ."
|
|
31
|
-
"_postinstall": "is-ci || husky install",
|
|
32
|
-
"prepublishOnly": "pinst --disable",
|
|
33
|
-
"postpublish": "pinst --enable"
|
|
33
|
+
"typecheck": "tsc -p ."
|
|
34
34
|
},
|
|
35
35
|
"commitlint": {
|
|
36
36
|
"extends": [
|
|
@@ -48,6 +48,23 @@
|
|
|
48
48
|
"singleQuote": true,
|
|
49
49
|
"trailingComma": "all"
|
|
50
50
|
},
|
|
51
|
+
"release": {
|
|
52
|
+
"branches": [
|
|
53
|
+
"main",
|
|
54
|
+
{
|
|
55
|
+
"name": "next",
|
|
56
|
+
"prerelease": true
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"plugins": [
|
|
60
|
+
"@semantic-release/commit-analyzer",
|
|
61
|
+
"@semantic-release/release-notes-generator",
|
|
62
|
+
"@semantic-release/changelog",
|
|
63
|
+
"@semantic-release/npm",
|
|
64
|
+
"@semantic-release/git",
|
|
65
|
+
"@semantic-release/github"
|
|
66
|
+
]
|
|
67
|
+
},
|
|
51
68
|
"jest": {
|
|
52
69
|
"coverageThreshold": {
|
|
53
70
|
"global": {
|
|
@@ -103,7 +120,6 @@
|
|
|
103
120
|
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0",
|
|
104
121
|
"eslint-config-prettier": "^8.3.0",
|
|
105
122
|
"eslint-plugin-eslint-comments": "^3.1.2",
|
|
106
|
-
"eslint-plugin-eslint-config": "^2.0.0",
|
|
107
123
|
"eslint-plugin-eslint-plugin": "^5.0.0",
|
|
108
124
|
"eslint-plugin-import": "^2.25.1",
|
|
109
125
|
"eslint-plugin-node": "^11.0.0",
|
|
@@ -135,28 +151,8 @@
|
|
|
135
151
|
"optional": true
|
|
136
152
|
}
|
|
137
153
|
},
|
|
154
|
+
"packageManager": "yarn@3.2.2",
|
|
138
155
|
"engines": {
|
|
139
156
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
|
140
|
-
}
|
|
141
|
-
"release": {
|
|
142
|
-
"branches": [
|
|
143
|
-
"main",
|
|
144
|
-
{
|
|
145
|
-
"name": "next",
|
|
146
|
-
"prerelease": true
|
|
147
|
-
}
|
|
148
|
-
],
|
|
149
|
-
"plugins": [
|
|
150
|
-
"@semantic-release/commit-analyzer",
|
|
151
|
-
"@semantic-release/release-notes-generator",
|
|
152
|
-
"@semantic-release/changelog",
|
|
153
|
-
"@semantic-release/npm",
|
|
154
|
-
"@semantic-release/git",
|
|
155
|
-
"@semantic-release/github"
|
|
156
|
-
]
|
|
157
|
-
},
|
|
158
|
-
"resolutions": {
|
|
159
|
-
"@typescript-eslint/experimental-utils": "^5.0.0"
|
|
160
|
-
},
|
|
161
|
-
"packageManager": "yarn@3.2.2"
|
|
157
|
+
}
|
|
162
158
|
}
|