@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,87 @@
|
|
|
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 canBe = (firstArgumentType, flag) => {
|
|
10
|
+
if (firstArgumentType.isUnion()) {
|
|
11
|
+
return firstArgumentType.types.some(typ => typ.flags & flag);
|
|
12
|
+
}
|
|
13
|
+
return firstArgumentType.flags & flag;
|
|
14
|
+
};
|
|
15
|
+
var _default = exports.default = (0, _utils2.createRule)({
|
|
16
|
+
name: __filename,
|
|
17
|
+
meta: {
|
|
18
|
+
docs: {
|
|
19
|
+
description: 'Disallow unnecessary assertions based on types',
|
|
20
|
+
requiresTypeChecking: true
|
|
21
|
+
},
|
|
22
|
+
messages: {
|
|
23
|
+
unnecessaryAssertion: 'Unnecessary assertion, subject cannot be {{ thing }}',
|
|
24
|
+
noStrictNullCheck: 'This rule requires the `strictNullChecks` compiler option to be turned on to function correctly.'
|
|
25
|
+
},
|
|
26
|
+
type: 'suggestion',
|
|
27
|
+
schema: []
|
|
28
|
+
},
|
|
29
|
+
defaultOptions: [],
|
|
30
|
+
create(context) {
|
|
31
|
+
const services = _utils.ESLintUtils.getParserServices(context);
|
|
32
|
+
const compilerOptions = services.program.getCompilerOptions();
|
|
33
|
+
const isStrictNullChecks = compilerOptions.strictNullChecks || compilerOptions.strict && compilerOptions.strictNullChecks !== false;
|
|
34
|
+
if (!isStrictNullChecks) {
|
|
35
|
+
context.report({
|
|
36
|
+
loc: {
|
|
37
|
+
start: {
|
|
38
|
+
column: 0,
|
|
39
|
+
line: 0
|
|
40
|
+
},
|
|
41
|
+
end: {
|
|
42
|
+
column: 0,
|
|
43
|
+
line: 0
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
messageId: 'noStrictNullCheck'
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
51
|
+
const {
|
|
52
|
+
TypeFlags
|
|
53
|
+
} = require('typescript');
|
|
54
|
+
return {
|
|
55
|
+
CallExpression(node) {
|
|
56
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
57
|
+
if (jestFnCall?.type !== 'expect' || jestFnCall.head.node.parent.type !== _utils.AST_NODE_TYPES.CallExpression) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const matcherName = (0, _utils2.getAccessorValue)(jestFnCall.matcher);
|
|
61
|
+
if (!['toBeNull', 'toBeDefined', 'toBeUndefined', 'toBeNaN'].includes(matcherName)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// todo: we should support resolving promise types
|
|
66
|
+
if (jestFnCall.modifiers.some(nod => (0, _utils2.getAccessorValue)(nod) !== 'not')) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const [argument] = jestFnCall.head.node.parent.arguments;
|
|
70
|
+
let desiredType = TypeFlags.Any | TypeFlags.Unknown;
|
|
71
|
+
|
|
72
|
+
// add in the appropriate type flag based on the matcher being used
|
|
73
|
+
desiredType |= matcherName === 'toBeNaN' ? TypeFlags.NumberLike : matcherName === 'toBeNull' ? TypeFlags.Null : TypeFlags.Undefined;
|
|
74
|
+
if (canBe(services.getTypeAtLocation(argument), desiredType)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
context.report({
|
|
78
|
+
messageId: 'unnecessaryAssertion',
|
|
79
|
+
data: {
|
|
80
|
+
thing: matcherName === 'toBeNaN' ? 'a number' : matcherName === 'toBeNull' ? 'null' : 'undefined'
|
|
81
|
+
},
|
|
82
|
+
node
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
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 unnecessary async function wrapper for expected promises'
|
|
14
|
+
},
|
|
15
|
+
fixable: 'code',
|
|
16
|
+
messages: {
|
|
17
|
+
noAsyncWrapperForExpectedPromise: 'Unnecessary async function wrapper'
|
|
18
|
+
},
|
|
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 !== 'expect') {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const {
|
|
31
|
+
parent
|
|
32
|
+
} = jestFnCall.head.node;
|
|
33
|
+
if (parent.type !== _utils.AST_NODE_TYPES.CallExpression) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const [awaitNode] = parent.arguments;
|
|
37
|
+
if (!awaitNode || !(0, _utils2.isFunction)(awaitNode) || !awaitNode.async || awaitNode.body.type !== _utils.AST_NODE_TYPES.BlockStatement || awaitNode.body.body.length !== 1) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const [callback] = awaitNode.body.body;
|
|
41
|
+
if (callback.type === _utils.AST_NODE_TYPES.ExpressionStatement && callback.expression.type === _utils.AST_NODE_TYPES.AwaitExpression && callback.expression.argument.type === _utils.AST_NODE_TYPES.CallExpression) {
|
|
42
|
+
const innerAsyncFuncCall = callback.expression.argument;
|
|
43
|
+
context.report({
|
|
44
|
+
node: awaitNode,
|
|
45
|
+
messageId: 'noAsyncWrapperForExpectedPromise',
|
|
46
|
+
fix(fixer) {
|
|
47
|
+
const {
|
|
48
|
+
sourceCode
|
|
49
|
+
} = context;
|
|
50
|
+
return [fixer.replaceTextRange([awaitNode.range[0], awaitNode.range[1]], sourceCode.getText(innerAsyncFuncCall))];
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
});
|
|
@@ -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("@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 using `jest.mock()` factories without an explicit type parameter'
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
addTypeParameterToModuleMock: 'Add a type parameter to the mock factory such as `typeof import({{ moduleName }})`'
|
|
17
|
+
},
|
|
18
|
+
fixable: 'code',
|
|
19
|
+
schema: [],
|
|
20
|
+
type: 'suggestion'
|
|
21
|
+
},
|
|
22
|
+
defaultOptions: [],
|
|
23
|
+
create(context) {
|
|
24
|
+
return {
|
|
25
|
+
CallExpression(node) {
|
|
26
|
+
const {
|
|
27
|
+
callee,
|
|
28
|
+
typeArguments
|
|
29
|
+
} = node;
|
|
30
|
+
if (callee.type !== _utils.AST_NODE_TYPES.MemberExpression) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const {
|
|
34
|
+
property
|
|
35
|
+
} = callee;
|
|
36
|
+
if (node.arguments.length === 2 && (0, _utils2.isTypeOfJestFnCall)(node, context, ['jest']) && (0, _utils2.isSupportedAccessor)(property) && ['mock', 'doMock'].includes((0, _utils2.getAccessorValue)(property))) {
|
|
37
|
+
const [nameNode, factoryNode] = node.arguments;
|
|
38
|
+
const hasTypeParameter = typeArguments !== undefined && typeArguments.params.length > 0;
|
|
39
|
+
const hasReturnType = (0, _utils2.isFunction)(factoryNode) && factoryNode.returnType !== undefined;
|
|
40
|
+
if (hasTypeParameter || hasReturnType) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const moduleName = (0, _utils2.findModuleName)(nameNode);
|
|
44
|
+
context.report({
|
|
45
|
+
messageId: 'addTypeParameterToModuleMock',
|
|
46
|
+
data: {
|
|
47
|
+
moduleName: moduleName?.raw ?? './module-name'
|
|
48
|
+
},
|
|
49
|
+
node,
|
|
50
|
+
fix(fixer) {
|
|
51
|
+
if (!moduleName) {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
return [fixer.insertTextAfter(callee, `<typeof import(${moduleName.raw})>`)];
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.config = void 0;
|
|
7
|
+
var _padding = require("./utils/padding");
|
|
8
|
+
const config = exports.config = [{
|
|
9
|
+
paddingType: _padding.PaddingType.Always,
|
|
10
|
+
prevStatementType: _padding.StatementType.Any,
|
|
11
|
+
nextStatementType: _padding.StatementType.AfterAllToken
|
|
12
|
+
}, {
|
|
13
|
+
paddingType: _padding.PaddingType.Always,
|
|
14
|
+
prevStatementType: _padding.StatementType.AfterAllToken,
|
|
15
|
+
nextStatementType: _padding.StatementType.Any
|
|
16
|
+
}];
|
|
17
|
+
var _default = exports.default = (0, _padding.createPaddingRule)(__filename, 'Enforce padding around `afterAll` blocks', config);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.config = void 0;
|
|
7
|
+
var _padding = require("./utils/padding");
|
|
8
|
+
const config = exports.config = [{
|
|
9
|
+
paddingType: _padding.PaddingType.Always,
|
|
10
|
+
prevStatementType: _padding.StatementType.Any,
|
|
11
|
+
nextStatementType: _padding.StatementType.AfterEachToken
|
|
12
|
+
}, {
|
|
13
|
+
paddingType: _padding.PaddingType.Always,
|
|
14
|
+
prevStatementType: _padding.StatementType.AfterEachToken,
|
|
15
|
+
nextStatementType: _padding.StatementType.Any
|
|
16
|
+
}];
|
|
17
|
+
var _default = exports.default = (0, _padding.createPaddingRule)(__filename, 'Enforce padding around `afterEach` blocks', config);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _paddingAroundAfterAllBlocks = require("./padding-around-after-all-blocks");
|
|
8
|
+
var _paddingAroundAfterEachBlocks = require("./padding-around-after-each-blocks");
|
|
9
|
+
var _paddingAroundBeforeAllBlocks = require("./padding-around-before-all-blocks");
|
|
10
|
+
var _paddingAroundBeforeEachBlocks = require("./padding-around-before-each-blocks");
|
|
11
|
+
var _paddingAroundDescribeBlocks = require("./padding-around-describe-blocks");
|
|
12
|
+
var _paddingAroundExpectGroups = require("./padding-around-expect-groups");
|
|
13
|
+
var _paddingAroundTestBlocks = require("./padding-around-test-blocks");
|
|
14
|
+
var _padding = require("./utils/padding");
|
|
15
|
+
var _default = exports.default = (0, _padding.createPaddingRule)(__filename, 'Enforce padding around Jest functions', [..._paddingAroundAfterAllBlocks.config, ..._paddingAroundAfterEachBlocks.config, ..._paddingAroundBeforeAllBlocks.config, ..._paddingAroundBeforeEachBlocks.config, ..._paddingAroundDescribeBlocks.config, ..._paddingAroundExpectGroups.config, ..._paddingAroundTestBlocks.config]);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.config = void 0;
|
|
7
|
+
var _padding = require("./utils/padding");
|
|
8
|
+
const config = exports.config = [{
|
|
9
|
+
paddingType: _padding.PaddingType.Always,
|
|
10
|
+
prevStatementType: _padding.StatementType.Any,
|
|
11
|
+
nextStatementType: _padding.StatementType.BeforeAllToken
|
|
12
|
+
}, {
|
|
13
|
+
paddingType: _padding.PaddingType.Always,
|
|
14
|
+
prevStatementType: _padding.StatementType.BeforeAllToken,
|
|
15
|
+
nextStatementType: _padding.StatementType.Any
|
|
16
|
+
}];
|
|
17
|
+
var _default = exports.default = (0, _padding.createPaddingRule)(__filename, 'Enforce padding around `beforeAll` blocks', config);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.config = void 0;
|
|
7
|
+
var _padding = require("./utils/padding");
|
|
8
|
+
const config = exports.config = [{
|
|
9
|
+
paddingType: _padding.PaddingType.Always,
|
|
10
|
+
prevStatementType: _padding.StatementType.Any,
|
|
11
|
+
nextStatementType: _padding.StatementType.BeforeEachToken
|
|
12
|
+
}, {
|
|
13
|
+
paddingType: _padding.PaddingType.Always,
|
|
14
|
+
prevStatementType: _padding.StatementType.BeforeEachToken,
|
|
15
|
+
nextStatementType: _padding.StatementType.Any
|
|
16
|
+
}];
|
|
17
|
+
var _default = exports.default = (0, _padding.createPaddingRule)(__filename, 'Enforce padding around `beforeEach` blocks', config);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.config = void 0;
|
|
7
|
+
var _padding = require("./utils/padding");
|
|
8
|
+
const config = exports.config = [{
|
|
9
|
+
paddingType: _padding.PaddingType.Always,
|
|
10
|
+
prevStatementType: _padding.StatementType.Any,
|
|
11
|
+
nextStatementType: [_padding.StatementType.DescribeToken, _padding.StatementType.FdescribeToken, _padding.StatementType.XdescribeToken]
|
|
12
|
+
}, {
|
|
13
|
+
paddingType: _padding.PaddingType.Always,
|
|
14
|
+
prevStatementType: [_padding.StatementType.DescribeToken, _padding.StatementType.FdescribeToken, _padding.StatementType.XdescribeToken],
|
|
15
|
+
nextStatementType: _padding.StatementType.Any
|
|
16
|
+
}];
|
|
17
|
+
var _default = exports.default = (0, _padding.createPaddingRule)(__filename, 'Enforce padding around `describe` blocks', config);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.config = void 0;
|
|
7
|
+
var _padding = require("./utils/padding");
|
|
8
|
+
const config = exports.config = [{
|
|
9
|
+
paddingType: _padding.PaddingType.Always,
|
|
10
|
+
prevStatementType: _padding.StatementType.Any,
|
|
11
|
+
nextStatementType: _padding.StatementType.ExpectToken
|
|
12
|
+
}, {
|
|
13
|
+
paddingType: _padding.PaddingType.Always,
|
|
14
|
+
prevStatementType: _padding.StatementType.ExpectToken,
|
|
15
|
+
nextStatementType: _padding.StatementType.Any
|
|
16
|
+
}, {
|
|
17
|
+
paddingType: _padding.PaddingType.Any,
|
|
18
|
+
prevStatementType: _padding.StatementType.ExpectToken,
|
|
19
|
+
nextStatementType: _padding.StatementType.ExpectToken
|
|
20
|
+
}];
|
|
21
|
+
var _default = exports.default = (0, _padding.createPaddingRule)(__filename, 'Enforce padding around `expect` groups', config);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.config = void 0;
|
|
7
|
+
var _padding = require("./utils/padding");
|
|
8
|
+
const config = exports.config = [{
|
|
9
|
+
paddingType: _padding.PaddingType.Always,
|
|
10
|
+
prevStatementType: _padding.StatementType.Any,
|
|
11
|
+
nextStatementType: [_padding.StatementType.TestToken, _padding.StatementType.ItToken, _padding.StatementType.FitToken, _padding.StatementType.XitToken, _padding.StatementType.XtestToken]
|
|
12
|
+
}, {
|
|
13
|
+
paddingType: _padding.PaddingType.Always,
|
|
14
|
+
prevStatementType: [_padding.StatementType.TestToken, _padding.StatementType.ItToken, _padding.StatementType.FitToken, _padding.StatementType.XitToken, _padding.StatementType.XtestToken],
|
|
15
|
+
nextStatementType: _padding.StatementType.Any
|
|
16
|
+
}];
|
|
17
|
+
var _default = exports.default = (0, _padding.createPaddingRule)(__filename, 'Enforce padding around `test` and `it` blocks', config);
|
|
@@ -0,0 +1,47 @@
|
|
|
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: 'Suggest using `toHaveBeenCalledWith()`'
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
preferCalledWith: 'Prefer {{ matcherName }}With(/* expected args */)'
|
|
16
|
+
},
|
|
17
|
+
type: 'suggestion',
|
|
18
|
+
schema: []
|
|
19
|
+
},
|
|
20
|
+
defaultOptions: [],
|
|
21
|
+
create(context) {
|
|
22
|
+
return {
|
|
23
|
+
CallExpression(node) {
|
|
24
|
+
const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
|
|
25
|
+
if (jestFnCall?.type !== 'expect') {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (jestFnCall.modifiers.some(nod => (0, _utils.getAccessorValue)(nod) === 'not')) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const {
|
|
32
|
+
matcher
|
|
33
|
+
} = jestFnCall;
|
|
34
|
+
const matcherName = (0, _utils.getAccessorValue)(matcher);
|
|
35
|
+
if (['toBeCalled', 'toHaveBeenCalled'].includes(matcherName)) {
|
|
36
|
+
context.report({
|
|
37
|
+
data: {
|
|
38
|
+
matcherName
|
|
39
|
+
},
|
|
40
|
+
messageId: 'preferCalledWith',
|
|
41
|
+
node: matcher
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
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 isString = node => {
|
|
10
|
+
return (0, _utils2.isStringNode)(node) || node.type === _utils.AST_NODE_TYPES.TemplateLiteral;
|
|
11
|
+
};
|
|
12
|
+
const isComparingToString = expression => {
|
|
13
|
+
return isString(expression.left) || isString(expression.right);
|
|
14
|
+
};
|
|
15
|
+
const invertOperator = operator => {
|
|
16
|
+
switch (operator) {
|
|
17
|
+
case '>':
|
|
18
|
+
return '<=';
|
|
19
|
+
case '<':
|
|
20
|
+
return '>=';
|
|
21
|
+
case '>=':
|
|
22
|
+
return '<';
|
|
23
|
+
case '<=':
|
|
24
|
+
return '>';
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
};
|
|
28
|
+
const determineMatcher = (operator, negated) => {
|
|
29
|
+
const op = negated ? invertOperator(operator) : operator;
|
|
30
|
+
switch (op) {
|
|
31
|
+
case '>':
|
|
32
|
+
return 'toBeGreaterThan';
|
|
33
|
+
case '<':
|
|
34
|
+
return 'toBeLessThan';
|
|
35
|
+
case '>=':
|
|
36
|
+
return 'toBeGreaterThanOrEqual';
|
|
37
|
+
case '<=':
|
|
38
|
+
return 'toBeLessThanOrEqual';
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
};
|
|
42
|
+
var _default = exports.default = (0, _utils2.createRule)({
|
|
43
|
+
name: __filename,
|
|
44
|
+
meta: {
|
|
45
|
+
docs: {
|
|
46
|
+
description: 'Suggest using the built-in comparison matchers'
|
|
47
|
+
},
|
|
48
|
+
messages: {
|
|
49
|
+
useToBeComparison: 'Prefer using `{{ preferredMatcher }}` instead'
|
|
50
|
+
},
|
|
51
|
+
fixable: 'code',
|
|
52
|
+
type: 'suggestion',
|
|
53
|
+
schema: []
|
|
54
|
+
},
|
|
55
|
+
defaultOptions: [],
|
|
56
|
+
create(context) {
|
|
57
|
+
return {
|
|
58
|
+
CallExpression(node) {
|
|
59
|
+
const jestFnCall = (0, _utils2.parseJestFnCall)(node, context);
|
|
60
|
+
if (jestFnCall?.type !== 'expect' || jestFnCall.args.length === 0) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const {
|
|
64
|
+
parent: expect
|
|
65
|
+
} = jestFnCall.head.node;
|
|
66
|
+
if (expect.type !== _utils.AST_NODE_TYPES.CallExpression) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const {
|
|
70
|
+
arguments: [comparison],
|
|
71
|
+
range: [, expectCallEnd]
|
|
72
|
+
} = expect;
|
|
73
|
+
const {
|
|
74
|
+
matcher
|
|
75
|
+
} = jestFnCall;
|
|
76
|
+
const matcherArg = (0, _utils2.getFirstMatcherArg)(jestFnCall);
|
|
77
|
+
if (comparison.type !== _utils.AST_NODE_TYPES.BinaryExpression || isComparingToString(comparison) || !_utils2.EqualityMatcher.hasOwnProperty((0, _utils2.getAccessorValue)(matcher)) || !(0, _utils2.isBooleanLiteral)(matcherArg)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const [modifier] = jestFnCall.modifiers;
|
|
81
|
+
const hasNot = jestFnCall.modifiers.some(nod => (0, _utils2.getAccessorValue)(nod) === 'not');
|
|
82
|
+
const preferredMatcher = determineMatcher(comparison.operator, matcherArg.value === hasNot);
|
|
83
|
+
if (!preferredMatcher) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
context.report({
|
|
87
|
+
fix(fixer) {
|
|
88
|
+
const {
|
|
89
|
+
sourceCode
|
|
90
|
+
} = context;
|
|
91
|
+
|
|
92
|
+
// preserve the existing modifier if it's not a negation
|
|
93
|
+
const modifierText = modifier && (0, _utils2.getAccessorValue)(modifier) !== 'not' ? `.${(0, _utils2.getAccessorValue)(modifier)}` : '';
|
|
94
|
+
return [
|
|
95
|
+
// replace the comparison argument with the left-hand side of the comparison
|
|
96
|
+
fixer.replaceText(comparison, sourceCode.getText(comparison.left)),
|
|
97
|
+
// replace the current matcher & modifier with the preferred matcher
|
|
98
|
+
fixer.replaceTextRange([expectCallEnd, matcher.parent.range[1]], `${modifierText}.${preferredMatcher}`),
|
|
99
|
+
// replace the matcher argument with the right-hand side of the comparison
|
|
100
|
+
fixer.replaceText(matcherArg, sourceCode.getText(comparison.right))];
|
|
101
|
+
},
|
|
102
|
+
messageId: 'useToBeComparison',
|
|
103
|
+
data: {
|
|
104
|
+
preferredMatcher
|
|
105
|
+
},
|
|
106
|
+
node: matcher
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
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: 'Prefer using `.each` rather than manual loops'
|
|
13
|
+
},
|
|
14
|
+
messages: {
|
|
15
|
+
preferEach: 'prefer using `{{ fn }}.each` rather than a manual loop'
|
|
16
|
+
},
|
|
17
|
+
type: 'suggestion',
|
|
18
|
+
schema: []
|
|
19
|
+
},
|
|
20
|
+
defaultOptions: [],
|
|
21
|
+
create(context) {
|
|
22
|
+
const jestFnCalls = [];
|
|
23
|
+
let inTestCaseCall = false;
|
|
24
|
+
const recommendFn = () => {
|
|
25
|
+
if (jestFnCalls.length === 1 && jestFnCalls[0] === 'test') {
|
|
26
|
+
return 'it';
|
|
27
|
+
}
|
|
28
|
+
return 'describe';
|
|
29
|
+
};
|
|
30
|
+
const enterForLoop = () => {
|
|
31
|
+
if (jestFnCalls.length === 0 || inTestCaseCall) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
jestFnCalls.length = 0;
|
|
35
|
+
};
|
|
36
|
+
const exitForLoop = node => {
|
|
37
|
+
if (jestFnCalls.length === 0 || inTestCaseCall) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
context.report({
|
|
41
|
+
node,
|
|
42
|
+
messageId: 'preferEach',
|
|
43
|
+
data: {
|
|
44
|
+
fn: recommendFn()
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
jestFnCalls.length = 0;
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
ForStatement: enterForLoop,
|
|
51
|
+
'ForStatement:exit': exitForLoop,
|
|
52
|
+
ForInStatement: enterForLoop,
|
|
53
|
+
'ForInStatement:exit': exitForLoop,
|
|
54
|
+
ForOfStatement: enterForLoop,
|
|
55
|
+
'ForOfStatement:exit': exitForLoop,
|
|
56
|
+
CallExpression(node) {
|
|
57
|
+
const {
|
|
58
|
+
type: jestFnCallType
|
|
59
|
+
} = (0, _utils.parseJestFnCall)(node, context) ?? {};
|
|
60
|
+
if (jestFnCallType === 'hook' || jestFnCallType === 'describe' || jestFnCallType === 'test') {
|
|
61
|
+
jestFnCalls.push(jestFnCallType);
|
|
62
|
+
}
|
|
63
|
+
if (jestFnCallType === 'test') {
|
|
64
|
+
inTestCaseCall = true;
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
'CallExpression:exit'(node) {
|
|
68
|
+
const {
|
|
69
|
+
type: jestFnCallType
|
|
70
|
+
} = (0, _utils.parseJestFnCall)(node, context) ?? {};
|
|
71
|
+
if (jestFnCallType === 'test') {
|
|
72
|
+
inTestCaseCall = false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
});
|