eslint-plugin-jest 24.4.3 → 24.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/CHANGELOG.md +37 -0
- package/README.md +72 -49
- package/docs/rules/no-deprecated-functions.md +5 -0
- package/docs/rules/prefer-expect-resolves.md +53 -0
- package/docs/rules/prefer-to-be.md +53 -0
- package/docs/rules/require-top-level-describe.md +28 -0
- package/docs/rules/valid-expect-in-promise.md +55 -14
- package/docs/rules/valid-title.md +30 -2
- package/lib/index.js +1 -1
- package/lib/rules/detectJestVersion.js +29 -0
- package/lib/rules/lowercase-name.js +20 -1
- package/lib/rules/no-deprecated-functions.js +9 -27
- package/lib/rules/no-identical-title.js +3 -3
- package/lib/rules/no-large-snapshots.js +1 -3
- package/lib/rules/prefer-expect-resolves.js +48 -0
- package/lib/rules/prefer-to-be.js +129 -0
- package/lib/rules/require-top-level-describe.js +40 -6
- package/lib/rules/utils.js +6 -4
- package/lib/rules/valid-expect-in-promise.js +252 -68
- package/lib/rules/valid-expect.js +10 -4
- package/lib/rules/valid-title.js +47 -47
- package/package.json +1 -1
|
@@ -9,96 +9,204 @@ var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
|
9
9
|
|
|
10
10
|
var _utils = require("./utils");
|
|
11
11
|
|
|
12
|
-
const isPromiseChainCall = node =>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return isFullExpectCall(line.expression);
|
|
19
|
-
}
|
|
12
|
+
const isPromiseChainCall = node => {
|
|
13
|
+
if (node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && (0, _utils.isSupportedAccessor)(node.callee.property)) {
|
|
14
|
+
// promise methods should have at least 1 argument
|
|
15
|
+
if (node.arguments.length === 0) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
switch ((0, _utils.getAccessorValue)(node.callee.property)) {
|
|
20
|
+
case 'then':
|
|
21
|
+
return node.arguments.length < 3;
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
case 'catch':
|
|
24
|
+
case 'finally':
|
|
25
|
+
return node.arguments.length < 2;
|
|
26
|
+
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
return
|
|
29
|
+
return false;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
const
|
|
32
|
+
const findTopMostCallExpression = node => {
|
|
33
|
+
let topMostCallExpression = node;
|
|
34
|
+
let {
|
|
35
|
+
parent
|
|
36
|
+
} = node;
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
while (parent) {
|
|
39
|
+
if (parent.type === _experimentalUtils.AST_NODE_TYPES.CallExpression) {
|
|
40
|
+
topMostCallExpression = parent;
|
|
41
|
+
parent = parent.parent;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (parent.type !== _experimentalUtils.AST_NODE_TYPES.MemberExpression) {
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
parent = parent.parent;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return topMostCallExpression;
|
|
46
53
|
};
|
|
47
54
|
|
|
48
|
-
const
|
|
49
|
-
|
|
55
|
+
const isTestCaseCallWithCallbackArg = node => {
|
|
56
|
+
if (!(0, _utils.isTestCaseCall)(node)) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const isJestEach = (0, _utils.getNodeName)(node).endsWith('.each');
|
|
50
61
|
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
62
|
+
if (isJestEach && node.callee.type !== _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression) {
|
|
63
|
+
// isJestEach but not a TaggedTemplateExpression, so this must be
|
|
64
|
+
// the `jest.each([])()` syntax which this rule doesn't support due
|
|
65
|
+
// to its complexity (see jest-community/eslint-plugin-jest#710)
|
|
66
|
+
// so we return true to trigger bailout
|
|
67
|
+
return true;
|
|
55
68
|
}
|
|
56
69
|
|
|
57
|
-
|
|
58
|
-
|
|
70
|
+
if (isJestEach || node.arguments.length >= 2) {
|
|
71
|
+
const [, callback] = node.arguments;
|
|
72
|
+
const callbackArgIndex = Number(isJestEach);
|
|
73
|
+
return callback && (0, _utils.isFunction)(callback) && callback.params.length === 1 + callbackArgIndex;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return false;
|
|
59
77
|
};
|
|
60
78
|
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
79
|
+
const isPromiseMethodThatUsesValue = (node, identifier) => {
|
|
80
|
+
const {
|
|
81
|
+
name
|
|
82
|
+
} = identifier;
|
|
83
|
+
|
|
84
|
+
if (node.argument === null) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (node.argument.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.argument.arguments.length > 0) {
|
|
89
|
+
const nodeName = (0, _utils.getNodeName)(node.argument);
|
|
90
|
+
|
|
91
|
+
if (['Promise.all', 'Promise.allSettled'].includes(nodeName)) {
|
|
92
|
+
const [firstArg] = node.argument.arguments;
|
|
64
93
|
|
|
65
|
-
|
|
66
|
-
|
|
94
|
+
if (firstArg.type === _experimentalUtils.AST_NODE_TYPES.ArrayExpression && firstArg.elements.some(nod => (0, _utils.isIdentifier)(nod, name))) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
67
97
|
}
|
|
68
98
|
|
|
69
|
-
|
|
99
|
+
if (['Promise.resolve', 'Promise.reject'].includes(nodeName) && node.argument.arguments.length === 1) {
|
|
100
|
+
return (0, _utils.isIdentifier)(node.argument.arguments[0], name);
|
|
101
|
+
}
|
|
70
102
|
}
|
|
71
103
|
|
|
72
|
-
return
|
|
104
|
+
return node.argument.type === _experimentalUtils.AST_NODE_TYPES.Identifier && (0, _utils.isIdentifier)(node.argument, name);
|
|
73
105
|
};
|
|
106
|
+
/**
|
|
107
|
+
* Attempts to determine if the runtime value represented by the given `identifier`
|
|
108
|
+
* is `await`ed or `return`ed within the given `body` of statements
|
|
109
|
+
*/
|
|
74
110
|
|
|
75
|
-
const isParentThenOrPromiseReturned = (node, testFunctionBody) => node.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement || isPromiseReturnedLater(node, testFunctionBody);
|
|
76
111
|
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
112
|
+
const isValueAwaitedOrReturned = (identifier, body) => {
|
|
113
|
+
const {
|
|
114
|
+
name
|
|
115
|
+
} = identifier;
|
|
116
|
+
|
|
117
|
+
for (const node of body) {
|
|
118
|
+
// skip all nodes that are before this identifier, because they'd probably
|
|
119
|
+
// be affecting a different runtime value (e.g. due to reassignment)
|
|
120
|
+
if (node.range[0] <= identifier.range[0]) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (node.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement) {
|
|
125
|
+
return isPromiseMethodThatUsesValue(node, identifier);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (node.type === _experimentalUtils.AST_NODE_TYPES.ExpressionStatement) {
|
|
129
|
+
if (node.expression.type === _experimentalUtils.AST_NODE_TYPES.AwaitExpression) {
|
|
130
|
+
return isPromiseMethodThatUsesValue(node.expression, identifier);
|
|
131
|
+
} // (re)assignment changes the runtime value, so if we've not found an
|
|
132
|
+
// await or return already we act as if we've reached the end of the body
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
if (node.expression.type === _experimentalUtils.AST_NODE_TYPES.AssignmentExpression) {
|
|
136
|
+
var _getNodeName;
|
|
137
|
+
|
|
138
|
+
// unless we're assigning to the same identifier, in which case
|
|
139
|
+
// we might be chaining off the existing promise value
|
|
140
|
+
if ((0, _utils.isIdentifier)(node.expression.left, name) && (_getNodeName = (0, _utils.getNodeName)(node.expression.right)) !== null && _getNodeName !== void 0 && _getNodeName.startsWith(`${name}.`) && isPromiseChainCall(node.expression.right)) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
break;
|
|
83
145
|
}
|
|
84
146
|
}
|
|
85
147
|
|
|
86
|
-
|
|
87
|
-
|
|
148
|
+
if (node.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement && isValueAwaitedOrReturned(identifier, node.body)) {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return false;
|
|
88
154
|
};
|
|
89
155
|
|
|
90
|
-
const
|
|
156
|
+
const findFirstBlockBodyUp = node => {
|
|
157
|
+
let parent = node;
|
|
158
|
+
|
|
159
|
+
while (parent) {
|
|
160
|
+
if (parent.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement) {
|
|
161
|
+
return parent.body;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
parent = parent.parent;
|
|
165
|
+
}
|
|
166
|
+
/* istanbul ignore next */
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
throw new Error(`Could not find BlockStatement - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const isDirectlyWithinTestCaseCall = node => {
|
|
173
|
+
let parent = node;
|
|
174
|
+
|
|
175
|
+
while (parent) {
|
|
176
|
+
if ((0, _utils.isFunction)(parent)) {
|
|
177
|
+
var _parent;
|
|
178
|
+
|
|
179
|
+
parent = parent.parent;
|
|
180
|
+
return !!(((_parent = parent) === null || _parent === void 0 ? void 0 : _parent.type) === _experimentalUtils.AST_NODE_TYPES.CallExpression && (0, _utils.isTestCaseCall)(parent));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
parent = parent.parent;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return false;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const isVariableAwaitedOrReturned = variable => {
|
|
190
|
+
const body = findFirstBlockBodyUp(variable); // it's pretty much impossible for us to track destructuring assignments,
|
|
191
|
+
// so we return true to bailout gracefully
|
|
192
|
+
|
|
193
|
+
if (!(0, _utils.isIdentifier)(variable.id)) {
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return isValueAwaitedOrReturned(variable.id, body);
|
|
198
|
+
};
|
|
91
199
|
|
|
92
200
|
var _default = (0, _utils.createRule)({
|
|
93
201
|
name: __filename,
|
|
94
202
|
meta: {
|
|
95
203
|
docs: {
|
|
96
204
|
category: 'Best Practices',
|
|
97
|
-
description: '
|
|
205
|
+
description: 'Ensure promises that have expectations in their chain are valid',
|
|
98
206
|
recommended: 'error'
|
|
99
207
|
},
|
|
100
208
|
messages: {
|
|
101
|
-
|
|
209
|
+
expectInFloatingPromise: "This promise should either be returned or awaited to ensure the expects in it's chain are called"
|
|
102
210
|
},
|
|
103
211
|
type: 'suggestion',
|
|
104
212
|
schema: []
|
|
@@ -106,30 +214,106 @@ var _default = (0, _utils.createRule)({
|
|
|
106
214
|
defaultOptions: [],
|
|
107
215
|
|
|
108
216
|
create(context) {
|
|
217
|
+
let inTestCaseWithDoneCallback = false; // an array of booleans representing each promise chain we enter, with the
|
|
218
|
+
// boolean value representing if we think a given chain contains an expect
|
|
219
|
+
// in it's body.
|
|
220
|
+
//
|
|
221
|
+
// since we only care about the inner-most chain, we represent the state in
|
|
222
|
+
// reverse with the inner-most being the first item, as that makes it
|
|
223
|
+
// slightly less code to assign to by not needing to know the length
|
|
224
|
+
|
|
225
|
+
const chains = [];
|
|
109
226
|
return {
|
|
110
227
|
CallExpression(node) {
|
|
111
|
-
|
|
228
|
+
// there are too many ways that the done argument could be used with
|
|
229
|
+
// promises that contain expect that would make the promise safe for us
|
|
230
|
+
if (isTestCaseCallWithCallbackArg(node)) {
|
|
231
|
+
inTestCaseWithDoneCallback = true;
|
|
112
232
|
return;
|
|
113
|
-
}
|
|
233
|
+
} // if this call expression is a promise chain, add it to the stack with
|
|
234
|
+
// value of "false", as we assume there are no expect calls initially
|
|
114
235
|
|
|
115
|
-
const testFunction = findTestFunction(node);
|
|
116
236
|
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
237
|
+
if (isPromiseChainCall(node)) {
|
|
238
|
+
chains.unshift(false);
|
|
239
|
+
return;
|
|
240
|
+
} // if we're within a promise chain, and this call expression looks like
|
|
241
|
+
// an expect call, mark the deepest chain as having an expect call
|
|
121
242
|
|
|
122
|
-
|
|
123
|
-
|
|
243
|
+
|
|
244
|
+
if (chains.length > 0 && (0, _utils.isExpectCall)(node)) {
|
|
245
|
+
chains[0] = true;
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
'CallExpression:exit'(node) {
|
|
250
|
+
// there are too many ways that the "done" argument could be used to
|
|
251
|
+
// make promises containing expects safe in a test for us to be able to
|
|
252
|
+
// accurately check, so we just bail out completely if it's present
|
|
253
|
+
if (inTestCaseWithDoneCallback) {
|
|
254
|
+
if ((0, _utils.isTestCaseCall)(node)) {
|
|
255
|
+
inTestCaseWithDoneCallback = false;
|
|
124
256
|
}
|
|
125
257
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (!isPromiseChainCall(node)) {
|
|
262
|
+
return;
|
|
263
|
+
} // since we're exiting this call expression (which is a promise chain)
|
|
264
|
+
// we remove it from the stack of chains, since we're unwinding
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
const hasExpectCall = chains.shift(); // if the promise chain we're exiting doesn't contain an expect,
|
|
268
|
+
// then we don't need to check it for anything
|
|
269
|
+
|
|
270
|
+
if (!hasExpectCall) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const {
|
|
275
|
+
parent
|
|
276
|
+
} = findTopMostCallExpression(node); // if we don't have a parent (which is technically impossible at runtime)
|
|
277
|
+
// or our parent is not directly within the test case, we stop checking
|
|
278
|
+
// because we're most likely in the body of a function being defined
|
|
279
|
+
// within the test, which we can't track
|
|
130
280
|
|
|
131
|
-
|
|
281
|
+
if (!parent || !isDirectlyWithinTestCaseCall(parent)) {
|
|
282
|
+
return;
|
|
132
283
|
}
|
|
284
|
+
|
|
285
|
+
switch (parent.type) {
|
|
286
|
+
case _experimentalUtils.AST_NODE_TYPES.VariableDeclarator:
|
|
287
|
+
{
|
|
288
|
+
if (isVariableAwaitedOrReturned(parent)) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
case _experimentalUtils.AST_NODE_TYPES.AssignmentExpression:
|
|
296
|
+
{
|
|
297
|
+
if (parent.left.type === _experimentalUtils.AST_NODE_TYPES.Identifier && isValueAwaitedOrReturned(parent.left, findFirstBlockBodyUp(parent))) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
case _experimentalUtils.AST_NODE_TYPES.ExpressionStatement:
|
|
305
|
+
break;
|
|
306
|
+
|
|
307
|
+
case _experimentalUtils.AST_NODE_TYPES.ReturnStatement:
|
|
308
|
+
case _experimentalUtils.AST_NODE_TYPES.AwaitExpression:
|
|
309
|
+
default:
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
context.report({
|
|
314
|
+
messageId: 'expectInFloatingPromise',
|
|
315
|
+
node: parent
|
|
316
|
+
});
|
|
133
317
|
}
|
|
134
318
|
|
|
135
319
|
};
|
|
@@ -26,19 +26,25 @@ const getPromiseCallExpressionNode = node => {
|
|
|
26
26
|
node = node.parent;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
if (node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee
|
|
29
|
+
if (node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && (0, _utils.isSupportedAccessor)(node.callee.object) && (0, _utils.getAccessorValue)(node.callee.object) === 'Promise' && node.parent) {
|
|
30
30
|
return node;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
return null;
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
const findPromiseCallExpressionNode = node =>
|
|
36
|
+
const findPromiseCallExpressionNode = node => {
|
|
37
|
+
var _node$parent;
|
|
38
|
+
|
|
39
|
+
return (_node$parent = node.parent) !== null && _node$parent !== void 0 && _node$parent.parent && [_experimentalUtils.AST_NODE_TYPES.CallExpression, _experimentalUtils.AST_NODE_TYPES.ArrayExpression].includes(node.parent.type) ? getPromiseCallExpressionNode(node.parent) : null;
|
|
40
|
+
};
|
|
37
41
|
|
|
38
42
|
const getParentIfThenified = node => {
|
|
39
|
-
|
|
43
|
+
var _node$parent2;
|
|
44
|
+
|
|
45
|
+
const grandParentNode = (_node$parent2 = node.parent) === null || _node$parent2 === void 0 ? void 0 : _node$parent2.parent;
|
|
40
46
|
|
|
41
|
-
if (grandParentNode && grandParentNode.type === _experimentalUtils.AST_NODE_TYPES.CallExpression &&
|
|
47
|
+
if (grandParentNode && grandParentNode.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && (0, _utils.isExpectMember)(grandParentNode.callee) && ['then', 'catch'].includes((0, _utils.getAccessorValue)(grandParentNode.callee.property)) && grandParentNode.parent) {
|
|
42
48
|
// Just in case `then`s are chained look one above.
|
|
43
49
|
return getParentIfThenified(grandParentNode);
|
|
44
50
|
}
|
package/lib/rules/valid-title.js
CHANGED
|
@@ -25,23 +25,38 @@ const doesBinaryExpressionContainStringNode = binaryExp => {
|
|
|
25
25
|
|
|
26
26
|
const quoteStringValue = node => node.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral ? `\`${node.quasis[0].value.raw}\`` : node.raw;
|
|
27
27
|
|
|
28
|
+
const compileMatcherPattern = matcherMaybeWithMessage => {
|
|
29
|
+
const [matcher, message] = Array.isArray(matcherMaybeWithMessage) ? matcherMaybeWithMessage : [matcherMaybeWithMessage];
|
|
30
|
+
return [new RegExp(matcher, 'u'), message];
|
|
31
|
+
};
|
|
32
|
+
|
|
28
33
|
const compileMatcherPatterns = matchers => {
|
|
29
|
-
if (typeof matchers === 'string') {
|
|
30
|
-
const
|
|
34
|
+
if (typeof matchers === 'string' || Array.isArray(matchers)) {
|
|
35
|
+
const compiledMatcher = compileMatcherPattern(matchers);
|
|
31
36
|
return {
|
|
32
|
-
describe:
|
|
33
|
-
test:
|
|
34
|
-
it:
|
|
37
|
+
describe: compiledMatcher,
|
|
38
|
+
test: compiledMatcher,
|
|
39
|
+
it: compiledMatcher
|
|
35
40
|
};
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
return {
|
|
39
|
-
describe: matchers.describe ?
|
|
40
|
-
test: matchers.test ?
|
|
41
|
-
it: matchers.it ?
|
|
44
|
+
describe: matchers.describe ? compileMatcherPattern(matchers.describe) : null,
|
|
45
|
+
test: matchers.test ? compileMatcherPattern(matchers.test) : null,
|
|
46
|
+
it: matchers.it ? compileMatcherPattern(matchers.it) : null
|
|
42
47
|
};
|
|
43
48
|
};
|
|
44
49
|
|
|
50
|
+
const MatcherAndMessageSchema = {
|
|
51
|
+
type: 'array',
|
|
52
|
+
items: {
|
|
53
|
+
type: 'string'
|
|
54
|
+
},
|
|
55
|
+
minItems: 1,
|
|
56
|
+
maxItems: 2,
|
|
57
|
+
additionalItems: false
|
|
58
|
+
};
|
|
59
|
+
|
|
45
60
|
var _default = (0, _utils.createRule)({
|
|
46
61
|
name: __filename,
|
|
47
62
|
meta: {
|
|
@@ -57,7 +72,9 @@ var _default = (0, _utils.createRule)({
|
|
|
57
72
|
accidentalSpace: 'should not have leading or trailing spaces',
|
|
58
73
|
disallowedWord: '"{{ word }}" is not allowed in test titles.',
|
|
59
74
|
mustNotMatch: '{{ jestFunctionName }} should not match {{ pattern }}',
|
|
60
|
-
mustMatch: '{{ jestFunctionName }} should match {{ pattern }}'
|
|
75
|
+
mustMatch: '{{ jestFunctionName }} should match {{ pattern }}',
|
|
76
|
+
mustNotMatchCustom: '{{ message }}',
|
|
77
|
+
mustMatchCustom: '{{ message }}'
|
|
61
78
|
},
|
|
62
79
|
type: 'suggestion',
|
|
63
80
|
schema: [{
|
|
@@ -72,43 +89,22 @@ var _default = (0, _utils.createRule)({
|
|
|
72
89
|
items: {
|
|
73
90
|
type: 'string'
|
|
74
91
|
}
|
|
75
|
-
}
|
|
76
|
-
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
patternProperties: {
|
|
95
|
+
[/^must(?:Not)?Match$/u.source]: {
|
|
77
96
|
oneOf: [{
|
|
78
97
|
type: 'string'
|
|
79
|
-
}, {
|
|
98
|
+
}, MatcherAndMessageSchema, {
|
|
80
99
|
type: 'object',
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
type: 'string'
|
|
84
|
-
},
|
|
85
|
-
test: {
|
|
86
|
-
type: 'string'
|
|
87
|
-
},
|
|
88
|
-
it: {
|
|
89
|
-
type: 'string'
|
|
90
|
-
}
|
|
100
|
+
propertyNames: {
|
|
101
|
+
enum: ['describe', 'test', 'it']
|
|
91
102
|
},
|
|
92
|
-
additionalProperties:
|
|
93
|
-
|
|
94
|
-
},
|
|
95
|
-
mustMatch: {
|
|
96
|
-
oneOf: [{
|
|
97
|
-
type: 'string'
|
|
98
|
-
}, {
|
|
99
|
-
type: 'object',
|
|
100
|
-
properties: {
|
|
101
|
-
describe: {
|
|
103
|
+
additionalProperties: {
|
|
104
|
+
oneOf: [{
|
|
102
105
|
type: 'string'
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
type: 'string'
|
|
106
|
-
},
|
|
107
|
-
it: {
|
|
108
|
-
type: 'string'
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
additionalProperties: false
|
|
106
|
+
}, MatcherAndMessageSchema]
|
|
107
|
+
}
|
|
112
108
|
}]
|
|
113
109
|
}
|
|
114
110
|
},
|
|
@@ -132,6 +128,8 @@ var _default = (0, _utils.createRule)({
|
|
|
132
128
|
const mustMatchPatterns = compileMatcherPatterns(mustMatch !== null && mustMatch !== void 0 ? mustMatch : {});
|
|
133
129
|
return {
|
|
134
130
|
CallExpression(node) {
|
|
131
|
+
var _mustNotMatchPatterns, _mustMatchPatterns$je;
|
|
132
|
+
|
|
135
133
|
if (!(0, _utils.isDescribeCall)(node) && !(0, _utils.isTestCaseCall)(node)) {
|
|
136
134
|
return;
|
|
137
135
|
}
|
|
@@ -205,32 +203,34 @@ var _default = (0, _utils.createRule)({
|
|
|
205
203
|
}
|
|
206
204
|
|
|
207
205
|
const [jestFunctionName] = nodeName.split('.');
|
|
208
|
-
const mustNotMatchPattern = mustNotMatchPatterns[jestFunctionName];
|
|
206
|
+
const [mustNotMatchPattern, mustNotMatchMessage] = (_mustNotMatchPatterns = mustNotMatchPatterns[jestFunctionName]) !== null && _mustNotMatchPatterns !== void 0 ? _mustNotMatchPatterns : [];
|
|
209
207
|
|
|
210
208
|
if (mustNotMatchPattern) {
|
|
211
209
|
if (mustNotMatchPattern.test(title)) {
|
|
212
210
|
context.report({
|
|
213
|
-
messageId: 'mustNotMatch',
|
|
211
|
+
messageId: mustNotMatchMessage ? 'mustNotMatchCustom' : 'mustNotMatch',
|
|
214
212
|
node: argument,
|
|
215
213
|
data: {
|
|
216
214
|
jestFunctionName,
|
|
217
|
-
pattern: mustNotMatchPattern
|
|
215
|
+
pattern: mustNotMatchPattern,
|
|
216
|
+
message: mustNotMatchMessage
|
|
218
217
|
}
|
|
219
218
|
});
|
|
220
219
|
return;
|
|
221
220
|
}
|
|
222
221
|
}
|
|
223
222
|
|
|
224
|
-
const mustMatchPattern = mustMatchPatterns[jestFunctionName];
|
|
223
|
+
const [mustMatchPattern, mustMatchMessage] = (_mustMatchPatterns$je = mustMatchPatterns[jestFunctionName]) !== null && _mustMatchPatterns$je !== void 0 ? _mustMatchPatterns$je : [];
|
|
225
224
|
|
|
226
225
|
if (mustMatchPattern) {
|
|
227
226
|
if (!mustMatchPattern.test(title)) {
|
|
228
227
|
context.report({
|
|
229
|
-
messageId: 'mustMatch',
|
|
228
|
+
messageId: mustMatchMessage ? 'mustMatchCustom' : 'mustMatch',
|
|
230
229
|
node: argument,
|
|
231
230
|
data: {
|
|
232
231
|
jestFunctionName,
|
|
233
|
-
pattern: mustMatchPattern
|
|
232
|
+
pattern: mustMatchPattern,
|
|
233
|
+
message: mustMatchMessage
|
|
234
234
|
}
|
|
235
235
|
});
|
|
236
236
|
return;
|