eslint-plugin-jest 29.2.2 → 29.3.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.
|
@@ -36,7 +36,7 @@ var _default = exports.default = (0, _utils2.createRule)({
|
|
|
36
36
|
},
|
|
37
37
|
messages: {
|
|
38
38
|
hasAssertionsTakesNoArguments: '`expect.hasAssertions` expects no arguments',
|
|
39
|
-
assertionsRequiresOneArgument: '`expect.assertions`
|
|
39
|
+
assertionsRequiresOneArgument: '`expect.assertions` expects a single argument of type number',
|
|
40
40
|
assertionsRequiresNumberArgument: 'This argument should be a number',
|
|
41
41
|
haveExpectAssertions: 'Every test should have either `expect.assertions(<number of assertions>)` or `expect.hasAssertions()` as its first expression',
|
|
42
42
|
suggestAddingHasAssertions: 'Add `expect.hasAssertions()`',
|
|
@@ -68,6 +68,7 @@ var _default = exports.default = (0, _utils2.createRule)({
|
|
|
68
68
|
}],
|
|
69
69
|
create(context, [options]) {
|
|
70
70
|
let expressionDepth = 0;
|
|
71
|
+
let describeDepth = 0;
|
|
71
72
|
let hasExpectInCallback = false;
|
|
72
73
|
let hasExpectInLoop = false;
|
|
73
74
|
let hasExpectAssertionsAsFirstStatement = false;
|
|
@@ -122,7 +123,7 @@ var _default = exports.default = (0, _utils2.createRule)({
|
|
|
122
123
|
return;
|
|
123
124
|
}
|
|
124
125
|
const [arg] = expectFnCall.args;
|
|
125
|
-
if (arg.type === _utils.AST_NODE_TYPES.Literal &&
|
|
126
|
+
if (arg.type === _utils.AST_NODE_TYPES.Literal && Number.isInteger(arg.value)) {
|
|
126
127
|
return;
|
|
127
128
|
}
|
|
128
129
|
context.report({
|
|
@@ -134,6 +135,14 @@ var _default = exports.default = (0, _utils2.createRule)({
|
|
|
134
135
|
const exitExpression = () => inTestCaseCall && expressionDepth--;
|
|
135
136
|
const enterForLoop = () => inForLoop = true;
|
|
136
137
|
const exitForLoop = () => inForLoop = false;
|
|
138
|
+
let inEachHook = false;
|
|
139
|
+
|
|
140
|
+
// when set to a non-negative value, all expect calls within describes whose depth
|
|
141
|
+
// are equal to or higher than this value are covered by an expect.hasAssertions set
|
|
142
|
+
// up within a beforeEach or afterEach hook
|
|
143
|
+
//
|
|
144
|
+
// when the describe depth is lower than the current value, it gets reset to -1
|
|
145
|
+
let coveredByHookAtDepth = -1;
|
|
137
146
|
return {
|
|
138
147
|
FunctionExpression: enterExpression,
|
|
139
148
|
'FunctionExpression:exit': exitExpression,
|
|
@@ -147,12 +156,24 @@ var _default = exports.default = (0, _utils2.createRule)({
|
|
|
147
156
|
'ForOfStatement:exit': exitForLoop,
|
|
148
157
|
CallExpression(node) {
|
|
149
158
|
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
159
|
+
if (jestFnCall?.type === 'describe') {
|
|
160
|
+
describeDepth += 1;
|
|
161
|
+
}
|
|
162
|
+
if (jestFnCall?.type === 'hook' && jestFnCall.name.endsWith('Each')) {
|
|
163
|
+
inEachHook = true;
|
|
164
|
+
}
|
|
150
165
|
if (jestFnCall?.type === 'test') {
|
|
151
166
|
inTestCaseCall = true;
|
|
152
167
|
return;
|
|
153
168
|
}
|
|
169
|
+
if (jestFnCall?.type === 'expect' && inEachHook && (0, _utils2.getAccessorValue)(jestFnCall.members[0]) === 'hasAssertions') {
|
|
170
|
+
checkExpectHasAssertions(jestFnCall, node);
|
|
171
|
+
if (coveredByHookAtDepth < 0) {
|
|
172
|
+
coveredByHookAtDepth = describeDepth;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
154
175
|
if (jestFnCall?.type === 'expect' && inTestCaseCall) {
|
|
155
|
-
if (expressionDepth === 1 && isFirstStatement(node) &&
|
|
176
|
+
if (expressionDepth === 1 && isFirstStatement(node) && ['assertions', 'hasAssertions'].includes((0, _utils2.getAccessorValue)(jestFnCall.members[0]))) {
|
|
156
177
|
checkExpectHasAssertions(jestFnCall, node);
|
|
157
178
|
hasExpectAssertionsAsFirstStatement = true;
|
|
158
179
|
}
|
|
@@ -165,7 +186,20 @@ var _default = exports.default = (0, _utils2.createRule)({
|
|
|
165
186
|
}
|
|
166
187
|
},
|
|
167
188
|
'CallExpression:exit'(node) {
|
|
168
|
-
|
|
189
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
190
|
+
if (jestFnCall?.type === 'describe') {
|
|
191
|
+
describeDepth -= 1;
|
|
192
|
+
|
|
193
|
+
// clear the "covered by each hook" flag if we have left the describe
|
|
194
|
+
// depth that it applies to
|
|
195
|
+
if (coveredByHookAtDepth > describeDepth) {
|
|
196
|
+
coveredByHookAtDepth = -1;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (jestFnCall?.type === 'hook' && jestFnCall.name.endsWith('Each')) {
|
|
200
|
+
inEachHook = false;
|
|
201
|
+
}
|
|
202
|
+
if (jestFnCall?.type !== 'test') {
|
|
169
203
|
return;
|
|
170
204
|
}
|
|
171
205
|
inTestCaseCall = false;
|
|
@@ -182,6 +216,9 @@ var _default = exports.default = (0, _utils2.createRule)({
|
|
|
182
216
|
hasExpectAssertionsAsFirstStatement = false;
|
|
183
217
|
return;
|
|
184
218
|
}
|
|
219
|
+
if (coveredByHookAtDepth >= 0 && coveredByHookAtDepth <= describeDepth) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
185
222
|
const suggestions = [];
|
|
186
223
|
if (testFn.body.type === _utils.AST_NODE_TYPES.BlockStatement) {
|
|
187
224
|
suggestions.push(['suggestAddingHasAssertions', 'expect.hasAssertions();'], ['suggestAddingAssertions', 'expect.assertions();']);
|