eslint-plugin-jest 29.4.1 → 29.6.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/README.md
CHANGED
|
@@ -351,6 +351,7 @@ Manually fixable by
|
|
|
351
351
|
| [no-standalone-expect](docs/rules/no-standalone-expect.md) | Disallow using `expect` outside of `it` or `test` blocks | ✅ | | | |
|
|
352
352
|
| [no-test-prefixes](docs/rules/no-test-prefixes.md) | Require using `.only` and `.skip` over `f` and `x` | ✅ | | 🔧 | |
|
|
353
353
|
| [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests | | | | |
|
|
354
|
+
| [no-unneeded-async-expect-function](docs/rules/no-unneeded-async-expect-function.md) | Disallow unnecessary async function wrapper for expected promises | | | 🔧 | |
|
|
354
355
|
| [no-untyped-mock-factory](docs/rules/no-untyped-mock-factory.md) | Disallow using `jest.mock()` factories without an explicit type parameter | | | 🔧 | |
|
|
355
356
|
| [padding-around-after-all-blocks](docs/rules/padding-around-after-all-blocks.md) | Enforce padding around `afterAll` blocks | | | 🔧 | |
|
|
356
357
|
| [padding-around-after-each-blocks](docs/rules/padding-around-after-each-blocks.md) | Enforce padding around `afterEach` blocks | | | 🔧 | |
|
|
@@ -393,9 +394,10 @@ Manually fixable by
|
|
|
393
394
|
|
|
394
395
|
### Requires Type Checking
|
|
395
396
|
|
|
396
|
-
| Name
|
|
397
|
-
|
|
|
398
|
-
| [
|
|
397
|
+
| Name | Description | 💼 | ⚠️ | 🔧 | 💡 |
|
|
398
|
+
| :----------------------------------------------------------------- | :----------------------------------------------------------- | :-- | :-- | :-- | :-- |
|
|
399
|
+
| [no-unnecessary-assertion](docs/rules/no-unnecessary-assertion.md) | Disallow unnecessary assertions based on types | | | | |
|
|
400
|
+
| [unbound-method](docs/rules/unbound-method.md) | Enforce unbound methods are called with their expected scope | | | | |
|
|
399
401
|
|
|
400
402
|
<!-- end auto-generated rules list -->
|
|
401
403
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Disallow unnecessary assertions based on types (`no-unnecessary-assertion`)
|
|
2
|
+
|
|
3
|
+
💭 This rule requires
|
|
4
|
+
[type information](https://typescript-eslint.io/linting/typed-linting).
|
|
5
|
+
|
|
6
|
+
<!-- end auto-generated rule header -->
|
|
7
|
+
|
|
8
|
+
When using TypeScript, runtime assertions based on types can often be omitted
|
|
9
|
+
provided that the types are accurate.
|
|
10
|
+
|
|
11
|
+
## Rule details
|
|
12
|
+
|
|
13
|
+
This rule warns when you do an assertion about being `null` or `undefined` on
|
|
14
|
+
something that cannot be those types, as that indicates either the assertion can
|
|
15
|
+
be removed or the types need to be adjusted.
|
|
16
|
+
|
|
17
|
+
The following patterns are considered warnings:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
expect('hello world'.match('sunshine') ?? []).toBeNull();
|
|
21
|
+
|
|
22
|
+
expect(User.findOrThrow(1)).toBeDefined();
|
|
23
|
+
|
|
24
|
+
expect(map.getOrInsert('key', 'default')).not.toBeUndefined();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The following patterns are not considered warnings:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
expect('hello world'.match('sunshine')).toBeNull();
|
|
31
|
+
|
|
32
|
+
expect(User.findOrNull(1)).toBeDefined();
|
|
33
|
+
|
|
34
|
+
expect(map.get('key')).not.toBeUndefined();
|
|
35
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Disallow unnecessary async function wrapper for expected promises (`no-unneeded-async-expect-function`)
|
|
2
|
+
|
|
3
|
+
🔧 This rule is automatically fixable by the
|
|
4
|
+
[`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
|
|
5
|
+
|
|
6
|
+
<!-- end auto-generated rule header -->
|
|
7
|
+
|
|
8
|
+
`Jest` can handle fulfilled/rejected promisified function call normally but
|
|
9
|
+
occassionally, engineers wrap said function in another `async` function that is
|
|
10
|
+
excessively verbose and make the tests harder to read.
|
|
11
|
+
|
|
12
|
+
## Rule details
|
|
13
|
+
|
|
14
|
+
This rule triggers a warning if `expect` is passed with an an `async` function
|
|
15
|
+
that has a single `await` call.
|
|
16
|
+
|
|
17
|
+
Examples of **incorrect** code for this rule
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
it('wrong1', async () => {
|
|
21
|
+
await expect(async () => {
|
|
22
|
+
await doSomethingAsync();
|
|
23
|
+
}).rejects.toThrow();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('wrong2', async () => {
|
|
27
|
+
await expect(async function () {
|
|
28
|
+
await doSomethingAsync();
|
|
29
|
+
}).rejects.toThrow();
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Examples of **correct** code for this rule
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
it('right1', async () => {
|
|
37
|
+
await expect(doSomethingAsync()).rejects.toThrow();
|
|
38
|
+
});
|
|
39
|
+
```
|
|
@@ -0,0 +1,78 @@
|
|
|
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'].includes(matcherName)) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const [argument] = jestFnCall.head.node.parent.arguments;
|
|
65
|
+
const isNullable = canBe(services.getTypeAtLocation(argument), matcherName === 'toBeNull' ? TypeFlags.Null : TypeFlags.Undefined);
|
|
66
|
+
if (!isNullable) {
|
|
67
|
+
context.report({
|
|
68
|
+
messageId: 'unnecessaryAssertion',
|
|
69
|
+
data: {
|
|
70
|
+
thing: matcherName === 'toBeNull' ? 'null' : 'undefined'
|
|
71
|
+
},
|
|
72
|
+
node
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
@@ -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
|
+
});
|