eslint-plugin-jest 26.1.1 → 26.5.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 (59) hide show
  1. package/README.md +50 -2
  2. package/docs/rules/no-conditional-expect.md +1 -1
  3. package/docs/rules/no-deprecated-functions.md +1 -2
  4. package/docs/rules/no-identical-title.md +1 -1
  5. package/docs/rules/no-jasmine-globals.md +2 -2
  6. package/docs/rules/no-jest-import.md +1 -1
  7. package/docs/rules/no-large-snapshots.md +2 -2
  8. package/docs/rules/no-standalone-expect.md +1 -1
  9. package/docs/rules/prefer-comparison-matcher.md +1 -1
  10. package/docs/rules/prefer-equality-matcher.md +1 -1
  11. package/docs/rules/prefer-expect-assertions.md +1 -1
  12. package/docs/rules/prefer-hooks-in-order.md +133 -0
  13. package/docs/rules/prefer-hooks-on-top.md +1 -1
  14. package/docs/rules/prefer-lowercase-title.md +2 -2
  15. package/docs/rules/valid-expect.md +2 -2
  16. package/lib/rules/consistent-test-it.js +9 -8
  17. package/lib/rules/expect-expect.js +4 -4
  18. package/lib/rules/max-nested-describe.js +2 -2
  19. package/lib/rules/no-alias-methods.js +1 -1
  20. package/lib/rules/no-conditional-expect.js +3 -3
  21. package/lib/rules/no-conditional-in-test.js +2 -2
  22. package/lib/rules/no-deprecated-functions.js +1 -3
  23. package/lib/rules/no-disabled-tests.js +36 -61
  24. package/lib/rules/no-done-callback.js +6 -4
  25. package/lib/rules/no-duplicate-hooks.js +23 -23
  26. package/lib/rules/no-export.js +1 -1
  27. package/lib/rules/no-focused-tests.js +40 -43
  28. package/lib/rules/no-hooks.js +4 -2
  29. package/lib/rules/no-identical-title.js +10 -7
  30. package/lib/rules/no-if.js +6 -4
  31. package/lib/rules/no-restricted-matchers.js +39 -43
  32. package/lib/rules/no-standalone-expect.js +5 -5
  33. package/lib/rules/no-test-prefixes.js +12 -20
  34. package/lib/rules/no-test-return-statement.js +5 -2
  35. package/lib/rules/prefer-called-with.js +14 -13
  36. package/lib/rules/prefer-comparison-matcher.js +9 -4
  37. package/lib/rules/prefer-equality-matcher.js +15 -5
  38. package/lib/rules/prefer-expect-assertions.js +4 -2
  39. package/lib/rules/prefer-hooks-in-order.js +84 -0
  40. package/lib/rules/prefer-hooks-on-top.js +2 -2
  41. package/lib/rules/prefer-lowercase-title.js +12 -22
  42. package/lib/rules/prefer-snapshot-hint.js +34 -3
  43. package/lib/rules/prefer-strict-equal.js +1 -1
  44. package/lib/rules/prefer-to-be.js +1 -1
  45. package/lib/rules/prefer-todo.js +22 -7
  46. package/lib/rules/require-hook.js +7 -7
  47. package/lib/rules/require-top-level-describe.js +10 -4
  48. package/lib/rules/utils/accessors.js +135 -0
  49. package/lib/rules/{detectJestVersion.js → utils/detectJestVersion.js} +0 -0
  50. package/lib/rules/utils/followTypeAssertionChain.js +14 -0
  51. package/lib/rules/utils/index.js +83 -0
  52. package/lib/rules/utils/misc.js +120 -0
  53. package/lib/rules/utils/parseExpectCall.js +145 -0
  54. package/lib/rules/utils/parseJestFnCall.js +323 -0
  55. package/lib/rules/valid-describe-callback.js +4 -2
  56. package/lib/rules/valid-expect-in-promise.js +13 -15
  57. package/lib/rules/valid-title.js +8 -6
  58. package/package.json +9 -12
  59. package/lib/rules/utils.js +0 -513
@@ -9,16 +9,18 @@ var _utils = require("@typescript-eslint/utils");
9
9
 
10
10
  var _utils2 = require("./utils");
11
11
 
12
- const findCallbackArg = (node, isJestEach) => {
12
+ const findCallbackArg = (node, isJestEach, context) => {
13
13
  if (isJestEach) {
14
14
  return node.arguments[1];
15
15
  }
16
16
 
17
- if ((0, _utils2.isHook)(node) && node.arguments.length >= 1) {
17
+ const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
18
+
19
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'hook' && node.arguments.length >= 1) {
18
20
  return node.arguments[0];
19
21
  }
20
22
 
21
- if ((0, _utils2.isTestCaseCall)(node) && node.arguments.length >= 2) {
23
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'test' && node.arguments.length >= 2) {
22
24
  return node.arguments[1];
23
25
  }
24
26
 
@@ -60,7 +62,7 @@ var _default = (0, _utils2.createRule)({
60
62
  return;
61
63
  }
62
64
 
63
- const callback = findCallbackArg(node, isJestEach);
65
+ const callback = findCallbackArg(node, isJestEach, context);
64
66
  const callbackArgIndex = Number(isJestEach);
65
67
 
66
68
  if (!callback || !(0, _utils2.isFunction)(callback) || callback.params.length !== 1 + callbackArgIndex) {
@@ -7,13 +7,6 @@ exports.default = void 0;
7
7
 
8
8
  var _utils = require("./utils");
9
9
 
10
- const newHookContext = () => ({
11
- beforeAll: 0,
12
- beforeEach: 0,
13
- afterAll: 0,
14
- afterEach: 0
15
- });
16
-
17
10
  var _default = (0, _utils.createRule)({
18
11
  name: __filename,
19
12
  meta: {
@@ -31,31 +24,38 @@ var _default = (0, _utils.createRule)({
31
24
  defaultOptions: [],
32
25
 
33
26
  create(context) {
34
- const hookContexts = [newHookContext()];
27
+ const hookContexts = [{}];
35
28
  return {
36
29
  CallExpression(node) {
37
- if ((0, _utils.isDescribeCall)(node)) {
38
- hookContexts.push(newHookContext());
30
+ var _jestFnCall$name;
31
+
32
+ const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
33
+
34
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'describe') {
35
+ hookContexts.push({});
36
+ }
37
+
38
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'hook') {
39
+ return;
39
40
  }
40
41
 
41
- if ((0, _utils.isHook)(node)) {
42
- const currentLayer = hookContexts[hookContexts.length - 1];
43
- currentLayer[node.callee.name] += 1;
42
+ const currentLayer = hookContexts[hookContexts.length - 1];
43
+ currentLayer[_jestFnCall$name = jestFnCall.name] || (currentLayer[_jestFnCall$name] = 0);
44
+ currentLayer[jestFnCall.name] += 1;
44
45
 
45
- if (currentLayer[node.callee.name] > 1) {
46
- context.report({
47
- messageId: 'noDuplicateHook',
48
- data: {
49
- hook: node.callee.name
50
- },
51
- node
52
- });
53
- }
46
+ if (currentLayer[jestFnCall.name] > 1) {
47
+ context.report({
48
+ messageId: 'noDuplicateHook',
49
+ data: {
50
+ hook: jestFnCall.name
51
+ },
52
+ node
53
+ });
54
54
  }
55
55
  },
56
56
 
57
57
  'CallExpression:exit'(node) {
58
- if ((0, _utils.isDescribeCall)(node)) {
58
+ if ((0, _utils.isTypeOfJestFnCall)(node, context, ['describe'])) {
59
59
  hookContexts.pop();
60
60
  }
61
61
  }
@@ -41,7 +41,7 @@ var _default = (0, _utils2.createRule)({
41
41
  },
42
42
 
43
43
  CallExpression(node) {
44
- if ((0, _utils2.isTestCaseCall)(node)) {
44
+ if ((0, _utils2.isTypeOfJestFnCall)(node, context, ['test'])) {
45
45
  hasTestCase = true;
46
46
  }
47
47
  },
@@ -9,24 +9,6 @@ var _utils = require("@typescript-eslint/utils");
9
9
 
10
10
  var _utils2 = require("./utils");
11
11
 
12
- const findOnlyNode = node => {
13
- const callee = node.callee.type === _utils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _utils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
14
-
15
- if (callee.type === _utils.AST_NODE_TYPES.MemberExpression) {
16
- if (callee.object.type === _utils.AST_NODE_TYPES.MemberExpression) {
17
- if ((0, _utils2.isSupportedAccessor)(callee.object.property, 'only')) {
18
- return callee.object.property;
19
- }
20
- }
21
-
22
- if ((0, _utils2.isSupportedAccessor)(callee.property, 'only')) {
23
- return callee.property;
24
- }
25
- }
26
-
27
- return null;
28
- };
29
-
30
12
  var _default = (0, _utils2.createRule)({
31
13
  name: __filename,
32
14
  meta: {
@@ -45,41 +27,56 @@ var _default = (0, _utils2.createRule)({
45
27
  hasSuggestions: true
46
28
  },
47
29
  defaultOptions: [],
48
- create: context => ({
49
- CallExpression(node) {
50
- if (!(0, _utils2.isDescribeCall)(node) && !(0, _utils2.isTestCaseCall)(node)) {
51
- return;
52
- }
53
30
 
54
- if ((0, _utils2.getNodeName)(node).startsWith('f')) {
31
+ create(context) {
32
+ return {
33
+ CallExpression(node) {
34
+ const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
35
+
36
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'test' && (jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'describe') {
37
+ return;
38
+ }
39
+
40
+ if (jestFnCall.name.startsWith('f')) {
41
+ context.report({
42
+ messageId: 'focusedTest',
43
+ node,
44
+ suggest: [{
45
+ messageId: 'suggestRemoveFocus',
46
+
47
+ fix(fixer) {
48
+ // don't apply the fixer if we're an aliased import
49
+ if (jestFnCall.head.type === 'import' && jestFnCall.name !== jestFnCall.head.local) {
50
+ return null;
51
+ }
52
+
53
+ return fixer.removeRange([node.range[0], node.range[0] + 1]);
54
+ }
55
+
56
+ }]
57
+ });
58
+ return;
59
+ }
60
+
61
+ const onlyNode = jestFnCall.members.find(s => (0, _utils2.getAccessorValue)(s) === 'only');
62
+
63
+ if (!onlyNode) {
64
+ return;
65
+ }
66
+
55
67
  context.report({
56
68
  messageId: 'focusedTest',
57
- node,
69
+ node: onlyNode,
58
70
  suggest: [{
59
71
  messageId: 'suggestRemoveFocus',
60
- fix: fixer => fixer.removeRange([node.range[0], node.range[0] + 1])
72
+ fix: fixer => fixer.removeRange([onlyNode.range[0] - 1, onlyNode.range[1] + Number(onlyNode.type !== _utils.AST_NODE_TYPES.Identifier)])
61
73
  }]
62
74
  });
63
- return;
64
75
  }
65
76
 
66
- const onlyNode = findOnlyNode(node);
67
-
68
- if (!onlyNode) {
69
- return;
70
- }
77
+ };
78
+ }
71
79
 
72
- context.report({
73
- messageId: 'focusedTest',
74
- node: onlyNode,
75
- suggest: [{
76
- messageId: 'suggestRemoveFocus',
77
- fix: fixer => fixer.removeRange([onlyNode.range[0] - 1, onlyNode.range[1] + Number(onlyNode.type !== _utils.AST_NODE_TYPES.Identifier)])
78
- }]
79
- });
80
- }
81
-
82
- })
83
80
  });
84
81
 
85
82
  exports.default = _default;
@@ -39,12 +39,14 @@ var _default = (0, _utils.createRule)({
39
39
  }]) {
40
40
  return {
41
41
  CallExpression(node) {
42
- if ((0, _utils.isHook)(node) && !allow.includes(node.callee.name)) {
42
+ const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
43
+
44
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'hook' && !allow.includes(jestFnCall.name)) {
43
45
  context.report({
44
46
  node,
45
47
  messageId: 'unexpectedHook',
46
48
  data: {
47
- hookName: node.callee.name
49
+ hookName: jestFnCall.name
48
50
  }
49
51
  });
50
52
  }
@@ -33,15 +33,18 @@ var _default = (0, _utils.createRule)({
33
33
  const contexts = [newDescribeContext()];
34
34
  return {
35
35
  CallExpression(node) {
36
- var _getNodeName;
37
-
38
36
  const currentLayer = contexts[contexts.length - 1];
37
+ const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
38
+
39
+ if (!jestFnCall) {
40
+ return;
41
+ }
39
42
 
40
- if ((0, _utils.isDescribeCall)(node)) {
43
+ if (jestFnCall.type === 'describe') {
41
44
  contexts.push(newDescribeContext());
42
45
  }
43
46
 
44
- if ((_getNodeName = (0, _utils.getNodeName)(node.callee)) !== null && _getNodeName !== void 0 && _getNodeName.endsWith('.each')) {
47
+ if (jestFnCall.members.find(s => (0, _utils.isSupportedAccessor)(s, 'each'))) {
45
48
  return;
46
49
  }
47
50
 
@@ -53,7 +56,7 @@ var _default = (0, _utils.createRule)({
53
56
 
54
57
  const title = (0, _utils.getStringValue)(argument);
55
58
 
56
- if ((0, _utils.isTestCaseCall)(node)) {
59
+ if (jestFnCall.type === 'test') {
57
60
  if (currentLayer.testTitles.includes(title)) {
58
61
  context.report({
59
62
  messageId: 'multipleTestTitle',
@@ -64,7 +67,7 @@ var _default = (0, _utils.createRule)({
64
67
  currentLayer.testTitles.push(title);
65
68
  }
66
69
 
67
- if (!(0, _utils.isDescribeCall)(node)) {
70
+ if (jestFnCall.type !== 'describe') {
68
71
  return;
69
72
  }
70
73
 
@@ -79,7 +82,7 @@ var _default = (0, _utils.createRule)({
79
82
  },
80
83
 
81
84
  'CallExpression:exit'(node) {
82
- if ((0, _utils.isDescribeCall)(node)) {
85
+ if ((0, _utils.isTypeOfJestFnCall)(node, context, ['describe'])) {
83
86
  contexts.pop();
84
87
  }
85
88
  }
@@ -9,7 +9,7 @@ var _utils = require("@typescript-eslint/utils");
9
9
 
10
10
  var _utils2 = require("./utils");
11
11
 
12
- const testCaseNames = new Set([...Object.keys(_utils2.TestCaseName), 'it.only', 'it.concurrent.only', 'it.skip', 'it.concurrent.skip', 'test.only', 'test.concurrent.only', 'test.skip', 'test.concurrent.skip', 'fit.concurrent']);
12
+ const testCaseNames = new Set([...Object.keys(_utils2.TestCaseName), 'it.only', 'it.only', 'it.skip', 'it.skip', 'test.only', 'test.only', 'test.skip', 'test.skip', 'fit.concurrent']);
13
13
 
14
14
  const isTestFunctionExpression = node => node.parent !== undefined && node.parent.type === _utils.AST_NODE_TYPES.CallExpression && testCaseNames.has((0, _utils2.getNodeName)(node.parent.callee));
15
15
 
@@ -58,10 +58,12 @@ var _default = (0, _utils2.createRule)({
58
58
 
59
59
  return {
60
60
  CallExpression(node) {
61
- if ((0, _utils2.isTestCaseCall)(node)) {
61
+ const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
62
+
63
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'test') {
62
64
  stack.push(true);
63
65
 
64
- if ((0, _utils2.getNodeName)(node).endsWith('each')) {
66
+ if (jestFnCall.members.some(s => (0, _utils2.getAccessorValue)(s) === 'each')) {
65
67
  stack.push(true);
66
68
  }
67
69
  }
@@ -73,7 +75,7 @@ var _default = (0, _utils2.createRule)({
73
75
 
74
76
  FunctionDeclaration(node) {
75
77
  const declaredVariables = context.getDeclaredVariables(node);
76
- const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
78
+ const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables, context);
77
79
  stack.push(testCallExpressions.length > 0);
78
80
  },
79
81
 
@@ -30,6 +30,23 @@ var _default = (0, _utils.createRule)({
30
30
  defaultOptions: [{}],
31
31
 
32
32
  create(context, [restrictedChains]) {
33
+ const reportIfRestricted = (loc, chain) => {
34
+ if (!(chain in restrictedChains)) {
35
+ return false;
36
+ }
37
+
38
+ const message = restrictedChains[chain];
39
+ context.report({
40
+ messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
41
+ data: {
42
+ message,
43
+ chain
44
+ },
45
+ loc
46
+ });
47
+ return true;
48
+ };
49
+
33
50
  return {
34
51
  CallExpression(node) {
35
52
  if (!(0, _utils.isExpectCall)(node)) {
@@ -41,58 +58,37 @@ var _default = (0, _utils.createRule)({
41
58
  modifier
42
59
  } = (0, _utils.parseExpectCall)(node);
43
60
 
44
- if (matcher) {
45
- const chain = matcher.name;
46
-
47
- if (chain in restrictedChains) {
48
- const message = restrictedChains[chain];
49
- context.report({
50
- messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
51
- data: {
52
- message,
53
- chain
54
- },
55
- node: matcher.node.property
56
- });
57
- return;
58
- }
61
+ if (matcher && reportIfRestricted(matcher.node.property.loc, matcher.name)) {
62
+ return;
59
63
  }
60
64
 
61
65
  if (modifier) {
62
- const chain = modifier.name;
63
-
64
- if (chain in restrictedChains) {
65
- const message = restrictedChains[chain];
66
- context.report({
67
- messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
68
- data: {
69
- message,
70
- chain
71
- },
72
- node: modifier.node.property
73
- });
66
+ if (reportIfRestricted(modifier.node.property.loc, modifier.name)) {
74
67
  return;
75
68
  }
69
+
70
+ if (modifier.negation) {
71
+ if (reportIfRestricted(modifier.negation.property.loc, 'not') || reportIfRestricted({
72
+ start: modifier.node.property.loc.start,
73
+ end: modifier.negation.property.loc.end
74
+ }, `${modifier.name}.not`)) {
75
+ return;
76
+ }
77
+ }
76
78
  }
77
79
 
78
80
  if (matcher && modifier) {
79
- const chain = `${modifier.name}.${matcher.name}`;
80
-
81
- if (chain in restrictedChains) {
82
- const message = restrictedChains[chain];
83
- context.report({
84
- messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
85
- data: {
86
- message,
87
- chain
88
- },
89
- loc: {
90
- start: modifier.node.property.loc.start,
91
- end: matcher.node.property.loc.end
92
- }
93
- });
94
- return;
81
+ let chain = modifier.name;
82
+
83
+ if (modifier.negation) {
84
+ chain += '.not';
95
85
  }
86
+
87
+ chain += `.${matcher.name}`;
88
+ reportIfRestricted({
89
+ start: modifier.node.property.loc.start,
90
+ end: matcher.node.property.loc.end
91
+ }, chain);
96
92
  }
97
93
  }
98
94
 
@@ -9,7 +9,7 @@ var _utils = require("@typescript-eslint/utils");
9
9
 
10
10
  var _utils2 = require("./utils");
11
11
 
12
- const getBlockType = statement => {
12
+ const getBlockType = (statement, context) => {
13
13
  const func = statement.parent;
14
14
  /* istanbul ignore if */
15
15
 
@@ -30,7 +30,7 @@ const getBlockType = statement => {
30
30
  } // if it's not a variable, it will be callExpr, we only care about describe
31
31
 
32
32
 
33
- if (expr.type === _utils.AST_NODE_TYPES.CallExpression && (0, _utils2.isDescribeCall)(expr)) {
33
+ if (expr.type === _utils.AST_NODE_TYPES.CallExpression && (0, _utils2.isTypeOfJestFnCall)(expr, context, ['describe'])) {
34
34
  return 'describe';
35
35
  }
36
36
  }
@@ -73,7 +73,7 @@ var _default = (0, _utils2.createRule)({
73
73
 
74
74
  const isCustomTestBlockFunction = node => additionalTestBlockFunctions.includes((0, _utils2.getNodeName)(node) || '');
75
75
 
76
- const isTestBlock = node => (0, _utils2.isTestCaseCall)(node) || isCustomTestBlockFunction(node);
76
+ const isTestBlock = node => (0, _utils2.isTypeOfJestFnCall)(node, context, ['test']) || isCustomTestBlockFunction(node);
77
77
 
78
78
  return {
79
79
  CallExpression(node) {
@@ -108,7 +108,7 @@ var _default = (0, _utils2.createRule)({
108
108
  },
109
109
 
110
110
  BlockStatement(statement) {
111
- const blockType = getBlockType(statement);
111
+ const blockType = getBlockType(statement, context);
112
112
 
113
113
  if (blockType) {
114
114
  callStack.push(blockType);
@@ -116,7 +116,7 @@ var _default = (0, _utils2.createRule)({
116
116
  },
117
117
 
118
118
  'BlockStatement:exit'(statement) {
119
- if (callStack[callStack.length - 1] === getBlockType(statement)) {
119
+ if (callStack[callStack.length - 1] === getBlockType(statement, context)) {
120
120
  callStack.pop();
121
121
  }
122
122
  },
@@ -29,10 +29,17 @@ var _default = (0, _utils2.createRule)({
29
29
  create(context) {
30
30
  return {
31
31
  CallExpression(node) {
32
- const nodeName = (0, _utils2.getNodeName)(node.callee);
33
- if (!nodeName || !(0, _utils2.isDescribeCall)(node) && !(0, _utils2.isTestCaseCall)(node)) return;
34
- const preferredNodeName = getPreferredNodeName(nodeName);
35
- if (!preferredNodeName) return;
32
+ const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
33
+
34
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'describe' && (jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'test') {
35
+ return;
36
+ }
37
+
38
+ if (jestFnCall.name[0] !== 'f' && jestFnCall.name[0] !== 'x') {
39
+ return;
40
+ }
41
+
42
+ const preferredNodeName = [jestFnCall.name.slice(1), jestFnCall.name[0] === 'f' ? 'only' : 'skip', ...jestFnCall.members.map(s => (0, _utils2.getAccessorValue)(s))].join('.');
36
43
  const funcNode = node.callee.type === _utils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _utils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
37
44
  context.report({
38
45
  messageId: 'usePreferredName',
@@ -53,19 +60,4 @@ var _default = (0, _utils2.createRule)({
53
60
 
54
61
  });
55
62
 
56
- exports.default = _default;
57
-
58
- function getPreferredNodeName(nodeName) {
59
- const firstChar = nodeName.charAt(0);
60
- const suffix = nodeName.endsWith('.each') ? '.each' : '';
61
-
62
- if (firstChar === 'f') {
63
- return `${nodeName.slice(1).replace('.each', '')}.only${suffix}`;
64
- }
65
-
66
- if (firstChar === 'x') {
67
- return `${nodeName.slice(1).replace('.each', '')}.skip${suffix}`;
68
- }
69
-
70
- return null;
71
- }
63
+ exports.default = _default;
@@ -38,7 +38,10 @@ var _default = (0, _utils2.createRule)({
38
38
  create(context) {
39
39
  return {
40
40
  CallExpression(node) {
41
- if (!(0, _utils2.isTestCaseCall)(node)) return;
41
+ if (!(0, _utils2.isTypeOfJestFnCall)(node, context, ['test'])) {
42
+ return;
43
+ }
44
+
42
45
  const body = getBody(node.arguments);
43
46
  const returnStmt = body.find(t => t.type === _utils.AST_NODE_TYPES.ReturnStatement);
44
47
  if (!returnStmt) return;
@@ -50,7 +53,7 @@ var _default = (0, _utils2.createRule)({
50
53
 
51
54
  FunctionDeclaration(node) {
52
55
  const declaredVariables = context.getDeclaredVariables(node);
53
- const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
56
+ const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables, context);
54
57
  if (testCallExpressions.length === 0) return;
55
58
  const returnStmt = node.body.body.find(t => t.type === _utils.AST_NODE_TYPES.ReturnStatement);
56
59
  if (!returnStmt) return;
@@ -33,19 +33,20 @@ var _default = (0, _utils.createRule)({
33
33
  const {
34
34
  modifier,
35
35
  matcher
36
- } = (0, _utils.parseExpectCall)(node); // Could check resolves/rejects here but not a likely idiom.
37
-
38
- if (matcher && !modifier) {
39
- if (['toBeCalled', 'toHaveBeenCalled'].includes(matcher.name)) {
40
- context.report({
41
- data: {
42
- name: matcher.name
43
- },
44
- // todo: rename to 'matcherName'
45
- messageId: 'preferCalledWith',
46
- node: matcher.node.property
47
- });
48
- }
36
+ } = (0, _utils.parseExpectCall)(node);
37
+
38
+ if (!matcher || (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.not || modifier !== null && modifier !== void 0 && modifier.negation) {
39
+ return;
40
+ }
41
+
42
+ if (['toBeCalled', 'toHaveBeenCalled'].includes(matcher.name)) {
43
+ context.report({
44
+ data: {
45
+ name: matcher.name
46
+ },
47
+ messageId: 'preferCalledWith',
48
+ node: matcher.node.property
49
+ });
49
50
  }
50
51
  }
51
52
 
@@ -108,7 +108,10 @@ var _default = (0, _utils2.createRule)({
108
108
  return;
109
109
  }
110
110
 
111
- const preferredMatcher = determineMatcher(comparison.operator, (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]).value === !!modifier);
111
+ const negation = modifier !== null && modifier !== void 0 && modifier.negation ? {
112
+ node: modifier.negation
113
+ } : (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils2.ModifierName.not ? modifier : null;
114
+ const preferredMatcher = determineMatcher(comparison.operator, (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]).value === !!negation);
112
115
 
113
116
  if (!preferredMatcher) {
114
117
  return;
@@ -116,10 +119,12 @@ var _default = (0, _utils2.createRule)({
116
119
 
117
120
  context.report({
118
121
  fix(fixer) {
119
- const sourceCode = context.getSourceCode();
122
+ const sourceCode = context.getSourceCode(); // preserve the existing modifier if it's not a negation
123
+
124
+ const modifierText = modifier && (modifier === null || modifier === void 0 ? void 0 : modifier.node) !== (negation === null || negation === void 0 ? void 0 : negation.node) ? `.${modifier.name}` : '';
120
125
  return [// replace the comparison argument with the left-hand side of the comparison
121
126
  fixer.replaceText(comparison, sourceCode.getText(comparison.left)), // replace the current matcher & modifier with the preferred matcher
122
- fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], `.${preferredMatcher}`), // replace the matcher argument with the right-hand side of the comparison
127
+ fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], `${modifierText}.${preferredMatcher}`), // replace the matcher argument with the right-hand side of the comparison
123
128
  fixer.replaceText(matcher.arguments[0], sourceCode.getText(comparison.right))];
124
129
  },
125
130
 
@@ -127,7 +132,7 @@ var _default = (0, _utils2.createRule)({
127
132
  data: {
128
133
  preferredMatcher
129
134
  },
130
- node: (modifier || matcher).node.property
135
+ node: (negation || matcher).node.property
131
136
  });
132
137
  }
133
138
 
@@ -64,16 +64,26 @@ var _default = (0, _utils2.createRule)({
64
64
  return;
65
65
  }
66
66
 
67
- const matcherValue = (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]).value; // we need to negate the expectation if the current expected
67
+ const matcherValue = (0, _utils2.followTypeAssertionChain)(matcher.arguments[0]).value;
68
+ const negation = modifier !== null && modifier !== void 0 && modifier.negation ? {
69
+ node: modifier.negation
70
+ } : (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils2.ModifierName.not ? modifier : null; // we need to negate the expectation if the current expected
68
71
  // value is itself negated by the "not" modifier
69
72
 
70
- const addNotModifier = (comparison.operator === '!==' ? !matcherValue : matcherValue) === !!modifier;
73
+ const addNotModifier = (comparison.operator === '!==' ? !matcherValue : matcherValue) === !!negation;
71
74
 
72
75
  const buildFixer = equalityMatcher => fixer => {
73
- const sourceCode = context.getSourceCode();
76
+ const sourceCode = context.getSourceCode(); // preserve the existing modifier if it's not a negation
77
+
78
+ let modifierText = modifier && (modifier === null || modifier === void 0 ? void 0 : modifier.node) !== (negation === null || negation === void 0 ? void 0 : negation.node) ? `.${modifier.name}` : '';
79
+
80
+ if (addNotModifier) {
81
+ modifierText += `.${_utils2.ModifierName.not}`;
82
+ }
83
+
74
84
  return [// replace the comparison argument with the left-hand side of the comparison
75
85
  fixer.replaceText(comparison, sourceCode.getText(comparison.left)), // replace the current matcher & modifier with the preferred matcher
76
- fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], addNotModifier ? `.${_utils2.ModifierName.not}.${equalityMatcher}` : `.${equalityMatcher}`), // replace the matcher argument with the right-hand side of the comparison
86
+ fixer.replaceTextRange([expectCallEnd, matcher.node.range[1]], `${modifierText}.${equalityMatcher}`), // replace the matcher argument with the right-hand side of the comparison
77
87
  fixer.replaceText(matcher.arguments[0], sourceCode.getText(comparison.right))];
78
88
  };
79
89
 
@@ -86,7 +96,7 @@ var _default = (0, _utils2.createRule)({
86
96
  },
87
97
  fix: buildFixer(equalityMatcher)
88
98
  })),
89
- node: (modifier || matcher).node.property
99
+ node: (negation || matcher).node.property
90
100
  });
91
101
  }
92
102
 
@@ -116,7 +116,7 @@ var _default = (0, _utils2.createRule)({
116
116
  'ForOfStatement:exit': exitForLoop,
117
117
 
118
118
  CallExpression(node) {
119
- if ((0, _utils2.isTestCaseCall)(node)) {
119
+ if ((0, _utils2.isTypeOfJestFnCall)(node, context, ['test'])) {
120
120
  inTestCaseCall = true;
121
121
  return;
122
122
  }
@@ -133,10 +133,12 @@ var _default = (0, _utils2.createRule)({
133
133
  },
134
134
 
135
135
  'CallExpression:exit'(node) {
136
- if (!(0, _utils2.isTestCaseCall)(node)) {
136
+ if (!(0, _utils2.isTypeOfJestFnCall)(node, context, ['test'])) {
137
137
  return;
138
138
  }
139
139
 
140
+ inTestCaseCall = false;
141
+
140
142
  if (node.arguments.length < 2) {
141
143
  return;
142
144
  }