eslint-plugin-jest 26.8.7 → 27.1.5

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 (114) hide show
  1. package/README.md +82 -78
  2. package/docs/rules/consistent-test-it.md +9 -4
  3. package/docs/rules/expect-expect.md +5 -0
  4. package/docs/rules/max-expects.md +3 -1
  5. package/docs/rules/max-nested-describe.md +3 -1
  6. package/docs/rules/no-alias-methods.md +13 -2
  7. package/docs/rules/no-commented-out-tests.md +6 -1
  8. package/docs/rules/no-conditional-expect.md +7 -2
  9. package/docs/rules/no-conditional-in-test.md +3 -1
  10. package/docs/rules/no-deprecated-functions.md +14 -7
  11. package/docs/rules/no-disabled-tests.md +6 -1
  12. package/docs/rules/no-done-callback.md +9 -1
  13. package/docs/rules/no-duplicate-hooks.md +3 -1
  14. package/docs/rules/no-export.md +6 -1
  15. package/docs/rules/no-focused-tests.md +10 -1
  16. package/docs/rules/no-hooks.md +3 -1
  17. package/docs/rules/no-identical-title.md +6 -1
  18. package/docs/rules/no-if.md +4 -4
  19. package/docs/rules/no-interpolation-in-snapshots.md +6 -1
  20. package/docs/rules/no-jasmine-globals.md +10 -2
  21. package/docs/rules/no-large-snapshots.md +4 -2
  22. package/docs/rules/no-mocks-import.md +6 -1
  23. package/docs/rules/no-restricted-jest-methods.md +51 -0
  24. package/docs/rules/no-restricted-matchers.md +19 -4
  25. package/docs/rules/no-standalone-expect.md +6 -1
  26. package/docs/rules/no-test-prefixes.md +9 -1
  27. package/docs/rules/no-test-return-statement.md +2 -0
  28. package/docs/rules/prefer-called-with.md +2 -0
  29. package/docs/rules/prefer-comparison-matcher.md +5 -0
  30. package/docs/rules/prefer-each.md +56 -0
  31. package/docs/rules/prefer-equality-matcher.md +5 -0
  32. package/docs/rules/prefer-expect-assertions.md +5 -2
  33. package/docs/rules/prefer-expect-resolves.md +8 -1
  34. package/docs/rules/prefer-hooks-in-order.md +3 -1
  35. package/docs/rules/prefer-hooks-on-top.md +3 -1
  36. package/docs/rules/prefer-lowercase-title.md +5 -0
  37. package/docs/rules/prefer-mock-promise-shorthand.md +6 -1
  38. package/docs/rules/prefer-snapshot-hint.md +2 -0
  39. package/docs/rules/prefer-spy-on.md +5 -2
  40. package/docs/rules/prefer-strict-equal.md +5 -2
  41. package/docs/rules/prefer-to-be.md +8 -0
  42. package/docs/rules/prefer-to-contain.md +8 -2
  43. package/docs/rules/prefer-to-have-length.md +8 -2
  44. package/docs/rules/prefer-todo.md +5 -2
  45. package/docs/rules/require-hook.md +2 -0
  46. package/docs/rules/require-to-throw-message.md +2 -2
  47. package/docs/rules/require-top-level-describe.md +5 -1
  48. package/docs/rules/unbound-method.md +7 -2
  49. package/docs/rules/valid-describe-callback.md +6 -1
  50. package/docs/rules/valid-expect-in-promise.md +6 -1
  51. package/docs/rules/valid-expect.md +5 -2
  52. package/docs/rules/valid-title.md +9 -1
  53. package/lib/index.js +14 -25
  54. package/lib/processors/snapshot-processor.js +3 -5
  55. package/lib/rules/consistent-test-it.js +1 -19
  56. package/lib/rules/expect-expect.js +1 -18
  57. package/lib/rules/max-expects.js +0 -16
  58. package/lib/rules/max-nested-describe.js +0 -13
  59. package/lib/rules/no-alias-methods.js +1 -10
  60. package/lib/rules/no-commented-out-tests.js +0 -10
  61. package/lib/rules/no-conditional-expect.js +2 -23
  62. package/lib/rules/no-conditional-in-test.js +0 -9
  63. package/lib/rules/no-deprecated-functions.js +2 -18
  64. package/lib/rules/no-disabled-tests.js +3 -19
  65. package/lib/rules/no-done-callback.js +5 -35
  66. package/lib/rules/no-duplicate-hooks.js +0 -12
  67. package/lib/rules/no-export.js +0 -12
  68. package/lib/rules/no-focused-tests.js +1 -17
  69. package/lib/rules/no-hooks.js +0 -7
  70. package/lib/rules/no-identical-title.js +0 -19
  71. package/lib/rules/no-if.js +0 -24
  72. package/lib/rules/no-interpolation-in-snapshots.js +0 -9
  73. package/lib/rules/no-jasmine-globals.js +1 -23
  74. package/lib/rules/no-large-snapshots.js +4 -24
  75. package/lib/rules/no-mocks-import.js +0 -12
  76. package/lib/rules/no-restricted-jest-methods.js +56 -0
  77. package/lib/rules/no-restricted-matchers.js +13 -28
  78. package/lib/rules/no-standalone-expect.js +7 -33
  79. package/lib/rules/no-test-prefixes.js +1 -13
  80. package/lib/rules/no-test-return-statement.js +0 -12
  81. package/lib/rules/prefer-called-with.js +0 -10
  82. package/lib/rules/prefer-comparison-matcher.js +8 -33
  83. package/lib/rules/prefer-each.js +80 -0
  84. package/lib/rules/prefer-equality-matcher.js +12 -25
  85. package/lib/rules/prefer-expect-assertions.js +8 -54
  86. package/lib/rules/prefer-expect-resolves.js +0 -12
  87. package/lib/rules/prefer-hooks-in-order.js +2 -16
  88. package/lib/rules/prefer-hooks-on-top.js +0 -9
  89. package/lib/rules/prefer-lowercase-title.js +0 -23
  90. package/lib/rules/prefer-mock-promise-shorthand.js +5 -26
  91. package/lib/rules/prefer-snapshot-hint.js +8 -34
  92. package/lib/rules/prefer-spy-on.js +0 -17
  93. package/lib/rules/prefer-strict-equal.js +1 -11
  94. package/lib/rules/prefer-to-be.js +5 -30
  95. package/lib/rules/prefer-to-contain.js +11 -21
  96. package/lib/rules/prefer-to-have-length.js +4 -16
  97. package/lib/rules/prefer-todo.js +2 -18
  98. package/lib/rules/require-hook.js +1 -25
  99. package/lib/rules/require-to-throw-message.js +0 -9
  100. package/lib/rules/require-top-level-describe.js +1 -18
  101. package/lib/rules/unbound-method.js +3 -30
  102. package/lib/rules/utils/accessors.js +6 -18
  103. package/lib/rules/utils/detectJestVersion.js +2 -7
  104. package/lib/rules/utils/followTypeAssertionChain.js +0 -4
  105. package/lib/rules/utils/index.js +0 -10
  106. package/lib/rules/utils/misc.js +2 -46
  107. package/lib/rules/utils/parseJestFnCall.js +51 -154
  108. package/lib/rules/valid-describe-callback.js +0 -17
  109. package/lib/rules/valid-expect-in-promise.js +28 -95
  110. package/lib/rules/valid-expect.js +5 -48
  111. package/lib/rules/valid-title.js +5 -40
  112. package/package.json +20 -16
  113. package/docs/rules/no-jest-import.md +0 -20
  114. package/lib/rules/no-jest-import.js +0 -48
@@ -4,21 +4,15 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _utils = require("@typescript-eslint/utils");
9
-
10
8
  var _utils2 = require("./utils");
11
-
12
9
  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
-
14
10
  const isTestFunctionExpression = node => node.parent !== undefined && node.parent.type === _utils.AST_NODE_TYPES.CallExpression && testCaseNames.has((0, _utils2.getNodeName)(node.parent.callee));
15
-
16
11
  const conditionName = {
17
12
  [_utils.AST_NODE_TYPES.ConditionalExpression]: 'conditional',
18
13
  [_utils.AST_NODE_TYPES.SwitchStatement]: 'switch',
19
14
  [_utils.AST_NODE_TYPES.IfStatement]: 'if'
20
15
  };
21
-
22
16
  var _default = (0, _utils2.createRule)({
23
17
  name: __filename,
24
18
  meta: {
@@ -36,17 +30,13 @@ var _default = (0, _utils2.createRule)({
36
30
  type: 'suggestion'
37
31
  },
38
32
  defaultOptions: [],
39
-
40
33
  create(context) {
41
34
  const stack = [];
42
-
43
35
  function validate(node) {
44
36
  const lastElementInStack = stack[stack.length - 1];
45
-
46
37
  if (stack.length === 0 || !lastElementInStack) {
47
38
  return;
48
39
  }
49
-
50
40
  context.report({
51
41
  data: {
52
42
  condition: conditionName[node.type]
@@ -55,57 +45,43 @@ var _default = (0, _utils2.createRule)({
55
45
  node
56
46
  });
57
47
  }
58
-
59
48
  return {
60
49
  CallExpression(node) {
61
50
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
62
-
63
51
  if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'test') {
64
52
  stack.push(true);
65
-
66
53
  if (jestFnCall.members.some(s => (0, _utils2.getAccessorValue)(s) === 'each')) {
67
54
  stack.push(true);
68
55
  }
69
56
  }
70
57
  },
71
-
72
58
  FunctionExpression(node) {
73
59
  stack.push(isTestFunctionExpression(node));
74
60
  },
75
-
76
61
  FunctionDeclaration(node) {
77
62
  const declaredVariables = context.getDeclaredVariables(node);
78
63
  const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables, context);
79
64
  stack.push(testCallExpressions.length > 0);
80
65
  },
81
-
82
66
  ArrowFunctionExpression(node) {
83
67
  stack.push(isTestFunctionExpression(node));
84
68
  },
85
-
86
69
  IfStatement: validate,
87
70
  SwitchStatement: validate,
88
71
  ConditionalExpression: validate,
89
-
90
72
  'CallExpression:exit'() {
91
73
  stack.pop();
92
74
  },
93
-
94
75
  'FunctionExpression:exit'() {
95
76
  stack.pop();
96
77
  },
97
-
98
78
  'FunctionDeclaration:exit'() {
99
79
  stack.pop();
100
80
  },
101
-
102
81
  'ArrowFunctionExpression:exit'() {
103
82
  stack.pop();
104
83
  }
105
-
106
84
  };
107
85
  }
108
-
109
86
  });
110
-
111
87
  exports.default = _default;
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _utils = require("@typescript-eslint/utils");
9
-
10
8
  var _utils2 = require("./utils");
11
-
12
9
  var _default = (0, _utils2.createRule)({
13
10
  name: __filename,
14
11
  meta: {
@@ -24,16 +21,13 @@ var _default = (0, _utils2.createRule)({
24
21
  type: 'problem'
25
22
  },
26
23
  defaultOptions: [],
27
-
28
24
  create(context) {
29
25
  return {
30
26
  CallExpression(node) {
31
27
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
32
-
33
28
  if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
34
29
  return;
35
30
  }
36
-
37
31
  if (['toMatchInlineSnapshot', 'toThrowErrorMatchingInlineSnapshot'].includes((0, _utils2.getAccessorValue)(jestFnCall.matcher))) {
38
32
  // Check all since the optional 'propertyMatchers' argument might be present
39
33
  jestFnCall.args.forEach(argument => {
@@ -46,10 +40,7 @@ var _default = (0, _utils2.createRule)({
46
40
  });
47
41
  }
48
42
  }
49
-
50
43
  };
51
44
  }
52
-
53
45
  });
54
-
55
46
  exports.default = _default;
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _utils = require("@typescript-eslint/utils");
9
-
10
8
  var _utils2 = require("./utils");
11
-
12
9
  var _default = (0, _utils2.createRule)({
13
10
  name: __filename,
14
11
  meta: {
@@ -29,7 +26,6 @@ var _default = (0, _utils2.createRule)({
29
26
  type: 'suggestion'
30
27
  },
31
28
  defaultOptions: [],
32
-
33
29
  create(context) {
34
30
  return {
35
31
  CallExpression(node) {
@@ -37,17 +33,14 @@ var _default = (0, _utils2.createRule)({
37
33
  callee
38
34
  } = node;
39
35
  const calleeName = (0, _utils2.getNodeName)(callee);
40
-
41
36
  if (!calleeName) {
42
37
  return;
43
38
  }
44
-
45
39
  if (calleeName === 'spyOn' || calleeName === 'spyOnProperty' || calleeName === 'fail' || calleeName === 'pending') {
46
- if ((0, _utils2.scopeHasLocalReference)(context.getScope(), calleeName)) {
40
+ if ((0, _utils2.resolveScope)(context.getScope(), calleeName)) {
47
41
  // It's a local variable, not a jasmine global.
48
42
  return;
49
43
  }
50
-
51
44
  switch (calleeName) {
52
45
  case 'spyOn':
53
46
  case 'spyOnProperty':
@@ -60,14 +53,12 @@ var _default = (0, _utils2.createRule)({
60
53
  }
61
54
  });
62
55
  break;
63
-
64
56
  case 'fail':
65
57
  context.report({
66
58
  node,
67
59
  messageId: 'illegalFail'
68
60
  });
69
61
  break;
70
-
71
62
  case 'pending':
72
63
  context.report({
73
64
  node,
@@ -75,13 +66,10 @@ var _default = (0, _utils2.createRule)({
75
66
  });
76
67
  break;
77
68
  }
78
-
79
69
  return;
80
70
  }
81
-
82
71
  if (callee.type === _utils.AST_NODE_TYPES.MemberExpression && calleeName.startsWith('jasmine.')) {
83
72
  const functionName = calleeName.replace('jasmine.', '');
84
-
85
73
  if (functionName === 'any' || functionName === 'anything' || functionName === 'arrayContaining' || functionName === 'objectContaining' || functionName === 'stringMatching') {
86
74
  context.report({
87
75
  fix: fixer => [fixer.replaceText(callee.object, 'expect')],
@@ -94,7 +82,6 @@ var _default = (0, _utils2.createRule)({
94
82
  });
95
83
  return;
96
84
  }
97
-
98
85
  if (functionName === 'addMatchers') {
99
86
  context.report({
100
87
  node,
@@ -106,7 +93,6 @@ var _default = (0, _utils2.createRule)({
106
93
  });
107
94
  return;
108
95
  }
109
-
110
96
  if (functionName === 'createSpy') {
111
97
  context.report({
112
98
  node,
@@ -118,27 +104,23 @@ var _default = (0, _utils2.createRule)({
118
104
  });
119
105
  return;
120
106
  }
121
-
122
107
  context.report({
123
108
  node,
124
109
  messageId: 'illegalJasmine'
125
110
  });
126
111
  }
127
112
  },
128
-
129
113
  MemberExpression(node) {
130
114
  if ((0, _utils2.isSupportedAccessor)(node.object, 'jasmine')) {
131
115
  const {
132
116
  parent,
133
117
  property
134
118
  } = node;
135
-
136
119
  if (parent && parent.type === _utils.AST_NODE_TYPES.AssignmentExpression) {
137
120
  if ((0, _utils2.isSupportedAccessor)(property, 'DEFAULT_TIMEOUT_INTERVAL')) {
138
121
  const {
139
122
  right
140
123
  } = parent;
141
-
142
124
  if (right.type === _utils.AST_NODE_TYPES.Literal) {
143
125
  context.report({
144
126
  fix: fixer => [fixer.replaceText(parent, `jest.setTimeout(${right.value})`)],
@@ -148,7 +130,6 @@ var _default = (0, _utils2.createRule)({
148
130
  return;
149
131
  }
150
132
  }
151
-
152
133
  context.report({
153
134
  node,
154
135
  messageId: 'illegalJasmine'
@@ -156,10 +137,7 @@ var _default = (0, _utils2.createRule)({
156
137
  }
157
138
  }
158
139
  }
159
-
160
140
  };
161
141
  }
162
-
163
142
  });
164
-
165
143
  exports.default = _default;
@@ -4,13 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _path = require("path");
9
-
10
8
  var _utils = require("@typescript-eslint/utils");
11
-
12
9
  var _utils2 = require("./utils");
13
-
14
10
  const reportOnViolation = (context, node, {
15
11
  maxSize: lineLimit = 50,
16
12
  allowedSnapshots = {}
@@ -19,29 +15,23 @@ const reportOnViolation = (context, node, {
19
15
  const endLine = node.loc.end.line;
20
16
  const lineCount = endLine - startLine;
21
17
  const allPathsAreAbsolute = Object.keys(allowedSnapshots).every(_path.isAbsolute);
22
-
23
18
  if (!allPathsAreAbsolute) {
24
19
  throw new Error('All paths for allowedSnapshots must be absolute. You can use JS config and `path.resolve`');
25
20
  }
26
-
27
21
  let isAllowed = false;
28
-
29
22
  if (node.type === _utils.AST_NODE_TYPES.ExpressionStatement && 'left' in node.expression && node.expression.left.type === _utils.AST_NODE_TYPES.MemberExpression && (0, _utils2.isSupportedAccessor)(node.expression.left.property)) {
30
23
  const fileName = context.getFilename();
31
24
  const allowedSnapshotsInFile = allowedSnapshots[fileName];
32
-
33
25
  if (allowedSnapshotsInFile) {
34
26
  const snapshotName = (0, _utils2.getAccessorValue)(node.expression.left.property);
35
27
  isAllowed = allowedSnapshotsInFile.some(name => {
36
28
  if (name instanceof RegExp) {
37
29
  return name.test(snapshotName);
38
30
  }
39
-
40
31
  return snapshotName === name;
41
32
  });
42
33
  }
43
34
  }
44
-
45
35
  if (!isAllowed && lineCount > lineLimit) {
46
36
  context.report({
47
37
  messageId: lineLimit === 0 ? 'noSnapshot' : 'tooLongSnapshots',
@@ -53,13 +43,12 @@ const reportOnViolation = (context, node, {
53
43
  });
54
44
  }
55
45
  };
56
-
57
46
  var _default = (0, _utils2.createRule)({
58
47
  name: __filename,
59
48
  meta: {
60
49
  docs: {
61
50
  category: 'Best Practices',
62
- description: 'disallow large snapshots',
51
+ description: 'Disallow large snapshots',
63
52
  recommended: false
64
53
  },
65
54
  messages: {
@@ -87,37 +76,28 @@ var _default = (0, _utils2.createRule)({
87
76
  }]
88
77
  },
89
78
  defaultOptions: [{}],
90
-
91
79
  create(context, [options]) {
92
80
  if (context.getFilename().endsWith('.snap')) {
93
81
  return {
94
82
  ExpressionStatement(node) {
95
83
  reportOnViolation(context, node, options);
96
84
  }
97
-
98
85
  };
99
86
  }
100
-
101
87
  return {
102
88
  CallExpression(node) {
103
89
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
104
-
105
90
  if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
106
91
  return;
107
92
  }
108
-
109
93
  if (['toMatchInlineSnapshot', 'toThrowErrorMatchingInlineSnapshot'].includes((0, _utils2.getAccessorValue)(jestFnCall.matcher)) && jestFnCall.args.length) {
110
- var _options$inlineMaxSiz;
111
-
112
- reportOnViolation(context, jestFnCall.args[0], { ...options,
113
- maxSize: (_options$inlineMaxSiz = options.inlineMaxSize) !== null && _options$inlineMaxSiz !== void 0 ? _options$inlineMaxSiz : options.maxSize
94
+ reportOnViolation(context, jestFnCall.args[0], {
95
+ ...options,
96
+ maxSize: options.inlineMaxSize ?? options.maxSize
114
97
  });
115
98
  }
116
99
  }
117
-
118
100
  };
119
101
  }
120
-
121
102
  });
122
-
123
103
  exports.default = _default;
@@ -4,17 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _path = require("path");
9
-
10
8
  var _utils = require("./utils");
11
-
12
9
  const mocksDirName = '__mocks__';
13
-
14
10
  const isMockPath = path => path.split(_path.posix.sep).includes(mocksDirName);
15
-
16
11
  const isMockImportLiteral = expression => (0, _utils.isStringNode)(expression) && isMockPath((0, _utils.getStringValue)(expression));
17
-
18
12
  var _default = (0, _utils.createRule)({
19
13
  name: __filename,
20
14
  meta: {
@@ -30,7 +24,6 @@ var _default = (0, _utils.createRule)({
30
24
  schema: []
31
25
  },
32
26
  defaultOptions: [],
33
-
34
27
  create(context) {
35
28
  return {
36
29
  ImportDeclaration(node) {
@@ -41,10 +34,8 @@ var _default = (0, _utils.createRule)({
41
34
  });
42
35
  }
43
36
  },
44
-
45
37
  'CallExpression[callee.name="require"]'(node) {
46
38
  const [arg] = node.arguments;
47
-
48
39
  if (arg && isMockImportLiteral(arg)) {
49
40
  context.report({
50
41
  node: arg,
@@ -52,10 +43,7 @@ var _default = (0, _utils.createRule)({
52
43
  });
53
44
  }
54
45
  }
55
-
56
46
  };
57
47
  }
58
-
59
48
  });
60
-
61
49
  exports.default = _default;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _utils = require("./utils");
8
+ const messages = {
9
+ restrictedJestMethod: 'Use of `{{ restriction }}` is disallowed',
10
+ restrictedJestMethodWithMessage: '{{ message }}'
11
+ };
12
+ var _default = (0, _utils.createRule)({
13
+ name: __filename,
14
+ meta: {
15
+ docs: {
16
+ category: 'Best Practices',
17
+ description: 'Disallow specific `jest.` methods',
18
+ recommended: false
19
+ },
20
+ type: 'suggestion',
21
+ schema: [{
22
+ type: 'object',
23
+ additionalProperties: {
24
+ type: ['string', 'null']
25
+ }
26
+ }],
27
+ messages
28
+ },
29
+ defaultOptions: [{}],
30
+ create(context, [restrictedMethods]) {
31
+ return {
32
+ CallExpression(node) {
33
+ const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
34
+ if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'jest' || jestFnCall.members.length === 0) {
35
+ return;
36
+ }
37
+ const method = (0, _utils.getAccessorValue)(jestFnCall.members[0]);
38
+ if (method in restrictedMethods) {
39
+ const message = restrictedMethods[method];
40
+ context.report({
41
+ messageId: message ? 'restrictedJestMethodWithMessage' : 'restrictedJestMethod',
42
+ data: {
43
+ message,
44
+ restriction: method
45
+ },
46
+ loc: {
47
+ start: jestFnCall.members[0].loc.start,
48
+ end: jestFnCall.members[jestFnCall.members.length - 1].loc.end
49
+ }
50
+ });
51
+ }
52
+ }
53
+ };
54
+ }
55
+ });
56
+ exports.default = _default;
@@ -4,9 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _utils = require("./utils");
9
-
8
+ const isChainRestricted = (chain, restriction) => {
9
+ if (_utils.ModifierName.hasOwnProperty(restriction) || restriction.endsWith('.not')) {
10
+ return chain.startsWith(restriction);
11
+ }
12
+ return chain === restriction;
13
+ };
10
14
  var _default = (0, _utils.createRule)({
11
15
  name: __filename,
12
16
  meta: {
@@ -23,56 +27,37 @@ var _default = (0, _utils.createRule)({
23
27
  }
24
28
  }],
25
29
  messages: {
26
- restrictedChain: 'Use of `{{ chain }}` is disallowed',
30
+ restrictedChain: 'Use of `{{ restriction }}` is disallowed',
27
31
  restrictedChainWithMessage: '{{ message }}'
28
32
  }
29
33
  },
30
34
  defaultOptions: [{}],
31
-
32
35
  create(context, [restrictedChains]) {
33
36
  return {
34
37
  CallExpression(node) {
35
38
  const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
36
-
37
39
  if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) !== 'expect') {
38
40
  return;
39
41
  }
40
-
41
- const permutations = [jestFnCall.members];
42
-
43
- if (jestFnCall.members.length > 2) {
44
- permutations.push([jestFnCall.members[0], jestFnCall.members[1]]);
45
- permutations.push([jestFnCall.members[1], jestFnCall.members[2]]);
46
- }
47
-
48
- if (jestFnCall.members.length > 1) {
49
- permutations.push(...jestFnCall.members.map(nod => [nod]));
50
- }
51
-
52
- for (const permutation of permutations) {
53
- const chain = permutation.map(nod => (0, _utils.getAccessorValue)(nod)).join('.');
54
-
55
- if (chain in restrictedChains) {
56
- const message = restrictedChains[chain];
42
+ const chain = jestFnCall.members.map(nod => (0, _utils.getAccessorValue)(nod)).join('.');
43
+ for (const [restriction, message] of Object.entries(restrictedChains)) {
44
+ if (isChainRestricted(chain, restriction)) {
57
45
  context.report({
58
46
  messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
59
47
  data: {
60
48
  message,
61
- chain
49
+ restriction
62
50
  },
63
51
  loc: {
64
- start: permutation[0].loc.start,
65
- end: permutation[permutation.length - 1].loc.end
52
+ start: jestFnCall.members[0].loc.start,
53
+ end: jestFnCall.members[jestFnCall.members.length - 1].loc.end
66
54
  }
67
55
  });
68
56
  break;
69
57
  }
70
58
  }
71
59
  }
72
-
73
60
  };
74
61
  }
75
-
76
62
  });
77
-
78
63
  exports.default = _default;
@@ -4,40 +4,35 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var _utils = require("@typescript-eslint/utils");
9
-
10
8
  var _utils2 = require("./utils");
11
-
12
9
  const getBlockType = (statement, context) => {
13
10
  const func = statement.parent;
14
- /* istanbul ignore if */
15
11
 
12
+ /* istanbul ignore if */
16
13
  if (!func) {
17
14
  throw new Error(`Unexpected BlockStatement. No parent defined. - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`);
18
- } // functionDeclaration: function func() {}
19
-
15
+ }
20
16
 
17
+ // functionDeclaration: function func() {}
21
18
  if (func.type === _utils.AST_NODE_TYPES.FunctionDeclaration) {
22
19
  return 'function';
23
20
  }
24
-
25
21
  if ((0, _utils2.isFunction)(func) && func.parent) {
26
- const expr = func.parent; // arrow function or function expr
22
+ const expr = func.parent;
27
23
 
24
+ // arrow function or function expr
28
25
  if (expr.type === _utils.AST_NODE_TYPES.VariableDeclarator) {
29
26
  return 'function';
30
- } // if it's not a variable, it will be callExpr, we only care about describe
31
-
27
+ }
32
28
 
29
+ // if it's not a variable, it will be callExpr, we only care about describe
33
30
  if (expr.type === _utils.AST_NODE_TYPES.CallExpression && (0, _utils2.isTypeOfJestFnCall)(expr, context, ['describe'])) {
34
31
  return 'describe';
35
32
  }
36
33
  }
37
-
38
34
  return null;
39
35
  };
40
-
41
36
  var _default = (0, _utils2.createRule)({
42
37
  name: __filename,
43
38
  meta: {
@@ -65,85 +60,64 @@ var _default = (0, _utils2.createRule)({
65
60
  defaultOptions: [{
66
61
  additionalTestBlockFunctions: []
67
62
  }],
68
-
69
63
  create(context, [{
70
64
  additionalTestBlockFunctions = []
71
65
  }]) {
72
66
  const callStack = [];
73
-
74
67
  const isCustomTestBlockFunction = node => additionalTestBlockFunctions.includes((0, _utils2.getNodeName)(node) || '');
75
-
76
68
  return {
77
69
  CallExpression(node) {
78
70
  const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
79
-
80
71
  if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'expect') {
81
72
  var _jestFnCall$head$node;
82
-
83
73
  if (((_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]))) {
84
74
  return;
85
75
  }
86
-
87
76
  const parent = callStack[callStack.length - 1];
88
-
89
77
  if (!parent || parent === _utils2.DescribeAlias.describe) {
90
78
  context.report({
91
79
  node,
92
80
  messageId: 'unexpectedExpect'
93
81
  });
94
82
  }
95
-
96
83
  return;
97
84
  }
98
-
99
85
  if ((jestFnCall === null || jestFnCall === void 0 ? void 0 : jestFnCall.type) === 'test' || isCustomTestBlockFunction(node)) {
100
86
  callStack.push('test');
101
87
  }
102
-
103
88
  if (node.callee.type === _utils.AST_NODE_TYPES.TaggedTemplateExpression) {
104
89
  callStack.push('template');
105
90
  }
106
91
  },
107
-
108
92
  'CallExpression:exit'(node) {
109
93
  const top = callStack[callStack.length - 1];
110
-
111
94
  if (top === 'test' && ((0, _utils2.isTypeOfJestFnCall)(node, context, ['test']) || isCustomTestBlockFunction(node)) && node.callee.type !== _utils.AST_NODE_TYPES.MemberExpression || top === 'template' && node.callee.type === _utils.AST_NODE_TYPES.TaggedTemplateExpression) {
112
95
  callStack.pop();
113
96
  }
114
97
  },
115
-
116
98
  BlockStatement(statement) {
117
99
  const blockType = getBlockType(statement, context);
118
-
119
100
  if (blockType) {
120
101
  callStack.push(blockType);
121
102
  }
122
103
  },
123
-
124
104
  'BlockStatement:exit'(statement) {
125
105
  if (callStack[callStack.length - 1] === getBlockType(statement, context)) {
126
106
  callStack.pop();
127
107
  }
128
108
  },
129
-
130
109
  ArrowFunctionExpression(node) {
131
110
  var _node$parent;
132
-
133
111
  if (((_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type) !== _utils.AST_NODE_TYPES.CallExpression) {
134
112
  callStack.push('arrow');
135
113
  }
136
114
  },
137
-
138
115
  'ArrowFunctionExpression:exit'() {
139
116
  if (callStack[callStack.length - 1] === 'arrow') {
140
117
  callStack.pop();
141
118
  }
142
119
  }
143
-
144
120
  };
145
121
  }
146
-
147
122
  });
148
-
149
123
  exports.default = _default;