eslint-plugin-jest 28.0.0-next.1 → 28.0.0-next.3

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.
Files changed (56) hide show
  1. package/lib/index.js +0 -2
  2. package/lib/rules/consistent-test-it.js +3 -3
  3. package/lib/rules/expect-expect.js +1 -3
  4. package/lib/rules/max-expects.js +3 -7
  5. package/lib/rules/max-nested-describe.js +1 -3
  6. package/lib/rules/no-alias-methods.js +2 -4
  7. package/lib/rules/no-commented-out-tests.js +1 -3
  8. package/lib/rules/no-conditional-expect.js +1 -3
  9. package/lib/rules/no-conditional-in-test.js +1 -3
  10. package/lib/rules/no-confusing-set-timeout.js +1 -3
  11. package/lib/rules/no-deprecated-functions.js +2 -5
  12. package/lib/rules/no-disabled-tests.js +1 -3
  13. package/lib/rules/no-done-callback.js +5 -9
  14. package/lib/rules/no-duplicate-hooks.js +4 -7
  15. package/lib/rules/no-export.js +1 -3
  16. package/lib/rules/no-focused-tests.js +2 -4
  17. package/lib/rules/no-hooks.js +3 -4
  18. package/lib/rules/no-identical-title.js +1 -3
  19. package/lib/rules/no-interpolation-in-snapshots.js +2 -4
  20. package/lib/rules/no-jasmine-globals.js +1 -3
  21. package/lib/rules/no-large-snapshots.js +2 -4
  22. package/lib/rules/no-mocks-import.js +1 -3
  23. package/lib/rules/no-restricted-jest-methods.js +2 -4
  24. package/lib/rules/no-restricted-matchers.js +2 -4
  25. package/lib/rules/no-standalone-expect.js +6 -9
  26. package/lib/rules/no-test-prefixes.js +2 -4
  27. package/lib/rules/no-test-return-statement.js +1 -3
  28. package/lib/rules/no-untyped-mock-factory.js +10 -7
  29. package/lib/rules/prefer-called-with.js +2 -4
  30. package/lib/rules/prefer-comparison-matcher.js +4 -6
  31. package/lib/rules/prefer-each.js +1 -3
  32. package/lib/rules/prefer-equality-matcher.js +4 -6
  33. package/lib/rules/prefer-expect-assertions.js +6 -10
  34. package/lib/rules/prefer-expect-resolves.js +4 -6
  35. package/lib/rules/prefer-hooks-in-order.js +2 -4
  36. package/lib/rules/prefer-hooks-on-top.js +1 -3
  37. package/lib/rules/prefer-lowercase-title.js +4 -3
  38. package/lib/rules/prefer-mock-promise-shorthand.js +3 -6
  39. package/lib/rules/prefer-snapshot-hint.js +3 -5
  40. package/lib/rules/prefer-spy-on.js +2 -5
  41. package/lib/rules/prefer-strict-equal.js +2 -4
  42. package/lib/rules/prefer-to-be.js +3 -6
  43. package/lib/rules/prefer-to-contain.js +3 -5
  44. package/lib/rules/prefer-to-have-length.js +4 -6
  45. package/lib/rules/prefer-todo.js +2 -4
  46. package/lib/rules/require-hook.js +2 -5
  47. package/lib/rules/require-to-throw-message.js +2 -4
  48. package/lib/rules/require-top-level-describe.js +1 -3
  49. package/lib/rules/unbound-method.js +8 -9
  50. package/lib/rules/utils/misc.js +6 -18
  51. package/lib/rules/utils/parseJestFnCall.js +12 -16
  52. package/lib/rules/valid-describe-callback.js +2 -4
  53. package/lib/rules/valid-expect-in-promise.js +7 -11
  54. package/lib/rules/valid-expect.js +7 -14
  55. package/lib/rules/valid-title.js +3 -4
  56. package/package.json +4 -4
@@ -50,9 +50,12 @@ const determineJestFnType = name => {
50
50
  return 'unknown';
51
51
  };
52
52
  const ValidJestFnCallChains = ['afterAll', 'afterEach', 'beforeAll', 'beforeEach', 'describe', 'describe.each', 'describe.only', 'describe.only.each', 'describe.skip', 'describe.skip.each', 'fdescribe', 'fdescribe.each', 'xdescribe', 'xdescribe.each', 'it', 'it.concurrent', 'it.concurrent.failing', 'it.concurrent.each', 'it.concurrent.failing.each', 'it.concurrent.failing.only.each', 'it.concurrent.failing.skip.each', 'it.concurrent.only.each', 'it.concurrent.skip.each', 'it.each', 'it.failing', 'it.failing.each', 'it.only', 'it.only.each', 'it.only.failing', 'it.only.failing.each', 'it.skip', 'it.skip.each', 'it.skip.failing', 'it.skip.failing.each', 'it.todo', 'fit', 'fit.each', 'fit.failing', 'fit.failing.each', 'xit', 'xit.each', 'xit.failing', 'xit.failing.each', 'test', 'test.concurrent', 'test.concurrent.failing', 'test.concurrent.each', 'test.concurrent.failing.each', 'test.concurrent.failing.only.each', 'test.concurrent.failing.skip.each', 'test.concurrent.only.each', 'test.concurrent.skip.each', 'test.each', 'test.failing', 'test.failing.each', 'test.only', 'test.only.each', 'test.only.failing', 'test.only.failing.each', 'test.skip', 'test.skip.each', 'test.skip.failing', 'test.skip.failing.each', 'test.todo', 'xtest', 'xtest.each', 'xtest.failing', 'xtest.failing.each'];
53
+
54
+ // todo: switch back to using declaration merging once https://github.com/typescript-eslint/typescript-eslint/pull/8485
55
+ // is landed
56
+
53
57
  const resolvePossibleAliasedGlobal = (global, context) => {
54
- var _context$settings$jes;
55
- const globalAliases = ((_context$settings$jes = context.settings.jest) === null || _context$settings$jes === void 0 ? void 0 : _context$settings$jes.globalAliases) ?? {};
58
+ const globalAliases = context.settings.jest?.globalAliases ?? {};
56
59
  const alias = Object.entries(globalAliases).find(([, aliases]) => aliases.includes(global));
57
60
  if (alias) {
58
61
  return alias[0];
@@ -79,9 +82,8 @@ const parseJestFnCallWithReason = (node, context) => {
79
82
  };
80
83
  exports.parseJestFnCallWithReason = parseJestFnCallWithReason;
81
84
  const parseJestFnCallWithReasonInner = (node, context) => {
82
- var _node$parent2, _node$parent3;
83
85
  const chain = getNodeChain(node);
84
- if (!(chain !== null && chain !== void 0 && chain.length)) {
86
+ if (!chain?.length) {
85
87
  return null;
86
88
  }
87
89
  const [first, ...rest] = chain;
@@ -127,8 +129,7 @@ const parseJestFnCallWithReasonInner = (node, context) => {
127
129
  return null;
128
130
  }
129
131
  if (result === 'matcher-not-found') {
130
- var _node$parent;
131
- if (((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) === _utils.AST_NODE_TYPES.MemberExpression) {
132
+ if (node.parent?.type === _utils.AST_NODE_TYPES.MemberExpression) {
132
133
  return 'matcher-not-called';
133
134
  }
134
135
  }
@@ -136,17 +137,14 @@ const parseJestFnCallWithReasonInner = (node, context) => {
136
137
  }
137
138
 
138
139
  // check that every link in the chain except the last is a member expression
139
- if (chain.slice(0, chain.length - 1).some(nod => {
140
- var _nod$parent;
141
- return ((_nod$parent = nod.parent) === null || _nod$parent === void 0 ? void 0 : _nod$parent.type) !== _utils.AST_NODE_TYPES.MemberExpression;
142
- })) {
140
+ if (chain.slice(0, chain.length - 1).some(nod => nod.parent?.type !== _utils.AST_NODE_TYPES.MemberExpression)) {
143
141
  return null;
144
142
  }
145
143
 
146
144
  // ensure that we're at the "top" of the function call chain otherwise when
147
145
  // parsing e.g. x().y.z(), we'll incorrectly find & parse "x()" even though
148
146
  // the full chain is not a valid jest function call chain
149
- 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) {
147
+ if (node.parent?.type === _utils.AST_NODE_TYPES.CallExpression || node.parent?.type === _utils.AST_NODE_TYPES.MemberExpression) {
150
148
  return null;
151
149
  }
152
150
  return {
@@ -157,10 +155,9 @@ const parseJestFnCallWithReasonInner = (node, context) => {
157
155
  const findModifiersAndMatcher = members => {
158
156
  const modifiers = [];
159
157
  for (const member of members) {
160
- var _member$parent, _member$parent$parent;
161
158
  // check if the member is being called, which means it is the matcher
162
159
  // (and also the end of the entire "expect" call chain)
163
- 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) {
160
+ if (member.parent?.type === _utils.AST_NODE_TYPES.MemberExpression && member.parent.parent?.type === _utils.AST_NODE_TYPES.CallExpression) {
164
161
  return {
165
162
  matcher: member,
166
163
  args: member.parent.parent.arguments,
@@ -245,7 +242,6 @@ const findImportSourceNode = node => {
245
242
  return null;
246
243
  };
247
244
  const describeVariableDefAsImport = def => {
248
- var _def$name$parent;
249
245
  // make sure that we've actually being assigned a value
250
246
  if (!def.node.init) {
251
247
  return null;
@@ -254,7 +250,7 @@ const describeVariableDefAsImport = def => {
254
250
  if (!sourceNode || !(0, _utils2.isStringNode)(sourceNode)) {
255
251
  return null;
256
252
  }
257
- if (((_def$name$parent = def.name.parent) === null || _def$name$parent === void 0 ? void 0 : _def$name$parent.type) !== _utils.AST_NODE_TYPES.Property) {
253
+ if (def.name.parent?.type !== _utils.AST_NODE_TYPES.Property) {
258
254
  return null;
259
255
  }
260
256
  if (!(0, _utils2.isSupportedAccessor)(def.name.parent.key)) {
@@ -293,7 +289,7 @@ const resolveScope = (scope, identifier) => {
293
289
  if (ref && ref.defs.length > 0) {
294
290
  const def = ref.defs[ref.defs.length - 1];
295
291
  const importDetails = describePossibleImportDef(def);
296
- if ((importDetails === null || importDetails === void 0 ? void 0 : importDetails.local) === identifier) {
292
+ if (importDetails?.local === identifier) {
297
293
  return importDetails;
298
294
  }
299
295
  return 'local';
@@ -19,9 +19,7 @@ var _default = exports.default = (0, _utils2.createRule)({
19
19
  meta: {
20
20
  type: 'problem',
21
21
  docs: {
22
- category: 'Possible Errors',
23
- description: 'Enforce valid `describe()` callback',
24
- recommended: 'error'
22
+ description: 'Enforce valid `describe()` callback'
25
23
  },
26
24
  messages: {
27
25
  nameAndCallback: 'Describe requires name and callback arguments',
@@ -37,7 +35,7 @@ var _default = exports.default = (0, _utils2.createRule)({
37
35
  return {
38
36
  CallExpression(node) {
39
37
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
40
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'describe') {
38
+ if (jestFnCall?.type !== 'describe') {
41
39
  return;
42
40
  }
43
41
  if (node.arguments.length < 1) {
@@ -24,7 +24,7 @@ const isPromiseChainCall = node => {
24
24
  };
25
25
  const isTestCaseCallWithCallbackArg = (node, context) => {
26
26
  const jestCallFn = (0, _utils2.parseJestFnCall)(node, context);
27
- if ((jestCallFn === null || jestCallFn === void 0 ? void 0 : jestCallFn.type) !== 'test') {
27
+ if (jestCallFn?.type !== 'test') {
28
28
  return false;
29
29
  }
30
30
  const isJestEach = jestCallFn.members.some(s => (0, _utils2.getAccessorValue)(s) === 'each');
@@ -67,10 +67,10 @@ const isPromiseMethodThatUsesValue = (node, identifier) => {
67
67
  */
68
68
  const isValueAwaitedInElements = (name, elements) => {
69
69
  for (const element of elements) {
70
- if ((element === null || element === void 0 ? void 0 : element.type) === _utils.AST_NODE_TYPES.AwaitExpression && (0, _utils2.isIdentifier)(element.argument, name)) {
70
+ if (element?.type === _utils.AST_NODE_TYPES.AwaitExpression && (0, _utils2.isIdentifier)(element.argument, name)) {
71
71
  return true;
72
72
  }
73
- if ((element === null || element === void 0 ? void 0 : element.type) === _utils.AST_NODE_TYPES.ArrayExpression && isValueAwaitedInElements(name, element.elements)) {
73
+ if (element?.type === _utils.AST_NODE_TYPES.ArrayExpression && isValueAwaitedInElements(name, element.elements)) {
74
74
  return true;
75
75
  }
76
76
  }
@@ -138,7 +138,7 @@ const isValueAwaitedOrReturned = (identifier, body, context) => {
138
138
  }
139
139
  const leftMostCall = getLeftMostCallExpression(node.expression);
140
140
  const jestFnCall = (0, _utils2.parseJestFnCall)(node.expression, context);
141
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'expect' && leftMostCall.arguments.length > 0 && (0, _utils2.isIdentifier)(leftMostCall.arguments[0], name)) {
141
+ if (jestFnCall?.type === 'expect' && leftMostCall.arguments.length > 0 && (0, _utils2.isIdentifier)(leftMostCall.arguments[0], name)) {
142
142
  if (jestFnCall.members.some(m => {
143
143
  const v = (0, _utils2.getAccessorValue)(m);
144
144
  return v === _utils2.ModifierName.resolves || v === _utils2.ModifierName.rejects;
@@ -154,10 +154,9 @@ const isValueAwaitedOrReturned = (identifier, body, context) => {
154
154
  // (re)assignment changes the runtime value, so if we've not found an
155
155
  // await or return already we act as if we've reached the end of the body
156
156
  if (node.expression.type === _utils.AST_NODE_TYPES.AssignmentExpression) {
157
- var _getNodeName;
158
157
  // unless we're assigning to the same identifier, in which case
159
158
  // we might be chaining off the existing promise value
160
- if ((0, _utils2.isIdentifier)(node.expression.left, name) && (_getNodeName = (0, _utils2.getNodeName)(node.expression.right)) !== null && _getNodeName !== void 0 && _getNodeName.startsWith(`${name}.`) && isPromiseChainCall(node.expression.right)) {
159
+ if ((0, _utils2.isIdentifier)(node.expression.left, name) && (0, _utils2.getNodeName)(node.expression.right)?.startsWith(`${name}.`) && isPromiseChainCall(node.expression.right)) {
161
160
  continue;
162
161
  }
163
162
  break;
@@ -185,9 +184,8 @@ const isDirectlyWithinTestCaseCall = (node, context) => {
185
184
  let parent = node;
186
185
  while (parent) {
187
186
  if ((0, _utils2.isFunction)(parent)) {
188
- var _parent;
189
187
  parent = parent.parent;
190
- return ((_parent = parent) === null || _parent === void 0 ? void 0 : _parent.type) === _utils.AST_NODE_TYPES.CallExpression && (0, _utils2.isTypeOfJestFnCall)(parent, context, ['test']);
188
+ return parent?.type === _utils.AST_NODE_TYPES.CallExpression && (0, _utils2.isTypeOfJestFnCall)(parent, context, ['test']);
191
189
  }
192
190
  parent = parent.parent;
193
191
  }
@@ -207,9 +205,7 @@ var _default = exports.default = (0, _utils2.createRule)({
207
205
  name: __filename,
208
206
  meta: {
209
207
  docs: {
210
- category: 'Best Practices',
211
- description: 'Require promises that have expectations in their chain to be valid',
212
- recommended: 'error'
208
+ description: 'Require promises that have expectations in their chain to be valid'
213
209
  },
214
210
  messages: {
215
211
  expectInFloatingPromise: 'This promise should either be returned or awaited to ensure the expects in its chain are called'
@@ -27,13 +27,9 @@ const getPromiseCallExpressionNode = node => {
27
27
  }
28
28
  return null;
29
29
  };
30
- const findPromiseCallExpressionNode = node => {
31
- var _node$parent;
32
- return (_node$parent = node.parent) !== null && _node$parent !== void 0 && _node$parent.parent && [_utils.AST_NODE_TYPES.CallExpression, _utils.AST_NODE_TYPES.ArrayExpression].includes(node.parent.type) ? getPromiseCallExpressionNode(node.parent) : null;
33
- };
30
+ const findPromiseCallExpressionNode = node => node.parent?.parent && [_utils.AST_NODE_TYPES.CallExpression, _utils.AST_NODE_TYPES.ArrayExpression].includes(node.parent.type) ? getPromiseCallExpressionNode(node.parent) : null;
34
31
  const getParentIfThenified = node => {
35
- var _node$parent2;
36
- const grandParentNode = (_node$parent2 = node.parent) === null || _node$parent2 === void 0 ? void 0 : _node$parent2.parent;
32
+ const grandParentNode = node.parent?.parent;
37
33
  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) {
38
34
  // Just in case `then`s are chained look one above.
39
35
  return getParentIfThenified(grandParentNode);
@@ -58,9 +54,7 @@ var _default = exports.default = (0, _utils2.createRule)({
58
54
  name: __filename,
59
55
  meta: {
60
56
  docs: {
61
- category: 'Best Practices',
62
- description: 'Enforce valid `expect()` usage',
63
- recommended: 'error'
57
+ description: 'Enforce valid `expect()` usage'
64
58
  },
65
59
  messages: {
66
60
  tooManyArgs: 'Expect takes at most {{ amount }} argument{{ s }}',
@@ -139,8 +133,7 @@ var _default = exports.default = (0, _utils2.createRule)({
139
133
  CallExpression(node) {
140
134
  const jestFnCall = (0, _utils2.parseJestFnCallWithReason)(node, context);
141
135
  if (typeof jestFnCall === 'string') {
142
- var _node$parent3;
143
- 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;
136
+ const reportingNode = node.parent?.type === _utils.AST_NODE_TYPES.MemberExpression ? findTopMostMemberExpression(node.parent).property : node;
144
137
  if (jestFnCall === 'matcher-not-found') {
145
138
  context.report({
146
139
  messageId: 'matcherNotFound',
@@ -162,13 +155,13 @@ var _default = exports.default = (0, _utils2.createRule)({
162
155
  return;
163
156
  }
164
157
  return;
165
- } else if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
158
+ } else if (jestFnCall?.type !== 'expect') {
166
159
  return;
167
160
  }
168
161
  const {
169
162
  parent: expect
170
163
  } = jestFnCall.head.node;
171
- if ((expect === null || expect === void 0 ? void 0 : expect.type) !== _utils.AST_NODE_TYPES.CallExpression) {
164
+ if (expect?.type !== _utils.AST_NODE_TYPES.CallExpression) {
172
165
  return;
173
166
  }
174
167
  if (expect.arguments.length < minArgs) {
@@ -222,7 +215,7 @@ var _default = exports.default = (0, _utils2.createRule)({
222
215
  } = jestFnCall;
223
216
  const parentNode = matcher.parent.parent;
224
217
  const shouldBeAwaited = jestFnCall.modifiers.some(nod => (0, _utils2.getAccessorValue)(nod) !== 'not') || asyncMatchers.includes((0, _utils2.getAccessorValue)(matcher));
225
- if (!(parentNode !== null && parentNode !== void 0 && parentNode.parent) || !shouldBeAwaited) {
218
+ if (!parentNode?.parent || !shouldBeAwaited) {
226
219
  return;
227
220
  }
228
221
  /**
@@ -49,9 +49,7 @@ var _default = exports.default = (0, _utils2.createRule)({
49
49
  name: __filename,
50
50
  meta: {
51
51
  docs: {
52
- category: 'Best Practices',
53
- description: 'Enforce valid titles',
54
- recommended: 'error'
52
+ description: 'Enforce valid titles'
55
53
  },
56
54
  messages: {
57
55
  titleMustBeString: 'Title must be a string',
@@ -93,6 +91,7 @@ var _default = exports.default = (0, _utils2.createRule)({
93
91
  type: 'string'
94
92
  }, MatcherAndMessageSchema, {
95
93
  type: 'object',
94
+ // @ts-expect-error https://github.com/eslint/eslint/discussions/17573
96
95
  propertyNames: {
97
96
  enum: ['describe', 'test', 'it']
98
97
  },
@@ -128,7 +127,7 @@ var _default = exports.default = (0, _utils2.createRule)({
128
127
  return {
129
128
  CallExpression(node) {
130
129
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
131
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'describe' && (jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'test') {
130
+ if (jestFnCall?.type !== 'describe' && jestFnCall?.type !== 'test') {
132
131
  return;
133
132
  }
134
133
  const [argument] = node.arguments;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-jest",
3
- "version": "28.0.0-next.1",
3
+ "version": "28.0.0-next.3",
4
4
  "description": "ESLint rules for Jest",
5
5
  "keywords": [
6
6
  "eslint",
@@ -95,7 +95,7 @@
95
95
  ]
96
96
  },
97
97
  "dependencies": {
98
- "@typescript-eslint/utils": "^5.10.0"
98
+ "@typescript-eslint/utils": "^6.0.0"
99
99
  },
100
100
  "devDependencies": {
101
101
  "@babel/cli": "^7.4.4",
@@ -107,7 +107,7 @@
107
107
  "@schemastore/package": "^0.0.10",
108
108
  "@semantic-release/changelog": "^6.0.0",
109
109
  "@semantic-release/git": "^10.0.0",
110
- "@tsconfig/node14": "^14.1.0",
110
+ "@tsconfig/node16": "^16.0.0",
111
111
  "@types/eslint": "^8.4.6",
112
112
  "@types/jest": "^29.0.0",
113
113
  "@types/node": "^14.18.26",
@@ -156,7 +156,7 @@
156
156
  },
157
157
  "packageManager": "yarn@3.8.1",
158
158
  "engines": {
159
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
159
+ "node": "^16.10.0 || >=18.0.0"
160
160
  },
161
161
  "publishConfig": {
162
162
  "provenance": true