@depup/eslint-plugin-jest 29.15.1-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -0
  3. package/changes.json +10 -0
  4. package/docs/rules/consistent-test-it.md +96 -0
  5. package/docs/rules/expect-expect.md +152 -0
  6. package/docs/rules/max-expects.md +78 -0
  7. package/docs/rules/max-nested-describe.md +134 -0
  8. package/docs/rules/no-alias-methods.md +57 -0
  9. package/docs/rules/no-commented-out-tests.md +68 -0
  10. package/docs/rules/no-conditional-expect.md +142 -0
  11. package/docs/rules/no-conditional-in-test.md +123 -0
  12. package/docs/rules/no-confusing-set-timeout.md +64 -0
  13. package/docs/rules/no-deprecated-functions.md +59 -0
  14. package/docs/rules/no-disabled-tests.md +72 -0
  15. package/docs/rules/no-done-callback.md +100 -0
  16. package/docs/rules/no-duplicate-hooks.md +79 -0
  17. package/docs/rules/no-error-equal.md +37 -0
  18. package/docs/rules/no-export.md +52 -0
  19. package/docs/rules/no-focused-tests.md +67 -0
  20. package/docs/rules/no-hooks.md +178 -0
  21. package/docs/rules/no-identical-title.md +59 -0
  22. package/docs/rules/no-interpolation-in-snapshots.md +67 -0
  23. package/docs/rules/no-jasmine-globals.md +69 -0
  24. package/docs/rules/no-large-snapshots.md +180 -0
  25. package/docs/rules/no-mocks-import.md +34 -0
  26. package/docs/rules/no-restricted-jest-methods.md +53 -0
  27. package/docs/rules/no-restricted-matchers.md +64 -0
  28. package/docs/rules/no-standalone-expect.md +106 -0
  29. package/docs/rules/no-test-prefixes.md +42 -0
  30. package/docs/rules/no-test-return-statement.md +50 -0
  31. package/docs/rules/no-unnecessary-assertion.md +41 -0
  32. package/docs/rules/no-unneeded-async-expect-function.md +41 -0
  33. package/docs/rules/no-untyped-mock-factory.md +74 -0
  34. package/docs/rules/padding-around-after-all-blocks.md +34 -0
  35. package/docs/rules/padding-around-after-each-blocks.md +38 -0
  36. package/docs/rules/padding-around-all.md +20 -0
  37. package/docs/rules/padding-around-before-all-blocks.md +37 -0
  38. package/docs/rules/padding-around-before-each-blocks.md +38 -0
  39. package/docs/rules/padding-around-describe-blocks.md +42 -0
  40. package/docs/rules/padding-around-expect-groups.md +44 -0
  41. package/docs/rules/padding-around-test-blocks.md +48 -0
  42. package/docs/rules/prefer-called-with.md +39 -0
  43. package/docs/rules/prefer-comparison-matcher.md +62 -0
  44. package/docs/rules/prefer-each.md +58 -0
  45. package/docs/rules/prefer-ending-with-an-expect.md +170 -0
  46. package/docs/rules/prefer-equality-matcher.md +36 -0
  47. package/docs/rules/prefer-expect-assertions.md +230 -0
  48. package/docs/rules/prefer-expect-resolves.md +62 -0
  49. package/docs/rules/prefer-hooks-in-order.md +137 -0
  50. package/docs/rules/prefer-hooks-on-top.md +124 -0
  51. package/docs/rules/prefer-importing-jest-globals.md +85 -0
  52. package/docs/rules/prefer-jest-mocked.md +40 -0
  53. package/docs/rules/prefer-lowercase-title.md +128 -0
  54. package/docs/rules/prefer-mock-promise-shorthand.md +41 -0
  55. package/docs/rules/prefer-mock-return-shorthand.md +50 -0
  56. package/docs/rules/prefer-snapshot-hint.md +192 -0
  57. package/docs/rules/prefer-spy-on.md +46 -0
  58. package/docs/rules/prefer-strict-equal.md +29 -0
  59. package/docs/rules/prefer-to-be.md +63 -0
  60. package/docs/rules/prefer-to-contain.md +53 -0
  61. package/docs/rules/prefer-to-have-been-called-times.md +43 -0
  62. package/docs/rules/prefer-to-have-been-called.md +35 -0
  63. package/docs/rules/prefer-to-have-length.md +41 -0
  64. package/docs/rules/prefer-todo.md +33 -0
  65. package/docs/rules/require-hook.md +187 -0
  66. package/docs/rules/require-to-throw-message.md +43 -0
  67. package/docs/rules/require-top-level-describe.md +86 -0
  68. package/docs/rules/unbound-method.md +61 -0
  69. package/docs/rules/valid-describe-callback.md +69 -0
  70. package/docs/rules/valid-expect-in-promise.md +79 -0
  71. package/docs/rules/valid-expect-with-promise.md +43 -0
  72. package/docs/rules/valid-expect.md +155 -0
  73. package/docs/rules/valid-mock-module-path.md +72 -0
  74. package/docs/rules/valid-title.md +319 -0
  75. package/index.d.ts +28 -0
  76. package/lib/globals.json +15 -0
  77. package/lib/index.js +85 -0
  78. package/lib/rules/consistent-test-it.js +101 -0
  79. package/lib/rules/expect-expect.js +102 -0
  80. package/lib/rules/max-expects.js +70 -0
  81. package/lib/rules/max-nested-describe.js +59 -0
  82. package/lib/rules/no-alias-methods.js +62 -0
  83. package/lib/rules/no-commented-out-tests.js +44 -0
  84. package/lib/rules/no-conditional-expect.js +80 -0
  85. package/lib/rules/no-conditional-in-test.js +63 -0
  86. package/lib/rules/no-confusing-set-timeout.js +61 -0
  87. package/lib/rules/no-deprecated-functions.js +81 -0
  88. package/lib/rules/no-disabled-tests.js +57 -0
  89. package/lib/rules/no-done-callback.js +120 -0
  90. package/lib/rules/no-duplicate-hooks.js +52 -0
  91. package/lib/rules/no-error-equal.js +41 -0
  92. package/lib/rules/no-export.js +61 -0
  93. package/lib/rules/no-focused-tests.js +63 -0
  94. package/lib/rules/no-hooks.js +51 -0
  95. package/lib/rules/no-identical-title.js +73 -0
  96. package/lib/rules/no-interpolation-in-snapshots.js +43 -0
  97. package/lib/rules/no-jasmine-globals.js +140 -0
  98. package/lib/rules/no-large-snapshots.js +100 -0
  99. package/lib/rules/no-mocks-import.js +46 -0
  100. package/lib/rules/no-restricted-jest-methods.js +53 -0
  101. package/lib/rules/no-restricted-matchers.js +60 -0
  102. package/lib/rules/no-standalone-expect.js +114 -0
  103. package/lib/rules/no-test-prefixes.js +48 -0
  104. package/lib/rules/no-test-return-statement.js +62 -0
  105. package/lib/rules/no-unnecessary-assertion.js +87 -0
  106. package/lib/rules/no-unneeded-async-expect-function.js +57 -0
  107. package/lib/rules/no-untyped-mock-factory.js +61 -0
  108. package/lib/rules/padding-around-after-all-blocks.js +17 -0
  109. package/lib/rules/padding-around-after-each-blocks.js +17 -0
  110. package/lib/rules/padding-around-all.js +15 -0
  111. package/lib/rules/padding-around-before-all-blocks.js +17 -0
  112. package/lib/rules/padding-around-before-each-blocks.js +17 -0
  113. package/lib/rules/padding-around-describe-blocks.js +17 -0
  114. package/lib/rules/padding-around-expect-groups.js +21 -0
  115. package/lib/rules/padding-around-test-blocks.js +17 -0
  116. package/lib/rules/prefer-called-with.js +47 -0
  117. package/lib/rules/prefer-comparison-matcher.js +111 -0
  118. package/lib/rules/prefer-each.js +77 -0
  119. package/lib/rules/prefer-ending-with-an-expect.js +102 -0
  120. package/lib/rules/prefer-equality-matcher.js +87 -0
  121. package/lib/rules/prefer-expect-assertions.js +237 -0
  122. package/lib/rules/prefer-expect-resolves.js +47 -0
  123. package/lib/rules/prefer-hooks-in-order.js +67 -0
  124. package/lib/rules/prefer-hooks-on-top.js +41 -0
  125. package/lib/rules/prefer-importing-jest-globals.js +126 -0
  126. package/lib/rules/prefer-jest-mocked.js +66 -0
  127. package/lib/rules/prefer-lowercase-title.js +128 -0
  128. package/lib/rules/prefer-mock-promise-shorthand.js +88 -0
  129. package/lib/rules/prefer-mock-return-shorthand.js +122 -0
  130. package/lib/rules/prefer-snapshot-hint.js +111 -0
  131. package/lib/rules/prefer-spy-on.js +80 -0
  132. package/lib/rules/prefer-strict-equal.js +46 -0
  133. package/lib/rules/prefer-to-be.js +98 -0
  134. package/lib/rules/prefer-to-contain.js +82 -0
  135. package/lib/rules/prefer-to-have-been-called-times.js +70 -0
  136. package/lib/rules/prefer-to-have-been-called.js +59 -0
  137. package/lib/rules/prefer-to-have-length.js +57 -0
  138. package/lib/rules/prefer-todo.js +72 -0
  139. package/lib/rules/require-hook.js +93 -0
  140. package/lib/rules/require-to-throw-message.js +45 -0
  141. package/lib/rules/require-top-level-describe.js +86 -0
  142. package/lib/rules/unbound-method.js +86 -0
  143. package/lib/rules/utils/accessors.js +127 -0
  144. package/lib/rules/utils/ast-utils.js +59 -0
  145. package/lib/rules/utils/detectJestVersion.js +24 -0
  146. package/lib/rules/utils/followTypeAssertionChain.js +10 -0
  147. package/lib/rules/utils/index.js +71 -0
  148. package/lib/rules/utils/misc.js +168 -0
  149. package/lib/rules/utils/padding.js +308 -0
  150. package/lib/rules/utils/parseJestFnCall.js +325 -0
  151. package/lib/rules/utils/ts.js +73 -0
  152. package/lib/rules/valid-describe-callback.js +94 -0
  153. package/lib/rules/valid-expect-in-promise.js +311 -0
  154. package/lib/rules/valid-expect-with-promise.js +54 -0
  155. package/lib/rules/valid-expect.js +302 -0
  156. package/lib/rules/valid-mock-module-path.js +90 -0
  157. package/lib/rules/valid-title.js +252 -0
  158. package/package.json +164 -0
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _utils = require("@typescript-eslint/utils");
8
+ var _utils2 = require("./utils");
9
+ var _default = exports.default = (0, _utils2.createRule)({
10
+ name: __filename,
11
+ meta: {
12
+ docs: {
13
+ description: 'Disallow Jasmine globals'
14
+ },
15
+ messages: {
16
+ illegalGlobal: 'Illegal usage of global `{{ global }}`, prefer `{{ replacement }}`',
17
+ illegalMethod: 'Illegal usage of `{{ method }}`, prefer `{{ replacement }}`',
18
+ illegalFail: 'Illegal usage of `fail`, prefer throwing an error, or the `done.fail` callback',
19
+ illegalPending: 'Illegal usage of `pending`, prefer explicitly skipping a test using `test.skip`',
20
+ illegalJasmine: 'Illegal usage of jasmine global'
21
+ },
22
+ fixable: 'code',
23
+ schema: [],
24
+ type: 'suggestion'
25
+ },
26
+ defaultOptions: [],
27
+ create(context) {
28
+ return {
29
+ CallExpression(node) {
30
+ const {
31
+ callee
32
+ } = node;
33
+ const calleeName = (0, _utils2.getNodeName)(callee);
34
+ if (!calleeName) {
35
+ return;
36
+ }
37
+ if (calleeName === 'spyOn' || calleeName === 'spyOnProperty' || calleeName === 'fail' || calleeName === 'pending') {
38
+ if ((0, _utils2.resolveScope)(context.sourceCode.getScope(node), calleeName)) {
39
+ // It's a local variable, not a jasmine global.
40
+ return;
41
+ }
42
+ switch (calleeName) {
43
+ case 'spyOn':
44
+ case 'spyOnProperty':
45
+ context.report({
46
+ node,
47
+ messageId: 'illegalGlobal',
48
+ data: {
49
+ global: calleeName,
50
+ replacement: 'jest.spyOn'
51
+ }
52
+ });
53
+ break;
54
+ case 'fail':
55
+ context.report({
56
+ node,
57
+ messageId: 'illegalFail'
58
+ });
59
+ break;
60
+ case 'pending':
61
+ context.report({
62
+ node,
63
+ messageId: 'illegalPending'
64
+ });
65
+ break;
66
+ }
67
+ return;
68
+ }
69
+ if (callee.type === _utils.AST_NODE_TYPES.MemberExpression && calleeName.startsWith('jasmine.')) {
70
+ const functionName = calleeName.replace('jasmine.', '');
71
+ if (functionName === 'any' || functionName === 'anything' || functionName === 'arrayContaining' || functionName === 'objectContaining' || functionName === 'stringMatching') {
72
+ context.report({
73
+ fix: fixer => [fixer.replaceText(callee.object, 'expect')],
74
+ node,
75
+ messageId: 'illegalMethod',
76
+ data: {
77
+ method: calleeName,
78
+ replacement: `expect.${functionName}`
79
+ }
80
+ });
81
+ return;
82
+ }
83
+ if (functionName === 'addMatchers') {
84
+ context.report({
85
+ node,
86
+ messageId: 'illegalMethod',
87
+ data: {
88
+ method: calleeName,
89
+ replacement: 'expect.extend'
90
+ }
91
+ });
92
+ return;
93
+ }
94
+ if (functionName === 'createSpy') {
95
+ context.report({
96
+ node,
97
+ messageId: 'illegalMethod',
98
+ data: {
99
+ method: calleeName,
100
+ replacement: 'jest.fn'
101
+ }
102
+ });
103
+ return;
104
+ }
105
+ context.report({
106
+ node,
107
+ messageId: 'illegalJasmine'
108
+ });
109
+ }
110
+ },
111
+ MemberExpression(node) {
112
+ if ((0, _utils2.isSupportedAccessor)(node.object, 'jasmine')) {
113
+ const {
114
+ parent,
115
+ property
116
+ } = node;
117
+ if (parent && parent.type === _utils.AST_NODE_TYPES.AssignmentExpression) {
118
+ if ((0, _utils2.isSupportedAccessor)(property, 'DEFAULT_TIMEOUT_INTERVAL')) {
119
+ const {
120
+ right
121
+ } = parent;
122
+ if (right.type === _utils.AST_NODE_TYPES.Literal) {
123
+ context.report({
124
+ fix: fixer => [fixer.replaceText(parent, `jest.setTimeout(${right.value})`)],
125
+ node,
126
+ messageId: 'illegalJasmine'
127
+ });
128
+ return;
129
+ }
130
+ }
131
+ context.report({
132
+ node,
133
+ messageId: 'illegalJasmine'
134
+ });
135
+ }
136
+ }
137
+ }
138
+ };
139
+ }
140
+ });
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _path = require("path");
8
+ var _utils = require("@typescript-eslint/utils");
9
+ var _utils2 = require("./utils");
10
+ const reportOnViolation = (context, node, {
11
+ maxSize: lineLimit = 50,
12
+ allowedSnapshots = {}
13
+ }) => {
14
+ const startLine = node.loc.start.line;
15
+ const endLine = node.loc.end.line;
16
+ const lineCount = endLine - startLine;
17
+ const allPathsAreAbsolute = Object.keys(allowedSnapshots).every(_path.isAbsolute);
18
+ if (!allPathsAreAbsolute) {
19
+ throw new Error('All paths for allowedSnapshots must be absolute. You can use JS config and `path.resolve`');
20
+ }
21
+ let isAllowed = false;
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)) {
23
+ const fileName = context.filename;
24
+ const allowedSnapshotsInFile = allowedSnapshots[fileName];
25
+ if (allowedSnapshotsInFile) {
26
+ const snapshotName = (0, _utils2.getAccessorValue)(node.expression.left.property);
27
+ isAllowed = allowedSnapshotsInFile.some(name => {
28
+ if (typeof name === 'string') {
29
+ return snapshotName === name;
30
+ }
31
+ return name.test(snapshotName);
32
+ });
33
+ }
34
+ }
35
+ if (!isAllowed && lineCount > lineLimit) {
36
+ context.report({
37
+ messageId: lineLimit === 0 ? 'noSnapshot' : 'tooLongSnapshots',
38
+ data: {
39
+ lineLimit,
40
+ lineCount
41
+ },
42
+ node
43
+ });
44
+ }
45
+ };
46
+ var _default = exports.default = (0, _utils2.createRule)({
47
+ name: __filename,
48
+ meta: {
49
+ docs: {
50
+ description: 'Disallow large snapshots'
51
+ },
52
+ messages: {
53
+ noSnapshot: 'Expected to not encounter a Jest snapshot but one was found that is {{ lineCount }} lines long',
54
+ tooLongSnapshots: 'Expected Jest snapshot to be smaller than {{ lineLimit }} lines but was {{ lineCount }} lines long'
55
+ },
56
+ type: 'suggestion',
57
+ schema: [{
58
+ type: 'object',
59
+ properties: {
60
+ maxSize: {
61
+ type: 'number'
62
+ },
63
+ inlineMaxSize: {
64
+ type: 'number'
65
+ },
66
+ allowedSnapshots: {
67
+ type: 'object',
68
+ additionalProperties: {
69
+ type: 'array'
70
+ }
71
+ }
72
+ },
73
+ additionalProperties: false
74
+ }]
75
+ },
76
+ defaultOptions: [{}],
77
+ create(context, [options]) {
78
+ if (context.filename.endsWith('.snap')) {
79
+ return {
80
+ ExpressionStatement(node) {
81
+ reportOnViolation(context, node, options);
82
+ }
83
+ };
84
+ }
85
+ return {
86
+ CallExpression(node) {
87
+ const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
88
+ if (jestFnCall?.type !== 'expect') {
89
+ return;
90
+ }
91
+ if (['toMatchInlineSnapshot', 'toThrowErrorMatchingInlineSnapshot'].includes((0, _utils2.getAccessorValue)(jestFnCall.matcher)) && jestFnCall.args.length) {
92
+ reportOnViolation(context, jestFnCall.args[0], {
93
+ ...options,
94
+ maxSize: options.inlineMaxSize ?? options.maxSize
95
+ });
96
+ }
97
+ }
98
+ };
99
+ }
100
+ });
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _path = require("path");
8
+ var _utils = require("./utils");
9
+ const mocksDirName = '__mocks__';
10
+ const isMockPath = path => path.split(_path.posix.sep).includes(mocksDirName);
11
+ const isMockImportLiteral = expression => (0, _utils.isStringNode)(expression) && isMockPath((0, _utils.getStringValue)(expression));
12
+ var _default = exports.default = (0, _utils.createRule)({
13
+ name: __filename,
14
+ meta: {
15
+ type: 'problem',
16
+ docs: {
17
+ description: 'Disallow manually importing from `__mocks__`'
18
+ },
19
+ messages: {
20
+ noManualImport: `Mocks should not be manually imported from a ${mocksDirName} directory. Instead use \`jest.mock\` and import from the original module path`
21
+ },
22
+ schema: []
23
+ },
24
+ defaultOptions: [],
25
+ create(context) {
26
+ return {
27
+ ImportDeclaration(node) {
28
+ if (isMockImportLiteral(node.source)) {
29
+ context.report({
30
+ node,
31
+ messageId: 'noManualImport'
32
+ });
33
+ }
34
+ },
35
+ 'CallExpression[callee.name="require"]'(node) {
36
+ const [arg] = node.arguments;
37
+ if (arg && isMockImportLiteral(arg)) {
38
+ context.report({
39
+ node: arg,
40
+ messageId: 'noManualImport'
41
+ });
42
+ }
43
+ }
44
+ };
45
+ }
46
+ });
@@ -0,0 +1,53 @@
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 = exports.default = (0, _utils.createRule)({
13
+ name: __filename,
14
+ meta: {
15
+ docs: {
16
+ description: 'Disallow specific `jest.` methods'
17
+ },
18
+ type: 'suggestion',
19
+ schema: [{
20
+ type: 'object',
21
+ additionalProperties: {
22
+ type: ['string', 'null']
23
+ }
24
+ }],
25
+ messages
26
+ },
27
+ defaultOptions: [{}],
28
+ create(context, [restrictedMethods]) {
29
+ return {
30
+ CallExpression(node) {
31
+ const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
32
+ if (jestFnCall?.type !== 'jest' || jestFnCall.members.length === 0) {
33
+ return;
34
+ }
35
+ const method = (0, _utils.getAccessorValue)(jestFnCall.members[0]);
36
+ if (method in restrictedMethods) {
37
+ const message = restrictedMethods[method];
38
+ context.report({
39
+ messageId: message ? 'restrictedJestMethodWithMessage' : 'restrictedJestMethod',
40
+ data: {
41
+ message,
42
+ restriction: method
43
+ },
44
+ loc: {
45
+ start: jestFnCall.members[0].loc.start,
46
+ end: jestFnCall.members[jestFnCall.members.length - 1].loc.end
47
+ }
48
+ });
49
+ }
50
+ }
51
+ };
52
+ }
53
+ });
@@ -0,0 +1,60 @@
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 isChainRestricted = (chain, restriction) => {
9
+ if (_utils.ModifierName.hasOwnProperty(restriction) || restriction.endsWith('.not')) {
10
+ return chain.startsWith(restriction);
11
+ }
12
+ return chain === restriction;
13
+ };
14
+ var _default = exports.default = (0, _utils.createRule)({
15
+ name: __filename,
16
+ meta: {
17
+ docs: {
18
+ description: 'Disallow specific matchers & modifiers'
19
+ },
20
+ type: 'suggestion',
21
+ schema: [{
22
+ type: 'object',
23
+ additionalProperties: {
24
+ type: ['string', 'null']
25
+ }
26
+ }],
27
+ messages: {
28
+ restrictedChain: 'Use of `{{ restriction }}` is disallowed',
29
+ restrictedChainWithMessage: '{{ message }}'
30
+ }
31
+ },
32
+ defaultOptions: [{}],
33
+ create(context, [restrictedChains]) {
34
+ return {
35
+ CallExpression(node) {
36
+ const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
37
+ if (jestFnCall?.type !== 'expect') {
38
+ return;
39
+ }
40
+ const chain = jestFnCall.members.map(nod => (0, _utils.getAccessorValue)(nod)).join('.');
41
+ for (const [restriction, message] of Object.entries(restrictedChains)) {
42
+ if (isChainRestricted(chain, restriction)) {
43
+ context.report({
44
+ messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
45
+ data: {
46
+ message,
47
+ restriction
48
+ },
49
+ loc: {
50
+ start: jestFnCall.members[0].loc.start,
51
+ end: jestFnCall.members[jestFnCall.members.length - 1].loc.end
52
+ }
53
+ });
54
+ break;
55
+ }
56
+ }
57
+ }
58
+ };
59
+ }
60
+ });
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _utils = require("@typescript-eslint/utils");
8
+ var _utils2 = require("./utils");
9
+ const getBlockType = (statement, context) => {
10
+ const func = statement.parent;
11
+
12
+ // functionDeclaration: function func() {}
13
+ if (func.type === _utils.AST_NODE_TYPES.FunctionDeclaration) {
14
+ return 'function';
15
+ }
16
+ if ((0, _utils2.isFunction)(func)) {
17
+ const expr = func.parent;
18
+
19
+ // arrow function or function expr
20
+ if (expr.type === _utils.AST_NODE_TYPES.VariableDeclarator) {
21
+ return 'function';
22
+ }
23
+
24
+ // if it's not a variable, it will be callExpr, we only care about describe
25
+ if (expr.type === _utils.AST_NODE_TYPES.CallExpression && (0, _utils2.isTypeOfJestFnCall)(expr, context, ['describe'])) {
26
+ return 'describe';
27
+ }
28
+ }
29
+ return null;
30
+ };
31
+ var _default = exports.default = (0, _utils2.createRule)({
32
+ name: __filename,
33
+ meta: {
34
+ docs: {
35
+ description: 'Disallow using `expect` outside of `it` or `test` blocks'
36
+ },
37
+ messages: {
38
+ unexpectedExpect: 'Expect must be inside of a test block'
39
+ },
40
+ type: 'suggestion',
41
+ schema: [{
42
+ type: 'object',
43
+ properties: {
44
+ additionalTestBlockFunctions: {
45
+ type: 'array',
46
+ items: {
47
+ type: 'string'
48
+ }
49
+ }
50
+ },
51
+ additionalProperties: false
52
+ }]
53
+ },
54
+ defaultOptions: [{
55
+ additionalTestBlockFunctions: []
56
+ }],
57
+ create(context, [{
58
+ additionalTestBlockFunctions = []
59
+ }]) {
60
+ const callStack = [];
61
+ const isCustomTestBlockFunction = node => additionalTestBlockFunctions.includes((0, _utils2.getNodeName)(node) || '');
62
+ return {
63
+ CallExpression(node) {
64
+ const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
65
+ if (jestFnCall?.type === 'expect') {
66
+ if (jestFnCall.head.node.parent.type === _utils.AST_NODE_TYPES.MemberExpression && jestFnCall.members.length === 1 && !['assertions', 'hasAssertions'].includes((0, _utils2.getAccessorValue)(jestFnCall.members[0]))) {
67
+ return;
68
+ }
69
+ const parent = callStack[callStack.length - 1];
70
+ if (!parent || parent === _utils2.DescribeAlias.describe) {
71
+ context.report({
72
+ node,
73
+ messageId: 'unexpectedExpect'
74
+ });
75
+ }
76
+ return;
77
+ }
78
+ if (jestFnCall?.type === 'test' || isCustomTestBlockFunction(node)) {
79
+ callStack.push('test');
80
+ }
81
+ if (node.callee.type === _utils.AST_NODE_TYPES.TaggedTemplateExpression) {
82
+ callStack.push('template');
83
+ }
84
+ },
85
+ 'CallExpression:exit'(node) {
86
+ const top = callStack[callStack.length - 1];
87
+ 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) {
88
+ callStack.pop();
89
+ }
90
+ },
91
+ BlockStatement(statement) {
92
+ const blockType = getBlockType(statement, context);
93
+ if (blockType) {
94
+ callStack.push(blockType);
95
+ }
96
+ },
97
+ 'BlockStatement:exit'(statement) {
98
+ if (callStack[callStack.length - 1] === getBlockType(statement, context)) {
99
+ callStack.pop();
100
+ }
101
+ },
102
+ ArrowFunctionExpression(node) {
103
+ if (node.parent.type !== _utils.AST_NODE_TYPES.CallExpression) {
104
+ callStack.push('arrow');
105
+ }
106
+ },
107
+ 'ArrowFunctionExpression:exit'() {
108
+ if (callStack[callStack.length - 1] === 'arrow') {
109
+ callStack.pop();
110
+ }
111
+ }
112
+ };
113
+ }
114
+ });
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _utils = require("@typescript-eslint/utils");
8
+ var _utils2 = require("./utils");
9
+ var _default = exports.default = (0, _utils2.createRule)({
10
+ name: __filename,
11
+ meta: {
12
+ docs: {
13
+ description: 'Require using `.only` and `.skip` over `f` and `x`'
14
+ },
15
+ messages: {
16
+ usePreferredName: 'Use "{{ preferredNodeName }}" instead'
17
+ },
18
+ fixable: 'code',
19
+ schema: [],
20
+ type: 'suggestion'
21
+ },
22
+ defaultOptions: [],
23
+ create(context) {
24
+ return {
25
+ CallExpression(node) {
26
+ const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
27
+ if (jestFnCall?.type !== 'describe' && jestFnCall?.type !== 'test') {
28
+ return;
29
+ }
30
+ if (jestFnCall.name[0] !== 'f' && jestFnCall.name[0] !== 'x') {
31
+ return;
32
+ }
33
+ const preferredNodeName = [jestFnCall.name.slice(1), jestFnCall.name[0] === 'f' ? 'only' : 'skip', ...jestFnCall.members.map(s => (0, _utils2.getAccessorValue)(s))].join('.');
34
+ 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;
35
+ context.report({
36
+ messageId: 'usePreferredName',
37
+ node: node.callee,
38
+ data: {
39
+ preferredNodeName
40
+ },
41
+ fix(fixer) {
42
+ return [fixer.replaceText(funcNode, preferredNodeName)];
43
+ }
44
+ });
45
+ }
46
+ };
47
+ }
48
+ });
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _utils = require("@typescript-eslint/utils");
8
+ var _utils2 = require("./utils");
9
+ const getBody = args => {
10
+ const [, secondArg] = args;
11
+ if (secondArg && (0, _utils2.isFunction)(secondArg) && secondArg.body.type === _utils.AST_NODE_TYPES.BlockStatement) {
12
+ return secondArg.body.body;
13
+ }
14
+ return [];
15
+ };
16
+ var _default = exports.default = (0, _utils2.createRule)({
17
+ name: __filename,
18
+ meta: {
19
+ docs: {
20
+ description: 'Disallow explicitly returning from tests'
21
+ },
22
+ messages: {
23
+ noReturnValue: 'Jest tests should not return a value'
24
+ },
25
+ schema: [],
26
+ type: 'suggestion'
27
+ },
28
+ defaultOptions: [],
29
+ create(context) {
30
+ return {
31
+ CallExpression(node) {
32
+ if (!(0, _utils2.isTypeOfJestFnCall)(node, context, ['test'])) {
33
+ return;
34
+ }
35
+ const body = getBody(node.arguments);
36
+ const returnStmt = body.find(t => t.type === _utils.AST_NODE_TYPES.ReturnStatement);
37
+ if (!returnStmt) {
38
+ return;
39
+ }
40
+ context.report({
41
+ messageId: 'noReturnValue',
42
+ node: returnStmt
43
+ });
44
+ },
45
+ FunctionDeclaration(node) {
46
+ const declaredVariables = context.sourceCode.getDeclaredVariables(node);
47
+ const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables, context);
48
+ if (testCallExpressions.length === 0) {
49
+ return;
50
+ }
51
+ const returnStmt = node.body.body.find(t => t.type === _utils.AST_NODE_TYPES.ReturnStatement);
52
+ if (!returnStmt) {
53
+ return;
54
+ }
55
+ context.report({
56
+ messageId: 'noReturnValue',
57
+ node: returnStmt
58
+ });
59
+ }
60
+ };
61
+ }
62
+ });