@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.
- package/LICENSE +21 -0
- package/README.md +31 -0
- package/changes.json +10 -0
- package/docs/rules/consistent-test-it.md +96 -0
- package/docs/rules/expect-expect.md +152 -0
- package/docs/rules/max-expects.md +78 -0
- package/docs/rules/max-nested-describe.md +134 -0
- package/docs/rules/no-alias-methods.md +57 -0
- package/docs/rules/no-commented-out-tests.md +68 -0
- package/docs/rules/no-conditional-expect.md +142 -0
- package/docs/rules/no-conditional-in-test.md +123 -0
- package/docs/rules/no-confusing-set-timeout.md +64 -0
- package/docs/rules/no-deprecated-functions.md +59 -0
- package/docs/rules/no-disabled-tests.md +72 -0
- package/docs/rules/no-done-callback.md +100 -0
- package/docs/rules/no-duplicate-hooks.md +79 -0
- package/docs/rules/no-error-equal.md +37 -0
- package/docs/rules/no-export.md +52 -0
- package/docs/rules/no-focused-tests.md +67 -0
- package/docs/rules/no-hooks.md +178 -0
- package/docs/rules/no-identical-title.md +59 -0
- package/docs/rules/no-interpolation-in-snapshots.md +67 -0
- package/docs/rules/no-jasmine-globals.md +69 -0
- package/docs/rules/no-large-snapshots.md +180 -0
- package/docs/rules/no-mocks-import.md +34 -0
- package/docs/rules/no-restricted-jest-methods.md +53 -0
- package/docs/rules/no-restricted-matchers.md +64 -0
- package/docs/rules/no-standalone-expect.md +106 -0
- package/docs/rules/no-test-prefixes.md +42 -0
- package/docs/rules/no-test-return-statement.md +50 -0
- package/docs/rules/no-unnecessary-assertion.md +41 -0
- package/docs/rules/no-unneeded-async-expect-function.md +41 -0
- package/docs/rules/no-untyped-mock-factory.md +74 -0
- package/docs/rules/padding-around-after-all-blocks.md +34 -0
- package/docs/rules/padding-around-after-each-blocks.md +38 -0
- package/docs/rules/padding-around-all.md +20 -0
- package/docs/rules/padding-around-before-all-blocks.md +37 -0
- package/docs/rules/padding-around-before-each-blocks.md +38 -0
- package/docs/rules/padding-around-describe-blocks.md +42 -0
- package/docs/rules/padding-around-expect-groups.md +44 -0
- package/docs/rules/padding-around-test-blocks.md +48 -0
- package/docs/rules/prefer-called-with.md +39 -0
- package/docs/rules/prefer-comparison-matcher.md +62 -0
- package/docs/rules/prefer-each.md +58 -0
- package/docs/rules/prefer-ending-with-an-expect.md +170 -0
- package/docs/rules/prefer-equality-matcher.md +36 -0
- package/docs/rules/prefer-expect-assertions.md +230 -0
- package/docs/rules/prefer-expect-resolves.md +62 -0
- package/docs/rules/prefer-hooks-in-order.md +137 -0
- package/docs/rules/prefer-hooks-on-top.md +124 -0
- package/docs/rules/prefer-importing-jest-globals.md +85 -0
- package/docs/rules/prefer-jest-mocked.md +40 -0
- package/docs/rules/prefer-lowercase-title.md +128 -0
- package/docs/rules/prefer-mock-promise-shorthand.md +41 -0
- package/docs/rules/prefer-mock-return-shorthand.md +50 -0
- package/docs/rules/prefer-snapshot-hint.md +192 -0
- package/docs/rules/prefer-spy-on.md +46 -0
- package/docs/rules/prefer-strict-equal.md +29 -0
- package/docs/rules/prefer-to-be.md +63 -0
- package/docs/rules/prefer-to-contain.md +53 -0
- package/docs/rules/prefer-to-have-been-called-times.md +43 -0
- package/docs/rules/prefer-to-have-been-called.md +35 -0
- package/docs/rules/prefer-to-have-length.md +41 -0
- package/docs/rules/prefer-todo.md +33 -0
- package/docs/rules/require-hook.md +187 -0
- package/docs/rules/require-to-throw-message.md +43 -0
- package/docs/rules/require-top-level-describe.md +86 -0
- package/docs/rules/unbound-method.md +61 -0
- package/docs/rules/valid-describe-callback.md +69 -0
- package/docs/rules/valid-expect-in-promise.md +79 -0
- package/docs/rules/valid-expect-with-promise.md +43 -0
- package/docs/rules/valid-expect.md +155 -0
- package/docs/rules/valid-mock-module-path.md +72 -0
- package/docs/rules/valid-title.md +319 -0
- package/index.d.ts +28 -0
- package/lib/globals.json +15 -0
- package/lib/index.js +85 -0
- package/lib/rules/consistent-test-it.js +101 -0
- package/lib/rules/expect-expect.js +102 -0
- package/lib/rules/max-expects.js +70 -0
- package/lib/rules/max-nested-describe.js +59 -0
- package/lib/rules/no-alias-methods.js +62 -0
- package/lib/rules/no-commented-out-tests.js +44 -0
- package/lib/rules/no-conditional-expect.js +80 -0
- package/lib/rules/no-conditional-in-test.js +63 -0
- package/lib/rules/no-confusing-set-timeout.js +61 -0
- package/lib/rules/no-deprecated-functions.js +81 -0
- package/lib/rules/no-disabled-tests.js +57 -0
- package/lib/rules/no-done-callback.js +120 -0
- package/lib/rules/no-duplicate-hooks.js +52 -0
- package/lib/rules/no-error-equal.js +41 -0
- package/lib/rules/no-export.js +61 -0
- package/lib/rules/no-focused-tests.js +63 -0
- package/lib/rules/no-hooks.js +51 -0
- package/lib/rules/no-identical-title.js +73 -0
- package/lib/rules/no-interpolation-in-snapshots.js +43 -0
- package/lib/rules/no-jasmine-globals.js +140 -0
- package/lib/rules/no-large-snapshots.js +100 -0
- package/lib/rules/no-mocks-import.js +46 -0
- package/lib/rules/no-restricted-jest-methods.js +53 -0
- package/lib/rules/no-restricted-matchers.js +60 -0
- package/lib/rules/no-standalone-expect.js +114 -0
- package/lib/rules/no-test-prefixes.js +48 -0
- package/lib/rules/no-test-return-statement.js +62 -0
- package/lib/rules/no-unnecessary-assertion.js +87 -0
- package/lib/rules/no-unneeded-async-expect-function.js +57 -0
- package/lib/rules/no-untyped-mock-factory.js +61 -0
- package/lib/rules/padding-around-after-all-blocks.js +17 -0
- package/lib/rules/padding-around-after-each-blocks.js +17 -0
- package/lib/rules/padding-around-all.js +15 -0
- package/lib/rules/padding-around-before-all-blocks.js +17 -0
- package/lib/rules/padding-around-before-each-blocks.js +17 -0
- package/lib/rules/padding-around-describe-blocks.js +17 -0
- package/lib/rules/padding-around-expect-groups.js +21 -0
- package/lib/rules/padding-around-test-blocks.js +17 -0
- package/lib/rules/prefer-called-with.js +47 -0
- package/lib/rules/prefer-comparison-matcher.js +111 -0
- package/lib/rules/prefer-each.js +77 -0
- package/lib/rules/prefer-ending-with-an-expect.js +102 -0
- package/lib/rules/prefer-equality-matcher.js +87 -0
- package/lib/rules/prefer-expect-assertions.js +237 -0
- package/lib/rules/prefer-expect-resolves.js +47 -0
- package/lib/rules/prefer-hooks-in-order.js +67 -0
- package/lib/rules/prefer-hooks-on-top.js +41 -0
- package/lib/rules/prefer-importing-jest-globals.js +126 -0
- package/lib/rules/prefer-jest-mocked.js +66 -0
- package/lib/rules/prefer-lowercase-title.js +128 -0
- package/lib/rules/prefer-mock-promise-shorthand.js +88 -0
- package/lib/rules/prefer-mock-return-shorthand.js +122 -0
- package/lib/rules/prefer-snapshot-hint.js +111 -0
- package/lib/rules/prefer-spy-on.js +80 -0
- package/lib/rules/prefer-strict-equal.js +46 -0
- package/lib/rules/prefer-to-be.js +98 -0
- package/lib/rules/prefer-to-contain.js +82 -0
- package/lib/rules/prefer-to-have-been-called-times.js +70 -0
- package/lib/rules/prefer-to-have-been-called.js +59 -0
- package/lib/rules/prefer-to-have-length.js +57 -0
- package/lib/rules/prefer-todo.js +72 -0
- package/lib/rules/require-hook.js +93 -0
- package/lib/rules/require-to-throw-message.js +45 -0
- package/lib/rules/require-top-level-describe.js +86 -0
- package/lib/rules/unbound-method.js +86 -0
- package/lib/rules/utils/accessors.js +127 -0
- package/lib/rules/utils/ast-utils.js +59 -0
- package/lib/rules/utils/detectJestVersion.js +24 -0
- package/lib/rules/utils/followTypeAssertionChain.js +10 -0
- package/lib/rules/utils/index.js +71 -0
- package/lib/rules/utils/misc.js +168 -0
- package/lib/rules/utils/padding.js +308 -0
- package/lib/rules/utils/parseJestFnCall.js +325 -0
- package/lib/rules/utils/ts.js +73 -0
- package/lib/rules/valid-describe-callback.js +94 -0
- package/lib/rules/valid-expect-in-promise.js +311 -0
- package/lib/rules/valid-expect-with-promise.js +54 -0
- package/lib/rules/valid-expect.js +302 -0
- package/lib/rules/valid-mock-module-path.js +90 -0
- package/lib/rules/valid-title.js +252 -0
- package/package.json +164 -0
|
@@ -0,0 +1,101 @@
|
|
|
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 buildFixer = (callee, nodeName, preferredTestKeyword) => fixer => [fixer.replaceText(callee.type === _utils.AST_NODE_TYPES.MemberExpression ? callee.object : callee, getPreferredNodeName(nodeName, preferredTestKeyword))];
|
|
10
|
+
var _default = exports.default = (0, _utils2.createRule)({
|
|
11
|
+
name: __filename,
|
|
12
|
+
meta: {
|
|
13
|
+
docs: {
|
|
14
|
+
description: 'Enforce `test` and `it` usage conventions'
|
|
15
|
+
},
|
|
16
|
+
fixable: 'code',
|
|
17
|
+
messages: {
|
|
18
|
+
consistentMethod: "Prefer using '{{ testKeyword }}' instead of '{{ oppositeTestKeyword }}'",
|
|
19
|
+
consistentMethodWithinDescribe: "Prefer using '{{ testKeywordWithinDescribe }}' instead of '{{ oppositeTestKeyword }}' within describe"
|
|
20
|
+
},
|
|
21
|
+
schema: [{
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
fn: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
enum: [_utils2.TestCaseName.it, _utils2.TestCaseName.test]
|
|
27
|
+
},
|
|
28
|
+
withinDescribe: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
enum: [_utils2.TestCaseName.it, _utils2.TestCaseName.test]
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
additionalProperties: false
|
|
34
|
+
}],
|
|
35
|
+
type: 'suggestion'
|
|
36
|
+
},
|
|
37
|
+
defaultOptions: [{
|
|
38
|
+
fn: _utils2.TestCaseName.test,
|
|
39
|
+
withinDescribe: _utils2.TestCaseName.it
|
|
40
|
+
}],
|
|
41
|
+
create(context) {
|
|
42
|
+
const configObj = context.options[0] || {};
|
|
43
|
+
const testKeyword = configObj.fn || _utils2.TestCaseName.test;
|
|
44
|
+
const testKeywordWithinDescribe = configObj.withinDescribe || configObj.fn || _utils2.TestCaseName.it;
|
|
45
|
+
let describeNestingLevel = 0;
|
|
46
|
+
return {
|
|
47
|
+
CallExpression(node) {
|
|
48
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
49
|
+
if (!jestFnCall) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (jestFnCall.type === 'describe') {
|
|
53
|
+
describeNestingLevel++;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
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;
|
|
57
|
+
if (jestFnCall.type === 'test' && describeNestingLevel === 0 && !jestFnCall.name.endsWith(testKeyword)) {
|
|
58
|
+
const oppositeTestKeyword = getOppositeTestKeyword(testKeyword);
|
|
59
|
+
context.report({
|
|
60
|
+
messageId: 'consistentMethod',
|
|
61
|
+
node: node.callee,
|
|
62
|
+
data: {
|
|
63
|
+
testKeyword,
|
|
64
|
+
oppositeTestKeyword
|
|
65
|
+
},
|
|
66
|
+
fix: buildFixer(funcNode, jestFnCall.name, testKeyword)
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (jestFnCall.type === 'test' && describeNestingLevel > 0 && !jestFnCall.name.endsWith(testKeywordWithinDescribe)) {
|
|
70
|
+
const oppositeTestKeyword = getOppositeTestKeyword(testKeywordWithinDescribe);
|
|
71
|
+
context.report({
|
|
72
|
+
messageId: 'consistentMethodWithinDescribe',
|
|
73
|
+
node: node.callee,
|
|
74
|
+
data: {
|
|
75
|
+
testKeywordWithinDescribe,
|
|
76
|
+
oppositeTestKeyword
|
|
77
|
+
},
|
|
78
|
+
fix: buildFixer(funcNode, jestFnCall.name, testKeywordWithinDescribe)
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
'CallExpression:exit'(node) {
|
|
83
|
+
if ((0, _utils2.isTypeOfJestFnCall)(node, context, ['describe'])) {
|
|
84
|
+
describeNestingLevel--;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
function getPreferredNodeName(nodeName, preferredTestKeyword) {
|
|
91
|
+
if (nodeName === _utils2.TestCaseName.fit) {
|
|
92
|
+
return 'test.only';
|
|
93
|
+
}
|
|
94
|
+
return nodeName.startsWith('f') || nodeName.startsWith('x') ? nodeName.charAt(0) + preferredTestKeyword : preferredTestKeyword;
|
|
95
|
+
}
|
|
96
|
+
function getOppositeTestKeyword(test) {
|
|
97
|
+
if (test === _utils2.TestCaseName.test) {
|
|
98
|
+
return _utils2.TestCaseName.it;
|
|
99
|
+
}
|
|
100
|
+
return _utils2.TestCaseName.test;
|
|
101
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
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
|
+
/*
|
|
10
|
+
* This implementation is adapted from eslint-plugin-jasmine.
|
|
11
|
+
* MIT license, Remco Haszing.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Checks if node names returned by getNodeName matches any of the given star patterns
|
|
16
|
+
* Pattern examples:
|
|
17
|
+
* request.*.expect
|
|
18
|
+
* request.**.expect
|
|
19
|
+
* request.**.expect*
|
|
20
|
+
*/
|
|
21
|
+
function matchesAssertFunctionName(nodeName, patterns) {
|
|
22
|
+
return patterns.some(p => new RegExp(`^${p.split('.').map(x => {
|
|
23
|
+
if (x === '**') {
|
|
24
|
+
return '[a-z\\d\\.]*';
|
|
25
|
+
}
|
|
26
|
+
return x.replace(/\*/gu, '[a-z\\d]*');
|
|
27
|
+
}).join('\\.')}(\\.|$)`, 'ui').test(nodeName));
|
|
28
|
+
}
|
|
29
|
+
var _default = exports.default = (0, _utils2.createRule)({
|
|
30
|
+
name: __filename,
|
|
31
|
+
meta: {
|
|
32
|
+
docs: {
|
|
33
|
+
description: 'Enforce assertion to be made in a test body'
|
|
34
|
+
},
|
|
35
|
+
messages: {
|
|
36
|
+
noAssertions: 'Test has no assertions'
|
|
37
|
+
},
|
|
38
|
+
schema: [{
|
|
39
|
+
type: 'object',
|
|
40
|
+
properties: {
|
|
41
|
+
assertFunctionNames: {
|
|
42
|
+
type: 'array',
|
|
43
|
+
items: {
|
|
44
|
+
type: 'string'
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
additionalTestBlockFunctions: {
|
|
48
|
+
type: 'array',
|
|
49
|
+
items: {
|
|
50
|
+
type: 'string'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
additionalProperties: false
|
|
55
|
+
}],
|
|
56
|
+
type: 'suggestion'
|
|
57
|
+
},
|
|
58
|
+
defaultOptions: [{
|
|
59
|
+
assertFunctionNames: ['expect'],
|
|
60
|
+
additionalTestBlockFunctions: []
|
|
61
|
+
}],
|
|
62
|
+
create(context, [{
|
|
63
|
+
assertFunctionNames = ['expect'],
|
|
64
|
+
additionalTestBlockFunctions = []
|
|
65
|
+
}]) {
|
|
66
|
+
const unchecked = [];
|
|
67
|
+
function checkCallExpressionUsed(nodes) {
|
|
68
|
+
for (const node of nodes) {
|
|
69
|
+
const index = node.type === _utils.AST_NODE_TYPES.CallExpression ? unchecked.indexOf(node) : -1;
|
|
70
|
+
if (node.type === _utils.AST_NODE_TYPES.FunctionDeclaration) {
|
|
71
|
+
const declaredVariables = context.sourceCode.getDeclaredVariables(node);
|
|
72
|
+
const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables, context);
|
|
73
|
+
checkCallExpressionUsed(testCallExpressions);
|
|
74
|
+
}
|
|
75
|
+
if (index !== -1) {
|
|
76
|
+
unchecked.splice(index, 1);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
CallExpression(node) {
|
|
83
|
+
const name = (0, _utils2.getNodeName)(node.callee) ?? '';
|
|
84
|
+
if ((0, _utils2.isTypeOfJestFnCall)(node, context, ['test']) || additionalTestBlockFunctions.includes(name)) {
|
|
85
|
+
if (node.callee.type === _utils.AST_NODE_TYPES.MemberExpression && (0, _utils2.isSupportedAccessor)(node.callee.property, 'todo')) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
unchecked.push(node);
|
|
89
|
+
} else if (matchesAssertFunctionName(name, assertFunctionNames)) {
|
|
90
|
+
// Return early in case of nested `it` statements.
|
|
91
|
+
checkCallExpressionUsed(context.sourceCode.getAncestors(node));
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
'Program:exit'() {
|
|
95
|
+
unchecked.forEach(node => context.report({
|
|
96
|
+
messageId: 'noAssertions',
|
|
97
|
+
node: node.callee
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
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: 'Enforces a maximum number assertion calls in a test body'
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
exceededMaxAssertion: 'Too many assertion calls ({{ count }}) - maximum allowed is {{ max }}'
|
|
17
|
+
},
|
|
18
|
+
type: 'suggestion',
|
|
19
|
+
schema: [{
|
|
20
|
+
type: 'object',
|
|
21
|
+
properties: {
|
|
22
|
+
max: {
|
|
23
|
+
type: 'integer',
|
|
24
|
+
minimum: 1
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
additionalProperties: false
|
|
28
|
+
}]
|
|
29
|
+
},
|
|
30
|
+
defaultOptions: [{
|
|
31
|
+
max: 5
|
|
32
|
+
}],
|
|
33
|
+
create(context, [{
|
|
34
|
+
max
|
|
35
|
+
}]) {
|
|
36
|
+
let count = 0;
|
|
37
|
+
const maybeResetCount = node => {
|
|
38
|
+
const isTestFn = node.parent.type !== _utils.AST_NODE_TYPES.CallExpression || (0, _utils2.isTypeOfJestFnCall)(node.parent, context, ['test']);
|
|
39
|
+
if (isTestFn) {
|
|
40
|
+
count = 0;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
FunctionExpression: maybeResetCount,
|
|
45
|
+
'FunctionExpression:exit': maybeResetCount,
|
|
46
|
+
ArrowFunctionExpression: maybeResetCount,
|
|
47
|
+
'ArrowFunctionExpression:exit': maybeResetCount,
|
|
48
|
+
CallExpression(node) {
|
|
49
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
50
|
+
if (jestFnCall?.type === 'test') {
|
|
51
|
+
count = 0;
|
|
52
|
+
}
|
|
53
|
+
if (jestFnCall?.type !== 'expect' || jestFnCall.head.node.parent.type === _utils.AST_NODE_TYPES.MemberExpression) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
count += 1;
|
|
57
|
+
if (count > max) {
|
|
58
|
+
context.report({
|
|
59
|
+
node,
|
|
60
|
+
messageId: 'exceededMaxAssertion',
|
|
61
|
+
data: {
|
|
62
|
+
count,
|
|
63
|
+
max
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _utils = require("./utils");
|
|
8
|
+
var _default = exports.default = (0, _utils.createRule)({
|
|
9
|
+
name: __filename,
|
|
10
|
+
meta: {
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Enforces a maximum depth to nested describe calls'
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
exceededMaxDepth: 'Too many nested describe calls ({{ depth }}) - maximum allowed is {{ max }}'
|
|
16
|
+
},
|
|
17
|
+
type: 'suggestion',
|
|
18
|
+
schema: [{
|
|
19
|
+
type: 'object',
|
|
20
|
+
properties: {
|
|
21
|
+
max: {
|
|
22
|
+
type: 'integer',
|
|
23
|
+
minimum: 0
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
additionalProperties: false
|
|
27
|
+
}]
|
|
28
|
+
},
|
|
29
|
+
defaultOptions: [{
|
|
30
|
+
max: 5
|
|
31
|
+
}],
|
|
32
|
+
create(context, [{
|
|
33
|
+
max
|
|
34
|
+
}]) {
|
|
35
|
+
const describes = [];
|
|
36
|
+
return {
|
|
37
|
+
CallExpression(node) {
|
|
38
|
+
if ((0, _utils.isTypeOfJestFnCall)(node, context, ['describe'])) {
|
|
39
|
+
describes.unshift(node);
|
|
40
|
+
if (describes.length > max) {
|
|
41
|
+
context.report({
|
|
42
|
+
node,
|
|
43
|
+
messageId: 'exceededMaxDepth',
|
|
44
|
+
data: {
|
|
45
|
+
depth: describes.length,
|
|
46
|
+
max
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
'CallExpression:exit'(node) {
|
|
53
|
+
if (describes[0] === node) {
|
|
54
|
+
describes.shift();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
@@ -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("./utils");
|
|
8
|
+
var _default = exports.default = (0, _utils.createRule)({
|
|
9
|
+
name: __filename,
|
|
10
|
+
meta: {
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Disallow alias methods'
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
replaceAlias: `Replace {{ alias }}() with its canonical name of {{ canonical }}()`
|
|
16
|
+
},
|
|
17
|
+
fixable: 'code',
|
|
18
|
+
type: 'suggestion',
|
|
19
|
+
schema: []
|
|
20
|
+
},
|
|
21
|
+
defaultOptions: [],
|
|
22
|
+
create(context) {
|
|
23
|
+
// map of jest matcher aliases & their canonical names
|
|
24
|
+
const methodNames = {
|
|
25
|
+
toBeCalled: 'toHaveBeenCalled',
|
|
26
|
+
toBeCalledTimes: 'toHaveBeenCalledTimes',
|
|
27
|
+
toBeCalledWith: 'toHaveBeenCalledWith',
|
|
28
|
+
lastCalledWith: 'toHaveBeenLastCalledWith',
|
|
29
|
+
nthCalledWith: 'toHaveBeenNthCalledWith',
|
|
30
|
+
toReturn: 'toHaveReturned',
|
|
31
|
+
toReturnTimes: 'toHaveReturnedTimes',
|
|
32
|
+
toReturnWith: 'toHaveReturnedWith',
|
|
33
|
+
lastReturnedWith: 'toHaveLastReturnedWith',
|
|
34
|
+
nthReturnedWith: 'toHaveNthReturnedWith',
|
|
35
|
+
toThrowError: 'toThrow'
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
CallExpression(node) {
|
|
39
|
+
const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
|
|
40
|
+
if (jestFnCall?.type !== 'expect') {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const {
|
|
44
|
+
matcher
|
|
45
|
+
} = jestFnCall;
|
|
46
|
+
const alias = (0, _utils.getAccessorValue)(matcher);
|
|
47
|
+
if (alias in methodNames) {
|
|
48
|
+
const canonical = methodNames[alias];
|
|
49
|
+
context.report({
|
|
50
|
+
messageId: 'replaceAlias',
|
|
51
|
+
data: {
|
|
52
|
+
alias,
|
|
53
|
+
canonical
|
|
54
|
+
},
|
|
55
|
+
node: matcher,
|
|
56
|
+
fix: fixer => [(0, _utils.replaceAccessorFixer)(fixer, matcher, canonical)]
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _utils = require("./utils");
|
|
8
|
+
function hasTests(node) {
|
|
9
|
+
return /^\s*[xf]?(test|it|describe)(\.\w+|\[['"]\w+['"]\])?\s*\(/mu.test(node.value);
|
|
10
|
+
}
|
|
11
|
+
var _default = exports.default = (0, _utils.createRule)({
|
|
12
|
+
name: __filename,
|
|
13
|
+
meta: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: 'Disallow commented out tests'
|
|
16
|
+
},
|
|
17
|
+
messages: {
|
|
18
|
+
commentedTests: 'Do not comment out tests'
|
|
19
|
+
},
|
|
20
|
+
schema: [],
|
|
21
|
+
type: 'suggestion'
|
|
22
|
+
},
|
|
23
|
+
defaultOptions: [],
|
|
24
|
+
create(context) {
|
|
25
|
+
const {
|
|
26
|
+
sourceCode
|
|
27
|
+
} = context;
|
|
28
|
+
function checkNode(node) {
|
|
29
|
+
if (!hasTests(node)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
context.report({
|
|
33
|
+
messageId: 'commentedTests',
|
|
34
|
+
node
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
Program() {
|
|
39
|
+
const comments = sourceCode.getAllComments();
|
|
40
|
+
comments.forEach(checkNode);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
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 isCatchCall = node => node.callee.type === _utils.AST_NODE_TYPES.MemberExpression && (0, _utils2.isSupportedAccessor)(node.callee.property, 'catch');
|
|
10
|
+
var _default = exports.default = (0, _utils2.createRule)({
|
|
11
|
+
name: __filename,
|
|
12
|
+
meta: {
|
|
13
|
+
docs: {
|
|
14
|
+
description: 'Disallow calling `expect` conditionally'
|
|
15
|
+
},
|
|
16
|
+
messages: {
|
|
17
|
+
conditionalExpect: 'Avoid calling `expect` conditionally`'
|
|
18
|
+
},
|
|
19
|
+
type: 'problem',
|
|
20
|
+
schema: []
|
|
21
|
+
},
|
|
22
|
+
defaultOptions: [],
|
|
23
|
+
create(context) {
|
|
24
|
+
let conditionalDepth = 0;
|
|
25
|
+
let inTestCase = false;
|
|
26
|
+
let inPromiseCatch = false;
|
|
27
|
+
const increaseConditionalDepth = () => inTestCase && conditionalDepth++;
|
|
28
|
+
const decreaseConditionalDepth = () => inTestCase && conditionalDepth--;
|
|
29
|
+
return {
|
|
30
|
+
FunctionDeclaration(node) {
|
|
31
|
+
const declaredVariables = context.sourceCode.getDeclaredVariables(node);
|
|
32
|
+
const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables, context);
|
|
33
|
+
if (testCallExpressions.length > 0) {
|
|
34
|
+
inTestCase = true;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
CallExpression(node) {
|
|
38
|
+
const {
|
|
39
|
+
type: jestFnCallType
|
|
40
|
+
} = (0, _utils2.parseJestFnCall)(node, context) ?? {};
|
|
41
|
+
if (jestFnCallType === 'test') {
|
|
42
|
+
inTestCase = true;
|
|
43
|
+
}
|
|
44
|
+
if (isCatchCall(node)) {
|
|
45
|
+
inPromiseCatch = true;
|
|
46
|
+
}
|
|
47
|
+
if (inTestCase && jestFnCallType === 'expect' && conditionalDepth > 0) {
|
|
48
|
+
context.report({
|
|
49
|
+
messageId: 'conditionalExpect',
|
|
50
|
+
node
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (inPromiseCatch && jestFnCallType === 'expect') {
|
|
54
|
+
context.report({
|
|
55
|
+
messageId: 'conditionalExpect',
|
|
56
|
+
node
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
'CallExpression:exit'(node) {
|
|
61
|
+
if ((0, _utils2.isTypeOfJestFnCall)(node, context, ['test'])) {
|
|
62
|
+
inTestCase = false;
|
|
63
|
+
}
|
|
64
|
+
if (isCatchCall(node)) {
|
|
65
|
+
inPromiseCatch = false;
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
CatchClause: increaseConditionalDepth,
|
|
69
|
+
'CatchClause:exit': decreaseConditionalDepth,
|
|
70
|
+
IfStatement: increaseConditionalDepth,
|
|
71
|
+
'IfStatement:exit': decreaseConditionalDepth,
|
|
72
|
+
SwitchStatement: increaseConditionalDepth,
|
|
73
|
+
'SwitchStatement:exit': decreaseConditionalDepth,
|
|
74
|
+
ConditionalExpression: increaseConditionalDepth,
|
|
75
|
+
'ConditionalExpression:exit': decreaseConditionalDepth,
|
|
76
|
+
LogicalExpression: increaseConditionalDepth,
|
|
77
|
+
'LogicalExpression:exit': decreaseConditionalDepth
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _utils = require("./utils");
|
|
8
|
+
var _default = exports.default = (0, _utils.createRule)({
|
|
9
|
+
name: __filename,
|
|
10
|
+
meta: {
|
|
11
|
+
docs: {
|
|
12
|
+
description: 'Disallow conditional logic in tests'
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
conditionalInTest: 'Avoid having conditionals in tests'
|
|
16
|
+
},
|
|
17
|
+
type: 'problem',
|
|
18
|
+
schema: [{
|
|
19
|
+
type: 'object',
|
|
20
|
+
properties: {
|
|
21
|
+
allowOptionalChaining: {
|
|
22
|
+
type: 'boolean'
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
additionalProperties: false
|
|
26
|
+
}]
|
|
27
|
+
},
|
|
28
|
+
defaultOptions: [{
|
|
29
|
+
allowOptionalChaining: true
|
|
30
|
+
}],
|
|
31
|
+
create(context, [{
|
|
32
|
+
allowOptionalChaining
|
|
33
|
+
}]) {
|
|
34
|
+
let inTestCase = false;
|
|
35
|
+
const maybeReportConditional = node => {
|
|
36
|
+
if (inTestCase) {
|
|
37
|
+
context.report({
|
|
38
|
+
messageId: 'conditionalInTest',
|
|
39
|
+
node
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
CallExpression(node) {
|
|
45
|
+
if ((0, _utils.isTypeOfJestFnCall)(node, context, ['test'])) {
|
|
46
|
+
inTestCase = true;
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
'CallExpression:exit'(node) {
|
|
50
|
+
if ((0, _utils.isTypeOfJestFnCall)(node, context, ['test'])) {
|
|
51
|
+
inTestCase = false;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
IfStatement: maybeReportConditional,
|
|
55
|
+
SwitchStatement: maybeReportConditional,
|
|
56
|
+
ConditionalExpression: maybeReportConditional,
|
|
57
|
+
LogicalExpression: maybeReportConditional,
|
|
58
|
+
...(!allowOptionalChaining && {
|
|
59
|
+
ChainExpression: maybeReportConditional
|
|
60
|
+
})
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _utils = require("./utils");
|
|
8
|
+
function isJestSetTimeout(jestFnCall) {
|
|
9
|
+
return jestFnCall.type === 'jest' && jestFnCall.members.length === 1 && (0, _utils.isIdentifier)(jestFnCall.members[0], 'setTimeout');
|
|
10
|
+
}
|
|
11
|
+
var _default = exports.default = (0, _utils.createRule)({
|
|
12
|
+
name: __filename,
|
|
13
|
+
meta: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: 'Disallow confusing usages of jest.setTimeout'
|
|
16
|
+
},
|
|
17
|
+
messages: {
|
|
18
|
+
globalSetTimeout: '`jest.setTimeout` should be call in `global` scope',
|
|
19
|
+
multipleSetTimeouts: 'Do not call `jest.setTimeout` multiple times, as only the last call will have an effect',
|
|
20
|
+
orderSetTimeout: '`jest.setTimeout` should be placed before any other jest methods'
|
|
21
|
+
},
|
|
22
|
+
type: 'problem',
|
|
23
|
+
schema: []
|
|
24
|
+
},
|
|
25
|
+
defaultOptions: [],
|
|
26
|
+
create(context) {
|
|
27
|
+
let seenJestTimeout = false;
|
|
28
|
+
let shouldEmitOrderSetTimeout = false;
|
|
29
|
+
return {
|
|
30
|
+
CallExpression(node) {
|
|
31
|
+
const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
|
|
32
|
+
if (!jestFnCall) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!isJestSetTimeout(jestFnCall)) {
|
|
36
|
+
shouldEmitOrderSetTimeout = true;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!['global', 'module'].includes(context.sourceCode.getScope(node).type)) {
|
|
40
|
+
context.report({
|
|
41
|
+
messageId: 'globalSetTimeout',
|
|
42
|
+
node
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (shouldEmitOrderSetTimeout) {
|
|
46
|
+
context.report({
|
|
47
|
+
messageId: 'orderSetTimeout',
|
|
48
|
+
node
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (seenJestTimeout) {
|
|
52
|
+
context.report({
|
|
53
|
+
messageId: 'multipleSetTimeouts',
|
|
54
|
+
node
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
seenJestTimeout = true;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
});
|