eslint-plugin-jest 27.9.0 → 28.0.0-next.2

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 (48) hide show
  1. package/README.md +59 -61
  2. package/docs/rules/no-done-callback.md +1 -1
  3. package/docs/rules/no-focused-tests.md +1 -1
  4. package/docs/rules/prefer-equality-matcher.md +1 -1
  5. package/docs/rules/prefer-expect-assertions.md +1 -1
  6. package/docs/rules/prefer-strict-equal.md +1 -1
  7. package/docs/rules/unbound-method.md +3 -3
  8. package/lib/index.js +29 -13
  9. package/lib/rules/max-expects.js +2 -4
  10. package/lib/rules/no-alias-methods.js +1 -1
  11. package/lib/rules/no-deprecated-functions.js +1 -2
  12. package/lib/rules/no-done-callback.js +4 -6
  13. package/lib/rules/no-duplicate-hooks.js +3 -4
  14. package/lib/rules/no-focused-tests.js +1 -1
  15. package/lib/rules/no-hooks.js +1 -1
  16. package/lib/rules/no-interpolation-in-snapshots.js +1 -1
  17. package/lib/rules/no-large-snapshots.js +1 -1
  18. package/lib/rules/no-restricted-jest-methods.js +1 -1
  19. package/lib/rules/no-restricted-matchers.js +1 -1
  20. package/lib/rules/no-standalone-expect.js +4 -6
  21. package/lib/rules/no-test-prefixes.js +1 -1
  22. package/lib/rules/no-untyped-mock-factory.js +1 -1
  23. package/lib/rules/prefer-called-with.js +1 -1
  24. package/lib/rules/prefer-comparison-matcher.js +3 -3
  25. package/lib/rules/prefer-equality-matcher.js +3 -3
  26. package/lib/rules/prefer-expect-assertions.js +5 -7
  27. package/lib/rules/prefer-expect-resolves.js +3 -3
  28. package/lib/rules/prefer-hooks-in-order.js +1 -1
  29. package/lib/rules/prefer-mock-promise-shorthand.js +2 -3
  30. package/lib/rules/prefer-snapshot-hint.js +2 -2
  31. package/lib/rules/prefer-spy-on.js +1 -2
  32. package/lib/rules/prefer-strict-equal.js +1 -1
  33. package/lib/rules/prefer-to-be.js +2 -3
  34. package/lib/rules/prefer-to-contain.js +2 -2
  35. package/lib/rules/prefer-to-have-length.js +3 -3
  36. package/lib/rules/prefer-todo.js +1 -1
  37. package/lib/rules/require-hook.js +1 -2
  38. package/lib/rules/require-to-throw-message.js +1 -1
  39. package/lib/rules/unbound-method.js +6 -7
  40. package/lib/rules/utils/misc.js +1 -1
  41. package/lib/rules/utils/parseJestFnCall.js +8 -16
  42. package/lib/rules/valid-describe-callback.js +1 -1
  43. package/lib/rules/valid-expect-in-promise.js +6 -8
  44. package/lib/rules/valid-expect.js +6 -11
  45. package/lib/rules/valid-title.js +1 -1
  46. package/package.json +7 -7
  47. package/docs/rules/no-if.md +0 -58
  48. package/lib/rules/no-if.js +0 -86
@@ -9,14 +9,13 @@ var _utils2 = require("./utils");
9
9
  const isFirstStatement = node => {
10
10
  let parent = node;
11
11
  while (parent) {
12
- var _parent$parent, _parent$parent2;
13
- if (((_parent$parent = parent.parent) === null || _parent$parent === void 0 ? void 0 : _parent$parent.type) === _utils.AST_NODE_TYPES.BlockStatement) {
12
+ if (parent.parent?.type === _utils.AST_NODE_TYPES.BlockStatement) {
14
13
  return parent.parent.body[0] === parent;
15
14
  }
16
15
 
17
16
  // if we've hit an arrow function, then it must have a single expression
18
17
  // as its body, as otherwise we would have hit the block statement already
19
- if (((_parent$parent2 = parent.parent) === null || _parent$parent2 === void 0 ? void 0 : _parent$parent2.type) === _utils.AST_NODE_TYPES.ArrowFunctionExpression) {
18
+ if (parent.parent?.type === _utils.AST_NODE_TYPES.ArrowFunctionExpression) {
20
19
  return true;
21
20
  }
22
21
  parent = parent.parent;
@@ -150,13 +149,12 @@ var _default = exports.default = (0, _utils2.createRule)({
150
149
  'ForOfStatement:exit': exitForLoop,
151
150
  CallExpression(node) {
152
151
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
153
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'test') {
152
+ if (jestFnCall?.type === 'test') {
154
153
  inTestCaseCall = true;
155
154
  return;
156
155
  }
157
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'expect' && inTestCaseCall) {
158
- var _jestFnCall$head$node;
159
- if (expressionDepth === 1 && isFirstStatement(node) && ((_jestFnCall$head$node = jestFnCall.head.node.parent) === null || _jestFnCall$head$node === void 0 ? void 0 : _jestFnCall$head$node.type) === _utils.AST_NODE_TYPES.MemberExpression && jestFnCall.members.length === 1 && ['assertions', 'hasAssertions'].includes((0, _utils2.getAccessorValue)(jestFnCall.members[0]))) {
156
+ if (jestFnCall?.type === 'expect' && inTestCaseCall) {
157
+ if (expressionDepth === 1 && isFirstStatement(node) && jestFnCall.head.node.parent?.type === _utils.AST_NODE_TYPES.MemberExpression && jestFnCall.members.length === 1 && ['assertions', 'hasAssertions'].includes((0, _utils2.getAccessorValue)(jestFnCall.members[0]))) {
160
158
  checkExpectHasAssertions(jestFnCall, node);
161
159
  hasExpectAssertionsAsFirstStatement = true;
162
160
  }
@@ -25,17 +25,17 @@ var _default = exports.default = (0, _utils2.createRule)({
25
25
  create: context => ({
26
26
  CallExpression(node) {
27
27
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
28
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
28
+ if (jestFnCall?.type !== 'expect') {
29
29
  return;
30
30
  }
31
31
  const {
32
32
  parent
33
33
  } = jestFnCall.head.node;
34
- if ((parent === null || parent === void 0 ? void 0 : parent.type) !== _utils.AST_NODE_TYPES.CallExpression) {
34
+ if (parent?.type !== _utils.AST_NODE_TYPES.CallExpression) {
35
35
  return;
36
36
  }
37
37
  const [awaitNode] = parent.arguments;
38
- if ((awaitNode === null || awaitNode === void 0 ? void 0 : awaitNode.type) === _utils.AST_NODE_TYPES.AwaitExpression) {
38
+ if (awaitNode?.type === _utils.AST_NODE_TYPES.AwaitExpression) {
39
39
  context.report({
40
40
  node: awaitNode,
41
41
  messageId: 'expectResolves',
@@ -31,7 +31,7 @@ var _default = exports.default = (0, _utils.createRule)({
31
31
  return;
32
32
  }
33
33
  const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
34
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'hook') {
34
+ if (jestFnCall?.type !== 'hook') {
35
35
  // Reset the previousHookIndex when encountering something different from a hook
36
36
  previousHookIndex = -1;
37
37
  return;
@@ -10,11 +10,10 @@ const withOnce = (name, addOnce) => {
10
10
  return `${name}${addOnce ? 'Once' : ''}`;
11
11
  };
12
12
  const findSingleReturnArgumentNode = fnNode => {
13
- var _fnNode$body$body$;
14
13
  if (fnNode.body.type !== _utils.AST_NODE_TYPES.BlockStatement) {
15
14
  return fnNode.body;
16
15
  }
17
- if (((_fnNode$body$body$ = fnNode.body.body[0]) === null || _fnNode$body$body$ === void 0 ? void 0 : _fnNode$body$body$.type) === _utils.AST_NODE_TYPES.ReturnStatement) {
16
+ if (fnNode.body.body[0]?.type === _utils.AST_NODE_TYPES.ReturnStatement) {
18
17
  return fnNode.body.body[0].argument;
19
18
  }
20
19
  return null;
@@ -37,7 +36,7 @@ var _default = exports.default = (0, _utils2.createRule)({
37
36
  defaultOptions: [],
38
37
  create(context) {
39
38
  const report = (property, isOnce, outerArgNode, innerArgNode = outerArgNode) => {
40
- if ((innerArgNode === null || innerArgNode === void 0 ? void 0 : innerArgNode.type) !== _utils.AST_NODE_TYPES.CallExpression) {
39
+ if (innerArgNode?.type !== _utils.AST_NODE_TYPES.CallExpression) {
41
40
  return;
42
41
  }
43
42
  const argName = (0, _utils2.getNodeName)(innerArgNode);
@@ -95,8 +95,8 @@ var _default = exports.default = (0, _utils.createRule)({
95
95
  },
96
96
  CallExpression(node) {
97
97
  const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
98
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
99
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'describe' || (jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'test') {
98
+ if (jestFnCall?.type !== 'expect') {
99
+ if (jestFnCall?.type === 'describe' || jestFnCall?.type === 'test') {
100
100
  depths.push(expressionDepth);
101
101
  expressionDepth = 0;
102
102
  }
@@ -29,8 +29,7 @@ const getJestFnCall = node => {
29
29
  return getJestFnCall(obj);
30
30
  };
31
31
  const getAutoFixMockImplementation = (jestFnCall, context) => {
32
- var _jestFnCall$parent;
33
- const hasMockImplementationAlready = ((_jestFnCall$parent = jestFnCall.parent) === null || _jestFnCall$parent === void 0 ? void 0 : _jestFnCall$parent.type) === _utils.AST_NODE_TYPES.MemberExpression && jestFnCall.parent.property.type === _utils.AST_NODE_TYPES.Identifier && jestFnCall.parent.property.name === 'mockImplementation';
32
+ const hasMockImplementationAlready = jestFnCall.parent?.type === _utils.AST_NODE_TYPES.MemberExpression && jestFnCall.parent.property.type === _utils.AST_NODE_TYPES.Identifier && jestFnCall.parent.property.name === 'mockImplementation';
34
33
  if (hasMockImplementationAlready) {
35
34
  return '';
36
35
  }
@@ -26,7 +26,7 @@ var _default = exports.default = (0, _utils.createRule)({
26
26
  return {
27
27
  CallExpression(node) {
28
28
  const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
29
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
29
+ if (jestFnCall?.type !== 'expect') {
30
30
  return;
31
31
  }
32
32
  const {
@@ -30,9 +30,8 @@ const reportPreferToBe = (context, whatToBe, expectFnCall, func, modifierNode) =
30
30
  context.report({
31
31
  messageId: `useToBe${whatToBe}`,
32
32
  fix(fixer) {
33
- var _expectFnCall$args;
34
33
  const fixes = [(0, _utils2.replaceAccessorFixer)(fixer, expectFnCall.matcher, `toBe${whatToBe}`)];
35
- if ((_expectFnCall$args = expectFnCall.args) !== null && _expectFnCall$args !== void 0 && _expectFnCall$args.length && whatToBe !== '') {
34
+ if (expectFnCall.args?.length && whatToBe !== '') {
36
35
  fixes.push((0, _utils2.removeExtraArgumentsFixer)(fixer, context, func, 0));
37
36
  }
38
37
  if (modifierNode) {
@@ -67,7 +66,7 @@ var _default = exports.default = (0, _utils2.createRule)({
67
66
  return {
68
67
  CallExpression(node) {
69
68
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
70
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
69
+ if (jestFnCall?.type !== 'expect') {
71
70
  return;
72
71
  }
73
72
  const matcherName = (0, _utils2.getAccessorValue)(jestFnCall.matcher);
@@ -37,13 +37,13 @@ var _default = exports.default = (0, _utils2.createRule)({
37
37
  return {
38
38
  CallExpression(node) {
39
39
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
40
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect' || jestFnCall.args.length === 0) {
40
+ if (jestFnCall?.type !== 'expect' || jestFnCall.args.length === 0) {
41
41
  return;
42
42
  }
43
43
  const {
44
44
  parent: expect
45
45
  } = jestFnCall.head.node;
46
- if ((expect === null || expect === void 0 ? void 0 : expect.type) !== _utils.AST_NODE_TYPES.CallExpression) {
46
+ if (expect?.type !== _utils.AST_NODE_TYPES.CallExpression) {
47
47
  return;
48
48
  }
49
49
  const {
@@ -26,20 +26,20 @@ var _default = exports.default = (0, _utils2.createRule)({
26
26
  return {
27
27
  CallExpression(node) {
28
28
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
29
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
29
+ if (jestFnCall?.type !== 'expect') {
30
30
  return;
31
31
  }
32
32
  const {
33
33
  parent: expect
34
34
  } = jestFnCall.head.node;
35
- if ((expect === null || expect === void 0 ? void 0 : expect.type) !== _utils.AST_NODE_TYPES.CallExpression) {
35
+ if (expect?.type !== _utils.AST_NODE_TYPES.CallExpression) {
36
36
  return;
37
37
  }
38
38
  const [argument] = expect.arguments;
39
39
  const {
40
40
  matcher
41
41
  } = jestFnCall;
42
- if (!_utils2.EqualityMatcher.hasOwnProperty((0, _utils2.getAccessorValue)(matcher)) || (argument === null || argument === void 0 ? void 0 : argument.type) !== _utils.AST_NODE_TYPES.MemberExpression || !(0, _utils2.isSupportedAccessor)(argument.property, 'length')) {
42
+ if (!_utils2.EqualityMatcher.hasOwnProperty((0, _utils2.getAccessorValue)(matcher)) || argument?.type !== _utils.AST_NODE_TYPES.MemberExpression || !(0, _utils2.isSupportedAccessor)(argument.property, 'length')) {
43
43
  return;
44
44
  }
45
45
  context.report({
@@ -51,7 +51,7 @@ var _default = exports.default = (0, _utils2.createRule)({
51
51
  CallExpression(node) {
52
52
  const [title, callback] = node.arguments;
53
53
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
54
- if (!title || (jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'test' || !isTargetedTestCase(jestFnCall) || !(0, _utils2.isStringNode)(title)) {
54
+ if (!title || jestFnCall?.type !== 'test' || !isTargetedTestCase(jestFnCall) || !(0, _utils2.isStringNode)(title)) {
55
55
  return;
56
56
  }
57
57
  if (callback && isEmptyFunction(callback)) {
@@ -7,11 +7,10 @@ exports.default = void 0;
7
7
  var _utils = require("@typescript-eslint/utils");
8
8
  var _utils2 = require("./utils");
9
9
  const isJestFnCall = (node, context) => {
10
- var _getNodeName;
11
10
  if ((0, _utils2.parseJestFnCall)(node, context)) {
12
11
  return true;
13
12
  }
14
- return !!((_getNodeName = (0, _utils2.getNodeName)(node)) !== null && _getNodeName !== void 0 && _getNodeName.startsWith('jest.'));
13
+ return !!(0, _utils2.getNodeName)(node)?.startsWith('jest.');
15
14
  };
16
15
  const isNullOrUndefined = node => {
17
16
  return node.type === _utils.AST_NODE_TYPES.Literal && node.value === null || (0, _utils2.isIdentifier)(node, 'undefined');
@@ -24,7 +24,7 @@ var _default = exports.default = (0, _utils.createRule)({
24
24
  return {
25
25
  CallExpression(node) {
26
26
  const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
27
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
27
+ if (jestFnCall?.type !== 'expect') {
28
28
  return;
29
29
  }
30
30
  const {
@@ -34,27 +34,26 @@ var _default = exports.default = (0, _utils2.createRule)({
34
34
  },
35
35
  schema: [],
36
36
  type: 'problem',
37
- ...(baseRule === null || baseRule === void 0 ? void 0 : baseRule.meta),
37
+ ...baseRule?.meta,
38
38
  docs: {
39
39
  category: 'Best Practices',
40
40
  description: 'Enforce unbound methods are called with their expected scope',
41
41
  requiresTypeChecking: true,
42
- ...(baseRule === null || baseRule === void 0 ? void 0 : baseRule.meta.docs),
42
+ ...baseRule?.meta.docs,
43
43
  recommended: false
44
44
  }
45
45
  },
46
46
  create(context) {
47
- const baseSelectors = baseRule === null || baseRule === void 0 ? void 0 : baseRule.create(context);
47
+ const baseSelectors = baseRule?.create(context);
48
48
  if (!baseSelectors) {
49
49
  return {};
50
50
  }
51
51
  return {
52
52
  ...baseSelectors,
53
53
  MemberExpression(node) {
54
- var _node$parent, _baseSelectors$Member;
55
- if (((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) === _utils.AST_NODE_TYPES.CallExpression) {
54
+ if (node.parent?.type === _utils.AST_NODE_TYPES.CallExpression) {
56
55
  const jestFnCall = (0, _utils2.parseJestFnCall)((0, _utils2.findTopMostCallExpression)(node.parent), context);
57
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'expect') {
56
+ if (jestFnCall?.type === 'expect') {
58
57
  const {
59
58
  matcher
60
59
  } = jestFnCall;
@@ -63,7 +62,7 @@ var _default = exports.default = (0, _utils2.createRule)({
63
62
  }
64
63
  }
65
64
  }
66
- (_baseSelectors$Member = baseSelectors.MemberExpression) === null || _baseSelectors$Member === void 0 || _baseSelectors$Member.call(baseSelectors, node);
65
+ baseSelectors.MemberExpression?.(node);
67
66
  }
68
67
  };
69
68
  }
@@ -103,7 +103,7 @@ const getTestCallExpressionsFromDeclaredVariables = (declaredVariables, context)
103
103
  references
104
104
  }) => acc.concat(references.map(({
105
105
  identifier
106
- }) => identifier.parent).filter(node => (node === null || node === void 0 ? void 0 : node.type) === _utils.AST_NODE_TYPES.CallExpression && (0, _parseJestFnCall.isTypeOfJestFnCall)(node, context, ['test']))), []);
106
+ }) => identifier.parent).filter(node => node?.type === _utils.AST_NODE_TYPES.CallExpression && (0, _parseJestFnCall.isTypeOfJestFnCall)(node, context, ['test']))), []);
107
107
  };
108
108
 
109
109
  /**
@@ -51,8 +51,7 @@ const determineJestFnType = name => {
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
53
  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) ?? {};
54
+ const globalAliases = context.settings.jest?.globalAliases ?? {};
56
55
  const alias = Object.entries(globalAliases).find(([, aliases]) => aliases.includes(global));
57
56
  if (alias) {
58
57
  return alias[0];
@@ -79,9 +78,8 @@ const parseJestFnCallWithReason = (node, context) => {
79
78
  };
80
79
  exports.parseJestFnCallWithReason = parseJestFnCallWithReason;
81
80
  const parseJestFnCallWithReasonInner = (node, context) => {
82
- var _node$parent2, _node$parent3;
83
81
  const chain = getNodeChain(node);
84
- if (!(chain !== null && chain !== void 0 && chain.length)) {
82
+ if (!chain?.length) {
85
83
  return null;
86
84
  }
87
85
  const [first, ...rest] = chain;
@@ -127,8 +125,7 @@ const parseJestFnCallWithReasonInner = (node, context) => {
127
125
  return null;
128
126
  }
129
127
  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) {
128
+ if (node.parent?.type === _utils.AST_NODE_TYPES.MemberExpression) {
132
129
  return 'matcher-not-called';
133
130
  }
134
131
  }
@@ -136,17 +133,14 @@ const parseJestFnCallWithReasonInner = (node, context) => {
136
133
  }
137
134
 
138
135
  // 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
- })) {
136
+ if (chain.slice(0, chain.length - 1).some(nod => nod.parent?.type !== _utils.AST_NODE_TYPES.MemberExpression)) {
143
137
  return null;
144
138
  }
145
139
 
146
140
  // ensure that we're at the "top" of the function call chain otherwise when
147
141
  // parsing e.g. x().y.z(), we'll incorrectly find & parse "x()" even though
148
142
  // 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) {
143
+ if (node.parent?.type === _utils.AST_NODE_TYPES.CallExpression || node.parent?.type === _utils.AST_NODE_TYPES.MemberExpression) {
150
144
  return null;
151
145
  }
152
146
  return {
@@ -157,10 +151,9 @@ const parseJestFnCallWithReasonInner = (node, context) => {
157
151
  const findModifiersAndMatcher = members => {
158
152
  const modifiers = [];
159
153
  for (const member of members) {
160
- var _member$parent, _member$parent$parent;
161
154
  // check if the member is being called, which means it is the matcher
162
155
  // (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) {
156
+ if (member.parent?.type === _utils.AST_NODE_TYPES.MemberExpression && member.parent.parent?.type === _utils.AST_NODE_TYPES.CallExpression) {
164
157
  return {
165
158
  matcher: member,
166
159
  args: member.parent.parent.arguments,
@@ -245,7 +238,6 @@ const findImportSourceNode = node => {
245
238
  return null;
246
239
  };
247
240
  const describeVariableDefAsImport = def => {
248
- var _def$name$parent;
249
241
  // make sure that we've actually being assigned a value
250
242
  if (!def.node.init) {
251
243
  return null;
@@ -254,7 +246,7 @@ const describeVariableDefAsImport = def => {
254
246
  if (!sourceNode || !(0, _utils2.isStringNode)(sourceNode)) {
255
247
  return null;
256
248
  }
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) {
249
+ if (def.name.parent?.type !== _utils.AST_NODE_TYPES.Property) {
258
250
  return null;
259
251
  }
260
252
  if (!(0, _utils2.isSupportedAccessor)(def.name.parent.key)) {
@@ -293,7 +285,7 @@ const resolveScope = (scope, identifier) => {
293
285
  if (ref && ref.defs.length > 0) {
294
286
  const def = ref.defs[ref.defs.length - 1];
295
287
  const importDetails = describePossibleImportDef(def);
296
- if ((importDetails === null || importDetails === void 0 ? void 0 : importDetails.local) === identifier) {
288
+ if (importDetails?.local === identifier) {
297
289
  return importDetails;
298
290
  }
299
291
  return 'local';
@@ -37,7 +37,7 @@ var _default = exports.default = (0, _utils2.createRule)({
37
37
  return {
38
38
  CallExpression(node) {
39
39
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
40
- if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'describe') {
40
+ if (jestFnCall?.type !== 'describe') {
41
41
  return;
42
42
  }
43
43
  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
  }
@@ -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);
@@ -139,8 +135,7 @@ var _default = exports.default = (0, _utils2.createRule)({
139
135
  CallExpression(node) {
140
136
  const jestFnCall = (0, _utils2.parseJestFnCallWithReason)(node, context);
141
137
  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;
138
+ const reportingNode = node.parent?.type === _utils.AST_NODE_TYPES.MemberExpression ? findTopMostMemberExpression(node.parent).property : node;
144
139
  if (jestFnCall === 'matcher-not-found') {
145
140
  context.report({
146
141
  messageId: 'matcherNotFound',
@@ -162,13 +157,13 @@ var _default = exports.default = (0, _utils2.createRule)({
162
157
  return;
163
158
  }
164
159
  return;
165
- } else if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
160
+ } else if (jestFnCall?.type !== 'expect') {
166
161
  return;
167
162
  }
168
163
  const {
169
164
  parent: expect
170
165
  } = jestFnCall.head.node;
171
- if ((expect === null || expect === void 0 ? void 0 : expect.type) !== _utils.AST_NODE_TYPES.CallExpression) {
166
+ if (expect?.type !== _utils.AST_NODE_TYPES.CallExpression) {
172
167
  return;
173
168
  }
174
169
  if (expect.arguments.length < minArgs) {
@@ -222,7 +217,7 @@ var _default = exports.default = (0, _utils2.createRule)({
222
217
  } = jestFnCall;
223
218
  const parentNode = matcher.parent.parent;
224
219
  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) {
220
+ if (!parentNode?.parent || !shouldBeAwaited) {
226
221
  return;
227
222
  }
228
223
  /**
@@ -128,7 +128,7 @@ var _default = exports.default = (0, _utils2.createRule)({
128
128
  return {
129
129
  CallExpression(node) {
130
130
  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') {
131
+ if (jestFnCall?.type !== 'describe' && jestFnCall?.type !== 'test') {
132
132
  return;
133
133
  }
134
134
  const [argument] = node.arguments;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-jest",
3
- "version": "27.9.0",
3
+ "version": "28.0.0-next.2",
4
4
  "description": "ESLint rules for Jest",
5
5
  "keywords": [
6
6
  "eslint",
@@ -21,7 +21,7 @@
21
21
  ],
22
22
  "scripts": {
23
23
  "build": "babel --extensions .js,.ts src --out-dir lib --copy-files && rimraf --glob lib/__tests__ 'lib/**/__tests__'",
24
- "_postinstall": "is-ci || husky install",
24
+ "_postinstall": "is-ci || husky",
25
25
  "lint": "eslint . --ignore-pattern '!.eslintrc.js' --ext js,ts",
26
26
  "prepack": "rimraf lib && yarn build",
27
27
  "prepublishOnly": "pinst --disable",
@@ -126,7 +126,7 @@
126
126
  "eslint-plugin-prettier": "^5.0.0",
127
127
  "eslint-remote-tester": "^3.0.0",
128
128
  "eslint-remote-tester-repositories": "~1.0.0",
129
- "husky": "^8.0.1",
129
+ "husky": "^9.0.1",
130
130
  "is-ci": "^3.0.0",
131
131
  "jest": "^29.0.0",
132
132
  "jest-runner-eslint": "^2.0.0",
@@ -135,7 +135,7 @@
135
135
  "pinst": "^3.0.0",
136
136
  "prettier": "^3.0.0",
137
137
  "rimraf": "^5.0.0",
138
- "semantic-release": "^22.0.0",
138
+ "semantic-release": "^23.0.0",
139
139
  "semver": "^7.3.5",
140
140
  "strip-ansi": "^6.0.0",
141
141
  "ts-node": "^10.2.1",
@@ -154,14 +154,14 @@
154
154
  "optional": true
155
155
  }
156
156
  },
157
- "packageManager": "yarn@3.8.0",
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
163
163
  },
164
164
  "resolutions": {
165
- "typescript": "~5.2.2"
165
+ "@typescript-eslint/typescript-estree@5.62.0": "patch:@typescript-eslint/typescript-estree@npm:^5.62.0#./.yarn/patches/@typescript-eslint-typescript-estree-npm-5.62.0-5d1ea132a9.patch"
166
166
  }
167
167
  }
@@ -1,58 +0,0 @@
1
- # Disallow conditional logic (`no-if`)
2
-
3
- ❌ This rule is deprecated. It was replaced by
4
- [`jest/no-conditional-in-test`](no-conditional-in-test.md).
5
-
6
- <!-- end auto-generated rule header -->
7
-
8
- Conditional logic in tests is usually an indication that a test is attempting to
9
- cover too much, and not testing the logic it intends to. Each branch of code
10
- executing within an if statement will usually be better served by a test devoted
11
- to it.
12
-
13
- Conditionals are often used to satisfy the typescript type checker. In these
14
- cases, using the non-null assertion operator (!) would be best.
15
-
16
- ## Rule details
17
-
18
- This rule prevents the use of if/ else statements and conditional (ternary)
19
- operations in tests.
20
-
21
- The following patterns are considered warnings:
22
-
23
- ```js
24
- it('foo', () => {
25
- if ('bar') {
26
- // an if statement here is invalid
27
- // you are probably testing too much
28
- }
29
- });
30
-
31
- it('foo', () => {
32
- const bar = foo ? 'bar' : null;
33
- });
34
- ```
35
-
36
- These patterns would not be considered warnings:
37
-
38
- ```js
39
- it('foo', () => {
40
- // only test the 'foo' case
41
- });
42
-
43
- it('bar', () => {
44
- // test the 'bar' case separately
45
- });
46
-
47
- it('foo', () => {
48
- function foo(bar) {
49
- // nested functions are valid
50
- return foo ? bar : null;
51
- }
52
- });
53
- ```
54
-
55
- ## When Not To Use It
56
-
57
- If you do not wish to prevent the use of if statements in tests, you can safely
58
- disable this rule.