eslint-plugin-jest 27.1.6 β 27.4.2
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 +56 -54
- package/docs/rules/no-alias-methods.md +1 -1
- package/docs/rules/no-confusing-set-timeout.md +62 -0
- package/docs/rules/no-hooks.md +1 -1
- package/docs/rules/no-if.md +1 -1
- package/docs/rules/no-large-snapshots.md +4 -0
- package/docs/rules/no-untyped-mock-factory.md +72 -0
- package/docs/rules/require-hook.md +2 -6
- package/docs/rules/valid-expect.md +2 -2
- package/docs/rules/valid-title.md +9 -1
- package/lib/index.js +5 -12
- package/lib/rules/expect-expect.js +3 -1
- package/lib/rules/max-expects.js +1 -1
- package/lib/rules/max-nested-describe.js +23 -35
- package/lib/rules/no-confusing-set-timeout.js +65 -0
- package/lib/rules/no-deprecated-functions.js +2 -2
- package/lib/rules/no-export.js +1 -1
- package/lib/rules/no-focused-tests.js +3 -3
- package/lib/rules/no-identical-title.js +2 -2
- package/lib/rules/no-if.js +1 -1
- package/lib/rules/no-mocks-import.js +1 -1
- package/lib/rules/no-standalone-expect.js +1 -1
- package/lib/rules/no-test-return-statement.js +10 -4
- package/lib/rules/no-untyped-mock-factory.js +70 -0
- package/lib/rules/prefer-expect-resolves.js +1 -1
- package/lib/rules/prefer-spy-on.js +19 -7
- package/lib/rules/unbound-method.js +1 -1
- package/lib/rules/utils/accessors.js +4 -0
- package/lib/rules/utils/misc.js +36 -20
- package/lib/rules/valid-expect-in-promise.js +3 -3
- package/lib/rules/valid-expect.js +7 -7
- package/lib/rules/valid-title.js +8 -2
- package/package.json +25 -24
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<a href="https://eslint.org/">
|
|
3
3
|
<img height="150" src="https://eslint.org/assets/images/logo/eslint-logo-color.svg">
|
|
4
4
|
</a>
|
|
5
|
-
<a href="https://
|
|
5
|
+
<a href="https://jestjs.io/">
|
|
6
6
|
<img width="150" height="150" vspace="" hspace="25" src="https://jestjs.io/img/jest.png">
|
|
7
7
|
</a>
|
|
8
8
|
<h1>eslint-plugin-jest</h1>
|
|
@@ -210,58 +210,60 @@ set to warn in.\
|
|
|
210
210
|
π‘ Manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).\
|
|
211
211
|
β Deprecated.
|
|
212
212
|
|
|
213
|
-
| NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β | Description
|
|
214
|
-
| :--------------------------------------------------------------------------- |
|
|
215
|
-
| [consistent-test-it](docs/rules/consistent-test-it.md) | Enforce `test` and `it` usage conventions
|
|
216
|
-
| [expect-expect](docs/rules/expect-expect.md) | Enforce assertion to be made in a test body
|
|
217
|
-
| [max-expects](docs/rules/max-expects.md) | Enforces a maximum number assertion calls in a test body
|
|
218
|
-
| [max-nested-describe](docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls
|
|
219
|
-
| [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods
|
|
220
|
-
| [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests
|
|
221
|
-
| [no-conditional-expect](docs/rules/no-conditional-expect.md) | Disallow calling `expect` conditionally
|
|
222
|
-
| [no-conditional-in-test](docs/rules/no-conditional-in-test.md) | Disallow conditional logic in tests
|
|
223
|
-
| [no-
|
|
224
|
-
| [no-
|
|
225
|
-
| [no-
|
|
226
|
-
| [no-
|
|
227
|
-
| [no-
|
|
228
|
-
| [no-
|
|
229
|
-
| [no-
|
|
230
|
-
| [no-
|
|
231
|
-
| [no-
|
|
232
|
-
| [no-
|
|
233
|
-
| [no-
|
|
234
|
-
| [no-
|
|
235
|
-
| [no-
|
|
236
|
-
| [no-
|
|
237
|
-
| [no-restricted-
|
|
238
|
-
| [no-
|
|
239
|
-
| [no-
|
|
240
|
-
| [no-test-
|
|
241
|
-
| [
|
|
242
|
-
| [
|
|
243
|
-
| [prefer-
|
|
244
|
-
| [prefer-
|
|
245
|
-
| [prefer-
|
|
246
|
-
| [prefer-
|
|
247
|
-
| [prefer-
|
|
248
|
-
| [prefer-
|
|
249
|
-
| [prefer-
|
|
250
|
-
| [prefer-
|
|
251
|
-
| [prefer-
|
|
252
|
-
| [prefer-
|
|
253
|
-
| [prefer-
|
|
254
|
-
| [prefer-
|
|
255
|
-
| [prefer-
|
|
256
|
-
| [prefer-to-
|
|
257
|
-
| [prefer-
|
|
258
|
-
| [
|
|
259
|
-
| [
|
|
260
|
-
| [require-
|
|
261
|
-
| [
|
|
262
|
-
| [
|
|
263
|
-
| [valid-
|
|
264
|
-
| [valid-
|
|
213
|
+
| NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β | Description | πΌ | β οΈ | π§ | π‘ | β |
|
|
214
|
+
| :--------------------------------------------------------------------------- | :------------------------------------------------------------------------ | :-- | :-- | :-- | :-- | :-- |
|
|
215
|
+
| [consistent-test-it](docs/rules/consistent-test-it.md) | Enforce `test` and `it` usage conventions | | | π§ | | |
|
|
216
|
+
| [expect-expect](docs/rules/expect-expect.md) | Enforce assertion to be made in a test body | | β
| | | |
|
|
217
|
+
| [max-expects](docs/rules/max-expects.md) | Enforces a maximum number assertion calls in a test body | | | | | |
|
|
218
|
+
| [max-nested-describe](docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls | | | | | |
|
|
219
|
+
| [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods | β
| π¨ | π§ | | |
|
|
220
|
+
| [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests | | β
| | | |
|
|
221
|
+
| [no-conditional-expect](docs/rules/no-conditional-expect.md) | Disallow calling `expect` conditionally | β
| | | | |
|
|
222
|
+
| [no-conditional-in-test](docs/rules/no-conditional-in-test.md) | Disallow conditional logic in tests | | | | | |
|
|
223
|
+
| [no-confusing-set-timeout](docs/rules/no-confusing-set-timeout.md) | Disallow confusing usages of jest.setTimeout | | | | | |
|
|
224
|
+
| [no-deprecated-functions](docs/rules/no-deprecated-functions.md) | Disallow use of deprecated functions | β
| | π§ | | |
|
|
225
|
+
| [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | | β
| | | |
|
|
226
|
+
| [no-done-callback](docs/rules/no-done-callback.md) | Disallow using a callback in asynchronous tests and hooks | β
| | | π‘ | |
|
|
227
|
+
| [no-duplicate-hooks](docs/rules/no-duplicate-hooks.md) | Disallow duplicate setup and teardown hooks | | | | | |
|
|
228
|
+
| [no-export](docs/rules/no-export.md) | Disallow using `exports` in files containing tests | β
| | | | |
|
|
229
|
+
| [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | β
| | | π‘ | |
|
|
230
|
+
| [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | | | | |
|
|
231
|
+
| [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | β
| | | | |
|
|
232
|
+
| [no-if](docs/rules/no-if.md) | Disallow conditional logic | | | | | β |
|
|
233
|
+
| [no-interpolation-in-snapshots](docs/rules/no-interpolation-in-snapshots.md) | Disallow string interpolation inside snapshots | β
| | | | |
|
|
234
|
+
| [no-jasmine-globals](docs/rules/no-jasmine-globals.md) | Disallow Jasmine globals | β
| | π§ | | |
|
|
235
|
+
| [no-large-snapshots](docs/rules/no-large-snapshots.md) | Disallow large snapshots | | | | | |
|
|
236
|
+
| [no-mocks-import](docs/rules/no-mocks-import.md) | Disallow manually importing from `__mocks__` | β
| | | | |
|
|
237
|
+
| [no-restricted-jest-methods](docs/rules/no-restricted-jest-methods.md) | Disallow specific `jest.` methods | | | | | |
|
|
238
|
+
| [no-restricted-matchers](docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers | | | | | |
|
|
239
|
+
| [no-standalone-expect](docs/rules/no-standalone-expect.md) | Disallow using `expect` outside of `it` or `test` blocks | β
| | | | |
|
|
240
|
+
| [no-test-prefixes](docs/rules/no-test-prefixes.md) | Require using `.only` and `.skip` over `f` and `x` | β
| | π§ | | |
|
|
241
|
+
| [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests | | | | | |
|
|
242
|
+
| [no-untyped-mock-factory](docs/rules/no-untyped-mock-factory.md) | Disallow using `jest.mock()` factories without an explicit type parameter | | | π§ | | |
|
|
243
|
+
| [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` | | | | | |
|
|
244
|
+
| [prefer-comparison-matcher](docs/rules/prefer-comparison-matcher.md) | Suggest using the built-in comparison matchers | | | π§ | | |
|
|
245
|
+
| [prefer-each](docs/rules/prefer-each.md) | Prefer using `.each` rather than manual loops | | | | | |
|
|
246
|
+
| [prefer-equality-matcher](docs/rules/prefer-equality-matcher.md) | Suggest using the built-in equality matchers | | | | π‘ | |
|
|
247
|
+
| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | | | π‘ | |
|
|
248
|
+
| [prefer-expect-resolves](docs/rules/prefer-expect-resolves.md) | Prefer `await expect(...).resolves` over `expect(await ...)` syntax | | | π§ | | |
|
|
249
|
+
| [prefer-hooks-in-order](docs/rules/prefer-hooks-in-order.md) | Prefer having hooks in a consistent order | | | | | |
|
|
250
|
+
| [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md) | Suggest having hooks before any test cases | | | | | |
|
|
251
|
+
| [prefer-lowercase-title](docs/rules/prefer-lowercase-title.md) | Enforce lowercase test names | | | π§ | | |
|
|
252
|
+
| [prefer-mock-promise-shorthand](docs/rules/prefer-mock-promise-shorthand.md) | Prefer mock resolved/rejected shorthands for promises | | | π§ | | |
|
|
253
|
+
| [prefer-snapshot-hint](docs/rules/prefer-snapshot-hint.md) | Prefer including a hint with external snapshots | | | | | |
|
|
254
|
+
| [prefer-spy-on](docs/rules/prefer-spy-on.md) | Suggest using `jest.spyOn()` | | | π§ | | |
|
|
255
|
+
| [prefer-strict-equal](docs/rules/prefer-strict-equal.md) | Suggest using `toStrictEqual()` | | | | π‘ | |
|
|
256
|
+
| [prefer-to-be](docs/rules/prefer-to-be.md) | Suggest using `toBe()` for primitive literals | π¨ | | π§ | | |
|
|
257
|
+
| [prefer-to-contain](docs/rules/prefer-to-contain.md) | Suggest using `toContain()` | π¨ | | π§ | | |
|
|
258
|
+
| [prefer-to-have-length](docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` | π¨ | | π§ | | |
|
|
259
|
+
| [prefer-todo](docs/rules/prefer-todo.md) | Suggest using `test.todo` | | | π§ | | |
|
|
260
|
+
| [require-hook](docs/rules/require-hook.md) | Require setup and teardown code to be within a hook | | | | | |
|
|
261
|
+
| [require-to-throw-message](docs/rules/require-to-throw-message.md) | Require a message for `toThrow()` | | | | | |
|
|
262
|
+
| [require-top-level-describe](docs/rules/require-top-level-describe.md) | Require test cases and hooks to be inside a `describe` block | | | | | |
|
|
263
|
+
| [valid-describe-callback](docs/rules/valid-describe-callback.md) | Enforce valid `describe()` callback | β
| | | | |
|
|
264
|
+
| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage | β
| | | | |
|
|
265
|
+
| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Require promises that have expectations in their chain to be valid | β
| | | | |
|
|
266
|
+
| [valid-title](docs/rules/valid-title.md) | Enforce valid titles | β
| | π§ | | |
|
|
265
267
|
|
|
266
268
|
### Requires Type Checking
|
|
267
269
|
|
|
@@ -273,7 +275,7 @@ set to warn in.\
|
|
|
273
275
|
|
|
274
276
|
In order to use the rules powered by TypeScript type-checking, you must be using
|
|
275
277
|
`@typescript-eslint/parser` & adjust your eslint config as outlined
|
|
276
|
-
[here](https://
|
|
278
|
+
[here](https://typescript-eslint.io/linting/typed-linting).
|
|
277
279
|
|
|
278
280
|
Note that unlike the type-checking rules in `@typescript-eslint/eslint-plugin`,
|
|
279
281
|
the rules here will fallback to doing nothing if type information is not
|
|
@@ -11,7 +11,7 @@ This rule _warns_ in the π¨ `style`
|
|
|
11
11
|
<!-- end auto-generated rule header -->
|
|
12
12
|
|
|
13
13
|
> These aliases are going to be removed in the next major version of Jest - see
|
|
14
|
-
> <https://github.com/
|
|
14
|
+
> <https://github.com/jestjs/jest/issues/13164> for more
|
|
15
15
|
|
|
16
16
|
Several Jest methods have alias names, such as `toThrow` having the alias of
|
|
17
17
|
`toThrowError`. This rule ensures that only the canonical name as used in the
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Disallow confusing usages of jest.setTimeout (`no-confusing-set-timeout`)
|
|
2
|
+
|
|
3
|
+
<!-- end auto-generated rule header -->
|
|
4
|
+
|
|
5
|
+
While `jest.setTimeout` can be called multiple times anywhere within a single
|
|
6
|
+
test file only the last call before any test functions run will have an effect.
|
|
7
|
+
|
|
8
|
+
## Rule details
|
|
9
|
+
|
|
10
|
+
this rule checks for several confusing usages of `jest.setTimeout` that looks
|
|
11
|
+
like it applies to specific tests within the same file, such as:
|
|
12
|
+
|
|
13
|
+
- being called anywhere other than in global scope
|
|
14
|
+
- being called multiple times
|
|
15
|
+
- being called after other Jest functions like hooks, `describe`, `test`, or
|
|
16
|
+
`it`
|
|
17
|
+
|
|
18
|
+
Examples of **incorrect** code for this rule:
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
describe('test foo', () => {
|
|
22
|
+
jest.setTimeout(1000);
|
|
23
|
+
it('test-description', () => {
|
|
24
|
+
// test logic;
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('test bar', () => {
|
|
29
|
+
it('test-description', () => {
|
|
30
|
+
jest.setTimeout(1000);
|
|
31
|
+
// test logic;
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('foo-bar', () => {
|
|
36
|
+
jest.setTimeout(1000);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('unit test', () => {
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
jest.setTimeout(1000);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Examples of **correct** code for this rule:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
jest.setTimeout(500);
|
|
50
|
+
test('test test', () => {
|
|
51
|
+
// do some stuff
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
jest.setTimeout(1000);
|
|
57
|
+
describe('test bar bar', () => {
|
|
58
|
+
it('test-description', () => {
|
|
59
|
+
// test logic;
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
```
|
package/docs/rules/no-hooks.md
CHANGED
package/docs/rules/no-if.md
CHANGED
|
@@ -24,6 +24,10 @@ module.exports = {
|
|
|
24
24
|
};
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
In order to check external snapshots, you must also have `eslint` check files
|
|
28
|
+
with the `.snap` extension by either passing `--ext snap` on the command line or
|
|
29
|
+
by explicitly specifying `.snap` in `overrides`.
|
|
30
|
+
|
|
27
31
|
## Rule details
|
|
28
32
|
|
|
29
33
|
This rule looks at all Jest inline and external snapshots (files with `.snap`
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Disallow using `jest.mock()` factories without an explicit type parameter (`no-untyped-mock-factory`)
|
|
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
|
+
By default, `jest.mock` and `jest.doMock` allow any type to be returned by a
|
|
9
|
+
mock factory. A generic type parameter can be used to enforce that the factory
|
|
10
|
+
returns an object with the same shape as the original module, or some other
|
|
11
|
+
strict type. Requiring a type makes it easier to use TypeScript to catch changes
|
|
12
|
+
needed in test mocks when the source module changes.
|
|
13
|
+
|
|
14
|
+
> **Warning**
|
|
15
|
+
>
|
|
16
|
+
> This rule expects to be run on TypeScript files **only**. If you are using a
|
|
17
|
+
> codebase that has a mix of JavaScript and TypeScript tests, you can use
|
|
18
|
+
> [overrides](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#how-do-overrides-work)
|
|
19
|
+
> to apply this rule to just your TypeScript test files.
|
|
20
|
+
|
|
21
|
+
## Rule details
|
|
22
|
+
|
|
23
|
+
This rule triggers a warning if `mock()` or `doMock()` is used without a generic
|
|
24
|
+
type parameter or return type.
|
|
25
|
+
|
|
26
|
+
The following patterns are considered errors:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
jest.mock('../moduleName', () => {
|
|
30
|
+
return jest.fn(() => 42);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
jest.mock('./module', () => ({
|
|
34
|
+
...jest.requireActual('./module'),
|
|
35
|
+
foo: jest.fn(),
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
jest.mock('random-num', () => {
|
|
39
|
+
return jest.fn(() => 42);
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The following patterns are not considered errors:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// Uses typeof import()
|
|
47
|
+
jest.mock<typeof import('../moduleName')>('../moduleName', () => {
|
|
48
|
+
return jest.fn(() => 42);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
jest.mock<typeof import('./module')>('./module', () => ({
|
|
52
|
+
...jest.requireActual('./module'),
|
|
53
|
+
foo: jest.fn(),
|
|
54
|
+
}));
|
|
55
|
+
|
|
56
|
+
// Uses custom type
|
|
57
|
+
jest.mock<() => number>('random-num', () => {
|
|
58
|
+
return jest.fn(() => 42);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// No factory
|
|
62
|
+
jest.mock('random-num');
|
|
63
|
+
|
|
64
|
+
// Virtual mock
|
|
65
|
+
jest.mock(
|
|
66
|
+
'../moduleName',
|
|
67
|
+
() => {
|
|
68
|
+
return jest.fn(() => 42);
|
|
69
|
+
},
|
|
70
|
+
{ virtual: true },
|
|
71
|
+
);
|
|
72
|
+
```
|
|
@@ -2,12 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- end auto-generated rule header -->
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
tests run, and
|
|
7
|
-
run. Jest provides helper functions to handle this.
|
|
8
|
-
|
|
9
|
-
It's common when writing tests to need to perform setup work that needs to
|
|
10
|
-
happen before tests run, and finishing work after tests run.
|
|
5
|
+
It's common when writing tests to need to perform setup work that has to happen
|
|
6
|
+
before tests run, and finishing work after tests run.
|
|
11
7
|
|
|
12
8
|
Because Jest executes all `describe` handlers in a test file _before_ it
|
|
13
9
|
executes any of the actual tests, it's important to ensure setup and teardown
|
|
@@ -66,7 +66,7 @@ This rule is enabled by default.
|
|
|
66
66
|
Enforces to use `await` inside block statements. Using `return` will trigger a
|
|
67
67
|
warning. Returning one line statements with arrow functions is _always allowed_.
|
|
68
68
|
|
|
69
|
-
Examples of **incorrect** code for the { "alwaysAwait":
|
|
69
|
+
Examples of **incorrect** code for the `{ "alwaysAwait": true }` option:
|
|
70
70
|
|
|
71
71
|
```js
|
|
72
72
|
// alwaysAwait: true
|
|
@@ -76,7 +76,7 @@ test('test1', async () => {
|
|
|
76
76
|
});
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
Examples of **correct** code for the { "alwaysAwait":
|
|
79
|
+
Examples of **correct** code for the `{ "alwaysAwait": true }` option:
|
|
80
80
|
|
|
81
81
|
```js
|
|
82
82
|
// alwaysAwait: true
|
|
@@ -125,7 +125,8 @@ describe('foo', () => {
|
|
|
125
125
|
|
|
126
126
|
**accidentalSpace**
|
|
127
127
|
|
|
128
|
-
A `describe` / `test` block should not contain accidentalSpace
|
|
128
|
+
A `describe` / `test` block should not contain accidentalSpace, but can be
|
|
129
|
+
turned off via the `ignoreSpaces` option:
|
|
129
130
|
|
|
130
131
|
Examples of **incorrect** code for this rule
|
|
131
132
|
|
|
@@ -161,6 +162,7 @@ describe('foo', () => {
|
|
|
161
162
|
|
|
162
163
|
```ts
|
|
163
164
|
interface Options {
|
|
165
|
+
ignoreSpaces?: boolean;
|
|
164
166
|
ignoreTypeOfDescribeName?: boolean;
|
|
165
167
|
disallowedWords?: string[];
|
|
166
168
|
mustNotMatch?: Partial<Record<'describe' | 'test' | 'it', string>> | string;
|
|
@@ -168,6 +170,12 @@ interface Options {
|
|
|
168
170
|
}
|
|
169
171
|
```
|
|
170
172
|
|
|
173
|
+
#### `ignoreSpaces`
|
|
174
|
+
|
|
175
|
+
Default: `false`
|
|
176
|
+
|
|
177
|
+
When enabled, the leading and trailing spaces won't be checked.
|
|
178
|
+
|
|
171
179
|
#### `ignoreTypeOfDescribeName`
|
|
172
180
|
|
|
173
181
|
Default: `false`
|
package/lib/index.js
CHANGED
|
@@ -7,6 +7,8 @@ var snapshotProcessor = _interopRequireWildcard(require("./processors/snapshot-p
|
|
|
7
7
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
8
8
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
9
9
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
+
// v5 of `@typescript-eslint/experimental-utils` removed this
|
|
11
|
+
|
|
10
12
|
// copied from https://github.com/babel/babel/blob/d8da63c929f2d28c401571e2a43166678c555bc4/packages/babel-helpers/src/helpers.js#L602-L606
|
|
11
13
|
/* istanbul ignore next */
|
|
12
14
|
const interopRequireDefault = obj => obj && obj.__esModule ? obj : {
|
|
@@ -17,18 +19,9 @@ const importDefault = moduleName =>
|
|
|
17
19
|
interopRequireDefault(require(moduleName)).default;
|
|
18
20
|
const rulesDir = (0, _path.join)(__dirname, 'rules');
|
|
19
21
|
const excludedFiles = ['__tests__', 'detectJestVersion', 'utils'];
|
|
20
|
-
const rules = (0, _fs.readdirSync)(rulesDir).map(rule => (0, _path.parse)(rule).name).filter(rule => !excludedFiles.includes(rule)).
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}), {});
|
|
24
|
-
const recommendedRules = Object.entries(rules).filter(([, rule]) => rule.meta.docs.recommended).reduce((acc, [name, rule]) => ({
|
|
25
|
-
...acc,
|
|
26
|
-
[`jest/${name}`]: rule.meta.docs.recommended
|
|
27
|
-
}), {});
|
|
28
|
-
const allRules = Object.entries(rules).filter(([, rule]) => !rule.meta.deprecated).reduce((acc, [name]) => ({
|
|
29
|
-
...acc,
|
|
30
|
-
[`jest/${name}`]: 'error'
|
|
31
|
-
}), {});
|
|
22
|
+
const rules = Object.fromEntries((0, _fs.readdirSync)(rulesDir).map(rule => (0, _path.parse)(rule).name).filter(rule => !excludedFiles.includes(rule)).map(rule => [rule, importDefault((0, _path.join)(rulesDir, rule))]));
|
|
23
|
+
const recommendedRules = Object.fromEntries(Object.entries(rules).filter(([, rule]) => rule.meta.docs.recommended).map(([name, rule]) => [`jest/${name}`, rule.meta.docs.recommended]));
|
|
24
|
+
const allRules = Object.fromEntries(Object.entries(rules).filter(([, rule]) => !rule.meta.deprecated).map(([name]) => [`jest/${name}`, 'error']));
|
|
32
25
|
const createConfig = rules => ({
|
|
33
26
|
plugins: ['jest'],
|
|
34
27
|
env: {
|
|
@@ -20,7 +20,9 @@ var _utils2 = require("./utils");
|
|
|
20
20
|
*/
|
|
21
21
|
function matchesAssertFunctionName(nodeName, patterns) {
|
|
22
22
|
return patterns.some(p => new RegExp(`^${p.split('.').map(x => {
|
|
23
|
-
if (x === '**')
|
|
23
|
+
if (x === '**') {
|
|
24
|
+
return '[a-z\\d\\.]*';
|
|
25
|
+
}
|
|
24
26
|
return x.replace(/\*/gu, '[a-z\\d]*');
|
|
25
27
|
}).join('\\.')}(\\.|$)`, 'ui').test(nodeName));
|
|
26
28
|
}
|
package/lib/rules/max-expects.js
CHANGED
|
@@ -15,7 +15,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
15
15
|
recommended: false
|
|
16
16
|
},
|
|
17
17
|
messages: {
|
|
18
|
-
exceededMaxAssertion: 'Too many assertion calls ({{ count }})
|
|
18
|
+
exceededMaxAssertion: 'Too many assertion calls ({{ count }}) - maximum allowed is {{ max }}'
|
|
19
19
|
},
|
|
20
20
|
type: 'suggestion',
|
|
21
21
|
schema: [{
|
|
@@ -4,9 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
var _utils = require("
|
|
8
|
-
var
|
|
9
|
-
var _default = (0, _utils2.createRule)({
|
|
7
|
+
var _utils = require("./utils");
|
|
8
|
+
var _default = (0, _utils.createRule)({
|
|
10
9
|
name: __filename,
|
|
11
10
|
meta: {
|
|
12
11
|
docs: {
|
|
@@ -15,7 +14,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
15
14
|
recommended: false
|
|
16
15
|
},
|
|
17
16
|
messages: {
|
|
18
|
-
exceededMaxDepth: 'Too many nested describe calls ({{ depth }})
|
|
17
|
+
exceededMaxDepth: 'Too many nested describe calls ({{ depth }}) - maximum allowed is {{ max }}'
|
|
19
18
|
},
|
|
20
19
|
type: 'suggestion',
|
|
21
20
|
schema: [{
|
|
@@ -35,39 +34,28 @@ var _default = (0, _utils2.createRule)({
|
|
|
35
34
|
create(context, [{
|
|
36
35
|
max
|
|
37
36
|
}]) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
depth: describeCallbackStack.length,
|
|
53
|
-
max
|
|
37
|
+
const describes = [];
|
|
38
|
+
return {
|
|
39
|
+
CallExpression(node) {
|
|
40
|
+
if ((0, _utils.isTypeOfJestFnCall)(node, context, ['describe'])) {
|
|
41
|
+
describes.unshift(node);
|
|
42
|
+
if (describes.length > max) {
|
|
43
|
+
context.report({
|
|
44
|
+
node,
|
|
45
|
+
messageId: 'exceededMaxDepth',
|
|
46
|
+
data: {
|
|
47
|
+
depth: describes.length,
|
|
48
|
+
max
|
|
49
|
+
}
|
|
50
|
+
});
|
|
54
51
|
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
} = node;
|
|
62
|
-
if ((parent === null || parent === void 0 ? void 0 : parent.type) === _utils.AST_NODE_TYPES.CallExpression && (0, _utils2.isTypeOfJestFnCall)(parent, context, ['describe'])) {
|
|
63
|
-
describeCallbackStack.pop();
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
'CallExpression:exit'(node) {
|
|
55
|
+
if (describes[0] === node) {
|
|
56
|
+
describes.shift();
|
|
57
|
+
}
|
|
64
58
|
}
|
|
65
|
-
}
|
|
66
|
-
return {
|
|
67
|
-
FunctionExpression: pushDescribeCallback,
|
|
68
|
-
'FunctionExpression:exit': popDescribeCallback,
|
|
69
|
-
ArrowFunctionExpression: pushDescribeCallback,
|
|
70
|
-
'ArrowFunctionExpression:exit': popDescribeCallback
|
|
71
59
|
};
|
|
72
60
|
}
|
|
73
61
|
});
|
|
@@ -0,0 +1,65 @@
|
|
|
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 = (0, _utils.createRule)({
|
|
12
|
+
name: __filename,
|
|
13
|
+
meta: {
|
|
14
|
+
docs: {
|
|
15
|
+
category: 'Best Practices',
|
|
16
|
+
description: 'Disallow confusing usages of jest.setTimeout',
|
|
17
|
+
recommended: false
|
|
18
|
+
},
|
|
19
|
+
messages: {
|
|
20
|
+
globalSetTimeout: '`jest.setTimeout` should be call in `global` scope',
|
|
21
|
+
multipleSetTimeouts: 'Do not call `jest.setTimeout` multiple times, as only the last call will have an effect',
|
|
22
|
+
orderSetTimeout: '`jest.setTimeout` should be placed before any other jest methods'
|
|
23
|
+
},
|
|
24
|
+
type: 'problem',
|
|
25
|
+
schema: []
|
|
26
|
+
},
|
|
27
|
+
defaultOptions: [],
|
|
28
|
+
create(context) {
|
|
29
|
+
let seenJestTimeout = false;
|
|
30
|
+
let shouldEmitOrderSetTimeout = false;
|
|
31
|
+
return {
|
|
32
|
+
CallExpression(node) {
|
|
33
|
+
const scope = context.getScope();
|
|
34
|
+
const jestFnCall = (0, _utils.parseJestFnCall)(node, context);
|
|
35
|
+
if (!jestFnCall) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (!isJestSetTimeout(jestFnCall)) {
|
|
39
|
+
shouldEmitOrderSetTimeout = true;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (!['global', 'module'].includes(scope.type)) {
|
|
43
|
+
context.report({
|
|
44
|
+
messageId: 'globalSetTimeout',
|
|
45
|
+
node
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (shouldEmitOrderSetTimeout) {
|
|
49
|
+
context.report({
|
|
50
|
+
messageId: 'orderSetTimeout',
|
|
51
|
+
node
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (seenJestTimeout) {
|
|
55
|
+
context.report({
|
|
56
|
+
messageId: 'multipleSetTimeouts',
|
|
57
|
+
node
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
seenJestTimeout = true;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
exports.default = _default;
|
|
@@ -30,8 +30,8 @@ var _default = (0, _utils2.createRule)({
|
|
|
30
30
|
},
|
|
31
31
|
defaultOptions: [],
|
|
32
32
|
create(context) {
|
|
33
|
-
var _context$settings
|
|
34
|
-
const jestVersion = parseJestVersion(((_context$settings = context.settings) === null || _context$settings === void 0
|
|
33
|
+
var _context$settings;
|
|
34
|
+
const jestVersion = parseJestVersion(((_context$settings = context.settings) === null || _context$settings === void 0 || (_context$settings = _context$settings.jest) === null || _context$settings === void 0 ? void 0 : _context$settings.version) || (0, _utils2.detectJestVersion)());
|
|
35
35
|
const deprecations = {
|
|
36
36
|
...(jestVersion >= 15 && {
|
|
37
37
|
'jest.resetModuleRegistry': 'jest.resetModules'
|
package/lib/rules/no-export.js
CHANGED
|
@@ -15,8 +15,8 @@ var _default = (0, _utils2.createRule)({
|
|
|
15
15
|
recommended: 'error'
|
|
16
16
|
},
|
|
17
17
|
messages: {
|
|
18
|
-
focusedTest: 'Unexpected focused test
|
|
19
|
-
suggestRemoveFocus: 'Remove focus from test
|
|
18
|
+
focusedTest: 'Unexpected focused test',
|
|
19
|
+
suggestRemoveFocus: 'Remove focus from test'
|
|
20
20
|
},
|
|
21
21
|
schema: [],
|
|
22
22
|
type: 'suggestion',
|
|
@@ -33,7 +33,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
33
33
|
if (jestFnCall.name.startsWith('f')) {
|
|
34
34
|
context.report({
|
|
35
35
|
messageId: 'focusedTest',
|
|
36
|
-
node,
|
|
36
|
+
node: jestFnCall.head.node,
|
|
37
37
|
suggest: [{
|
|
38
38
|
messageId: 'suggestRemoveFocus',
|
|
39
39
|
fix(fixer) {
|
|
@@ -18,8 +18,8 @@ var _default = (0, _utils.createRule)({
|
|
|
18
18
|
recommended: 'error'
|
|
19
19
|
},
|
|
20
20
|
messages: {
|
|
21
|
-
multipleTestTitle: 'Test title is used multiple times in the same describe block
|
|
22
|
-
multipleDescribeTitle: 'Describe block title is used multiple times in the same describe block
|
|
21
|
+
multipleTestTitle: 'Test title is used multiple times in the same describe block',
|
|
22
|
+
multipleDescribeTitle: 'Describe block title is used multiple times in the same describe block'
|
|
23
23
|
},
|
|
24
24
|
schema: [],
|
|
25
25
|
type: 'suggestion'
|
package/lib/rules/no-if.js
CHANGED
|
@@ -22,7 +22,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
22
22
|
recommended: false
|
|
23
23
|
},
|
|
24
24
|
messages: {
|
|
25
|
-
conditionalInTest: 'Test should not contain {{ condition }} statements
|
|
25
|
+
conditionalInTest: 'Test should not contain {{ condition }} statements'
|
|
26
26
|
},
|
|
27
27
|
deprecated: true,
|
|
28
28
|
replacedBy: ['no-conditional-in-test'],
|
|
@@ -19,7 +19,7 @@ var _default = (0, _utils.createRule)({
|
|
|
19
19
|
recommended: 'error'
|
|
20
20
|
},
|
|
21
21
|
messages: {
|
|
22
|
-
noManualImport: `Mocks should not be manually imported from a ${mocksDirName} directory. Instead use \`jest.mock\` and import from the original module path
|
|
22
|
+
noManualImport: `Mocks should not be manually imported from a ${mocksDirName} directory. Instead use \`jest.mock\` and import from the original module path`
|
|
23
23
|
},
|
|
24
24
|
schema: []
|
|
25
25
|
},
|
|
@@ -22,7 +22,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
22
22
|
recommended: false
|
|
23
23
|
},
|
|
24
24
|
messages: {
|
|
25
|
-
noReturnValue: 'Jest tests should not return a value
|
|
25
|
+
noReturnValue: 'Jest tests should not return a value'
|
|
26
26
|
},
|
|
27
27
|
schema: [],
|
|
28
28
|
type: 'suggestion'
|
|
@@ -36,7 +36,9 @@ var _default = (0, _utils2.createRule)({
|
|
|
36
36
|
}
|
|
37
37
|
const body = getBody(node.arguments);
|
|
38
38
|
const returnStmt = body.find(t => t.type === _utils.AST_NODE_TYPES.ReturnStatement);
|
|
39
|
-
if (!returnStmt)
|
|
39
|
+
if (!returnStmt) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
40
42
|
context.report({
|
|
41
43
|
messageId: 'noReturnValue',
|
|
42
44
|
node: returnStmt
|
|
@@ -45,9 +47,13 @@ var _default = (0, _utils2.createRule)({
|
|
|
45
47
|
FunctionDeclaration(node) {
|
|
46
48
|
const declaredVariables = context.getDeclaredVariables(node);
|
|
47
49
|
const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables, context);
|
|
48
|
-
if (testCallExpressions.length === 0)
|
|
50
|
+
if (testCallExpressions.length === 0) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
49
53
|
const returnStmt = node.body.body.find(t => t.type === _utils.AST_NODE_TYPES.ReturnStatement);
|
|
50
|
-
if (!returnStmt)
|
|
54
|
+
if (!returnStmt) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
51
57
|
context.report({
|
|
52
58
|
messageId: 'noReturnValue',
|
|
53
59
|
node: returnStmt
|
|
@@ -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
|
+
const findModuleName = node => {
|
|
10
|
+
if (node.type === _utils.AST_NODE_TYPES.Literal && typeof node.value === 'string') {
|
|
11
|
+
return node;
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
};
|
|
15
|
+
var _default = (0, _utils2.createRule)({
|
|
16
|
+
name: __filename,
|
|
17
|
+
meta: {
|
|
18
|
+
docs: {
|
|
19
|
+
category: 'Best Practices',
|
|
20
|
+
description: 'Disallow using `jest.mock()` factories without an explicit type parameter',
|
|
21
|
+
recommended: false
|
|
22
|
+
},
|
|
23
|
+
messages: {
|
|
24
|
+
addTypeParameterToModuleMock: 'Add a type parameter to the mock factory such as `typeof import({{ moduleName }})`'
|
|
25
|
+
},
|
|
26
|
+
fixable: 'code',
|
|
27
|
+
schema: [],
|
|
28
|
+
type: 'suggestion'
|
|
29
|
+
},
|
|
30
|
+
defaultOptions: [],
|
|
31
|
+
create(context) {
|
|
32
|
+
return {
|
|
33
|
+
CallExpression(node) {
|
|
34
|
+
const {
|
|
35
|
+
callee,
|
|
36
|
+
typeParameters
|
|
37
|
+
} = node;
|
|
38
|
+
if (callee.type !== _utils.AST_NODE_TYPES.MemberExpression) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const {
|
|
42
|
+
property
|
|
43
|
+
} = callee;
|
|
44
|
+
if (node.arguments.length === 2 && (0, _utils2.isTypeOfJestFnCall)(node, context, ['jest']) && (0, _utils2.isSupportedAccessor)(property) && ['mock', 'doMock'].includes((0, _utils2.getAccessorValue)(property))) {
|
|
45
|
+
const [nameNode, factoryNode] = node.arguments;
|
|
46
|
+
const hasTypeParameter = typeParameters !== undefined && typeParameters.params.length > 0;
|
|
47
|
+
const hasReturnType = (0, _utils2.isFunction)(factoryNode) && factoryNode.returnType !== undefined;
|
|
48
|
+
if (hasTypeParameter || hasReturnType) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const moduleName = findModuleName(nameNode);
|
|
52
|
+
context.report({
|
|
53
|
+
messageId: 'addTypeParameterToModuleMock',
|
|
54
|
+
data: {
|
|
55
|
+
moduleName: (moduleName === null || moduleName === void 0 ? void 0 : moduleName.raw) ?? './module-name'
|
|
56
|
+
},
|
|
57
|
+
node,
|
|
58
|
+
fix(fixer) {
|
|
59
|
+
if (!moduleName) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
return [fixer.insertTextAfter(callee, `<typeof import(${moduleName.raw})>`)];
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
exports.default = _default;
|
|
@@ -28,6 +28,16 @@ const getJestFnCall = node => {
|
|
|
28
28
|
}
|
|
29
29
|
return getJestFnCall(obj);
|
|
30
30
|
};
|
|
31
|
+
const getAutoFixMockImplementation = (jestFnCall, context) => {
|
|
32
|
+
var _jestFnCall$parent;
|
|
33
|
+
const hasMockImplementationAlready = ((_jestFnCall$parent = jestFnCall.parent) === null || _jestFnCall$parent === void 0 ? void 0 : _jestFnCall$parent.type) === _utils.AST_NODE_TYPES.MemberExpression && jestFnCall.parent.property.type === _utils.AST_NODE_TYPES.Identifier && jestFnCall.parent.property.name === 'mockImplementation';
|
|
34
|
+
if (hasMockImplementationAlready) {
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
const [arg] = jestFnCall.arguments;
|
|
38
|
+
const argSource = arg && context.getSourceCode().getText(arg);
|
|
39
|
+
return argSource ? `.mockImplementation(${argSource})` : '.mockImplementation()';
|
|
40
|
+
};
|
|
31
41
|
var _default = (0, _utils2.createRule)({
|
|
32
42
|
name: __filename,
|
|
33
43
|
meta: {
|
|
@@ -37,7 +47,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
37
47
|
recommended: false
|
|
38
48
|
},
|
|
39
49
|
messages: {
|
|
40
|
-
useJestSpyOn: 'Use jest.spyOn() instead
|
|
50
|
+
useJestSpyOn: 'Use jest.spyOn() instead'
|
|
41
51
|
},
|
|
42
52
|
fixable: 'code',
|
|
43
53
|
schema: [],
|
|
@@ -51,17 +61,19 @@ var _default = (0, _utils2.createRule)({
|
|
|
51
61
|
left,
|
|
52
62
|
right
|
|
53
63
|
} = node;
|
|
54
|
-
if (left.type !== _utils.AST_NODE_TYPES.MemberExpression)
|
|
64
|
+
if (left.type !== _utils.AST_NODE_TYPES.MemberExpression) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
55
67
|
const jestFnCall = getJestFnCall(right);
|
|
56
|
-
if (!jestFnCall)
|
|
68
|
+
if (!jestFnCall) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
57
71
|
context.report({
|
|
58
72
|
node,
|
|
59
73
|
messageId: 'useJestSpyOn',
|
|
60
74
|
fix(fixer) {
|
|
61
|
-
const leftPropQuote = left.property.type === _utils.AST_NODE_TYPES.Identifier ? "'" : '';
|
|
62
|
-
const
|
|
63
|
-
const argSource = arg && context.getSourceCode().getText(arg);
|
|
64
|
-
const mockImplementation = argSource ? `.mockImplementation(${argSource})` : '.mockImplementation()';
|
|
75
|
+
const leftPropQuote = left.property.type === _utils.AST_NODE_TYPES.Identifier && !left.computed ? "'" : '';
|
|
76
|
+
const mockImplementation = getAutoFixMockImplementation(jestFnCall, context);
|
|
65
77
|
return [fixer.insertTextBefore(left, `jest.spyOn(`), fixer.replaceTextRange([left.object.range[1], left.property.range[0]], `, ${leftPropQuote}`), fixer.replaceTextRange([left.property.range[1], jestFnCall.range[1]], `${leftPropQuote})${mockImplementation}`)];
|
|
66
78
|
}
|
|
67
79
|
});
|
|
@@ -63,7 +63,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
(_baseSelectors$Member = baseSelectors.MemberExpression) === null || _baseSelectors$Member === void 0
|
|
66
|
+
(_baseSelectors$Member = baseSelectors.MemberExpression) === null || _baseSelectors$Member === void 0 || _baseSelectors$Member.call(baseSelectors, node);
|
|
67
67
|
}
|
|
68
68
|
};
|
|
69
69
|
}
|
|
@@ -5,6 +5,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.isSupportedAccessor = exports.isStringNode = exports.isIdentifier = exports.getStringValue = exports.getAccessorValue = void 0;
|
|
7
7
|
var _utils = require("@typescript-eslint/utils");
|
|
8
|
+
/**
|
|
9
|
+
* A `Literal` with a `value` of type `string`.
|
|
10
|
+
*/
|
|
11
|
+
|
|
8
12
|
/**
|
|
9
13
|
* Checks if the given `node` is a `StringLiteral`.
|
|
10
14
|
*
|
package/lib/rules/utils/misc.js
CHANGED
|
@@ -21,6 +21,22 @@ const createRule = _utils.ESLintUtils.RuleCreator(name => {
|
|
|
21
21
|
/**
|
|
22
22
|
* Represents a `MemberExpression` with a "known" `property`.
|
|
23
23
|
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Represents a `CallExpression` with a "known" `property` accessor.
|
|
27
|
+
*
|
|
28
|
+
* i.e `KnownCallExpression<'includes'>` represents `.includes()`.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Represents a `MemberExpression` with a "known" `property`, that is called.
|
|
33
|
+
*
|
|
34
|
+
* This is `KnownCallExpression` from the perspective of the `MemberExpression` node.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Represents a `CallExpression` with a single argument.
|
|
39
|
+
*/
|
|
24
40
|
exports.createRule = createRule;
|
|
25
41
|
/**
|
|
26
42
|
* Guards that the given `call` has only one `argument`.
|
|
@@ -31,44 +47,44 @@ exports.createRule = createRule;
|
|
|
31
47
|
*/
|
|
32
48
|
const hasOnlyOneArgument = call => call.arguments.length === 1;
|
|
33
49
|
exports.hasOnlyOneArgument = hasOnlyOneArgument;
|
|
34
|
-
let DescribeAlias
|
|
35
|
-
exports.DescribeAlias = DescribeAlias;
|
|
36
|
-
(function (DescribeAlias) {
|
|
50
|
+
let DescribeAlias = /*#__PURE__*/function (DescribeAlias) {
|
|
37
51
|
DescribeAlias["describe"] = "describe";
|
|
38
52
|
DescribeAlias["fdescribe"] = "fdescribe";
|
|
39
53
|
DescribeAlias["xdescribe"] = "xdescribe";
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
exports.
|
|
43
|
-
|
|
54
|
+
return DescribeAlias;
|
|
55
|
+
}({});
|
|
56
|
+
exports.DescribeAlias = DescribeAlias;
|
|
57
|
+
let TestCaseName = /*#__PURE__*/function (TestCaseName) {
|
|
44
58
|
TestCaseName["fit"] = "fit";
|
|
45
59
|
TestCaseName["it"] = "it";
|
|
46
60
|
TestCaseName["test"] = "test";
|
|
47
61
|
TestCaseName["xit"] = "xit";
|
|
48
62
|
TestCaseName["xtest"] = "xtest";
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
exports.
|
|
52
|
-
|
|
63
|
+
return TestCaseName;
|
|
64
|
+
}({});
|
|
65
|
+
exports.TestCaseName = TestCaseName;
|
|
66
|
+
let HookName = /*#__PURE__*/function (HookName) {
|
|
53
67
|
HookName["beforeAll"] = "beforeAll";
|
|
54
68
|
HookName["beforeEach"] = "beforeEach";
|
|
55
69
|
HookName["afterAll"] = "afterAll";
|
|
56
70
|
HookName["afterEach"] = "afterEach";
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
exports.
|
|
60
|
-
|
|
71
|
+
return HookName;
|
|
72
|
+
}({});
|
|
73
|
+
exports.HookName = HookName;
|
|
74
|
+
let ModifierName = /*#__PURE__*/function (ModifierName) {
|
|
61
75
|
ModifierName["not"] = "not";
|
|
62
76
|
ModifierName["rejects"] = "rejects";
|
|
63
77
|
ModifierName["resolves"] = "resolves";
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
exports.
|
|
67
|
-
|
|
78
|
+
return ModifierName;
|
|
79
|
+
}({});
|
|
80
|
+
exports.ModifierName = ModifierName;
|
|
81
|
+
let EqualityMatcher = /*#__PURE__*/function (EqualityMatcher) {
|
|
68
82
|
EqualityMatcher["toBe"] = "toBe";
|
|
69
83
|
EqualityMatcher["toEqual"] = "toEqual";
|
|
70
84
|
EqualityMatcher["toStrictEqual"] = "toStrictEqual";
|
|
71
|
-
|
|
85
|
+
return EqualityMatcher;
|
|
86
|
+
}({});
|
|
87
|
+
exports.EqualityMatcher = EqualityMatcher;
|
|
72
88
|
const joinNames = (a, b) => a && b ? `${a}.${b}` : null;
|
|
73
89
|
function getNodeName(node) {
|
|
74
90
|
if ((0, _accessors.isSupportedAccessor)(node)) {
|
|
@@ -50,7 +50,7 @@ const isPromiseMethodThatUsesValue = (node, identifier) => {
|
|
|
50
50
|
const nodeName = (0, _utils2.getNodeName)(node.argument);
|
|
51
51
|
if (['Promise.all', 'Promise.allSettled'].includes(nodeName)) {
|
|
52
52
|
const [firstArg] = node.argument.arguments;
|
|
53
|
-
if (firstArg.type === _utils.AST_NODE_TYPES.ArrayExpression && firstArg.elements.some(nod => (0, _utils2.isIdentifier)(nod, name))) {
|
|
53
|
+
if (firstArg.type === _utils.AST_NODE_TYPES.ArrayExpression && firstArg.elements.some(nod => nod && (0, _utils2.isIdentifier)(nod, name))) {
|
|
54
54
|
return true;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -67,10 +67,10 @@ const isPromiseMethodThatUsesValue = (node, identifier) => {
|
|
|
67
67
|
*/
|
|
68
68
|
const isValueAwaitedInElements = (name, elements) => {
|
|
69
69
|
for (const element of elements) {
|
|
70
|
-
if (element.type === _utils.AST_NODE_TYPES.AwaitExpression && (0, _utils2.isIdentifier)(element.argument, name)) {
|
|
70
|
+
if ((element === null || element === void 0 ? void 0 : element.type) === _utils.AST_NODE_TYPES.AwaitExpression && (0, _utils2.isIdentifier)(element.argument, name)) {
|
|
71
71
|
return true;
|
|
72
72
|
}
|
|
73
|
-
if (element.type === _utils.AST_NODE_TYPES.ArrayExpression && isValueAwaitedInElements(name, element.elements)) {
|
|
73
|
+
if ((element === null || element === void 0 ? void 0 : element.type) === _utils.AST_NODE_TYPES.ArrayExpression && isValueAwaitedInElements(name, element.elements)) {
|
|
74
74
|
return true;
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -63,13 +63,13 @@ var _default = (0, _utils2.createRule)({
|
|
|
63
63
|
recommended: 'error'
|
|
64
64
|
},
|
|
65
65
|
messages: {
|
|
66
|
-
tooManyArgs: 'Expect takes at most {{ amount }} argument{{ s }}
|
|
67
|
-
notEnoughArgs: 'Expect requires at least {{ amount }} argument{{ s }}
|
|
68
|
-
modifierUnknown: 'Expect has an unknown modifier
|
|
69
|
-
matcherNotFound: 'Expect must have a corresponding matcher call
|
|
70
|
-
matcherNotCalled: 'Matchers must be called to assert
|
|
71
|
-
asyncMustBeAwaited: 'Async assertions must be awaited{{ orReturned }}
|
|
72
|
-
promisesWithAsyncAssertionsMustBeAwaited: 'Promises which return async assertions must be awaited{{ orReturned }}
|
|
66
|
+
tooManyArgs: 'Expect takes at most {{ amount }} argument{{ s }}',
|
|
67
|
+
notEnoughArgs: 'Expect requires at least {{ amount }} argument{{ s }}',
|
|
68
|
+
modifierUnknown: 'Expect has an unknown modifier',
|
|
69
|
+
matcherNotFound: 'Expect must have a corresponding matcher call',
|
|
70
|
+
matcherNotCalled: 'Matchers must be called to assert',
|
|
71
|
+
asyncMustBeAwaited: 'Async assertions must be awaited{{ orReturned }}',
|
|
72
|
+
promisesWithAsyncAssertionsMustBeAwaited: 'Promises which return async assertions must be awaited{{ orReturned }}'
|
|
73
73
|
},
|
|
74
74
|
type: 'suggestion',
|
|
75
75
|
schema: [{
|
package/lib/rules/valid-title.js
CHANGED
|
@@ -58,7 +58,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
58
58
|
emptyTitle: '{{ jestFunctionName }} should not have an empty title',
|
|
59
59
|
duplicatePrefix: 'should not have duplicate prefix',
|
|
60
60
|
accidentalSpace: 'should not have leading or trailing spaces',
|
|
61
|
-
disallowedWord: '"{{ word }}" is not allowed in test titles
|
|
61
|
+
disallowedWord: '"{{ word }}" is not allowed in test titles',
|
|
62
62
|
mustNotMatch: '{{ jestFunctionName }} should not match {{ pattern }}',
|
|
63
63
|
mustMatch: '{{ jestFunctionName }} should match {{ pattern }}',
|
|
64
64
|
mustNotMatchCustom: '{{ message }}',
|
|
@@ -68,6 +68,10 @@ var _default = (0, _utils2.createRule)({
|
|
|
68
68
|
schema: [{
|
|
69
69
|
type: 'object',
|
|
70
70
|
properties: {
|
|
71
|
+
ignoreSpaces: {
|
|
72
|
+
type: 'boolean',
|
|
73
|
+
default: false
|
|
74
|
+
},
|
|
71
75
|
ignoreTypeOfDescribeName: {
|
|
72
76
|
type: 'boolean',
|
|
73
77
|
default: false
|
|
@@ -101,10 +105,12 @@ var _default = (0, _utils2.createRule)({
|
|
|
101
105
|
fixable: 'code'
|
|
102
106
|
},
|
|
103
107
|
defaultOptions: [{
|
|
108
|
+
ignoreSpaces: false,
|
|
104
109
|
ignoreTypeOfDescribeName: false,
|
|
105
110
|
disallowedWords: []
|
|
106
111
|
}],
|
|
107
112
|
create(context, [{
|
|
113
|
+
ignoreSpaces,
|
|
108
114
|
ignoreTypeOfDescribeName,
|
|
109
115
|
disallowedWords = [],
|
|
110
116
|
mustNotMatch,
|
|
@@ -159,7 +165,7 @@ var _default = (0, _utils2.createRule)({
|
|
|
159
165
|
return;
|
|
160
166
|
}
|
|
161
167
|
}
|
|
162
|
-
if (title.trim().length !== title.length) {
|
|
168
|
+
if (ignoreSpaces === false && title.trim().length !== title.length) {
|
|
163
169
|
context.report({
|
|
164
170
|
messageId: 'accidentalSpace',
|
|
165
171
|
node: argument,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-jest",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.4.2",
|
|
4
4
|
"description": "ESLint rules for Jest",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
"email": "hello@jkimbo.com",
|
|
15
15
|
"url": "jkimbo.com"
|
|
16
16
|
},
|
|
17
|
-
"main": "lib/",
|
|
17
|
+
"main": "lib/index.js",
|
|
18
18
|
"files": [
|
|
19
19
|
"docs/",
|
|
20
20
|
"lib/"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
-
"build": "babel --extensions .js,.ts src --out-dir lib --copy-files && rimraf lib/__tests__ 'lib/**/__tests__'",
|
|
23
|
+
"build": "babel --extensions .js,.ts src --out-dir lib --copy-files && rimraf --glob lib/__tests__ 'lib/**/__tests__'",
|
|
24
24
|
"_postinstall": "is-ci || husky install",
|
|
25
25
|
"lint": "eslint . --ignore-pattern '!.eslintrc.js' --ext js,ts",
|
|
26
26
|
"prepack": "rimraf lib && yarn build",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"prettier:write": "prettier --write 'docs/**/*.md' README.md '.github/**' package.json tsconfig.json src/globals.json .yarnrc.yml",
|
|
30
30
|
"postpublish": "pinst --enable",
|
|
31
31
|
"test": "jest",
|
|
32
|
-
"tools:regenerate-docs": "yarn prepack && eslint-doc-generator
|
|
32
|
+
"tools:regenerate-docs": "yarn prepack && eslint-doc-generator",
|
|
33
33
|
"typecheck": "tsc -p ."
|
|
34
34
|
},
|
|
35
35
|
"commitlint": {
|
|
@@ -45,8 +45,7 @@
|
|
|
45
45
|
"arrowParens": "avoid",
|
|
46
46
|
"endOfLine": "auto",
|
|
47
47
|
"proseWrap": "always",
|
|
48
|
-
"singleQuote": true
|
|
49
|
-
"trailingComma": "all"
|
|
48
|
+
"singleQuote": true
|
|
50
49
|
},
|
|
51
50
|
"release": {
|
|
52
51
|
"branches": [
|
|
@@ -105,47 +104,46 @@
|
|
|
105
104
|
"@babel/preset-typescript": "^7.3.3",
|
|
106
105
|
"@commitlint/cli": "^17.0.3",
|
|
107
106
|
"@commitlint/config-conventional": "^17.0.3",
|
|
108
|
-
"@schemastore/package": "^0.0.
|
|
107
|
+
"@schemastore/package": "^0.0.10",
|
|
109
108
|
"@semantic-release/changelog": "^6.0.0",
|
|
110
109
|
"@semantic-release/git": "^10.0.0",
|
|
111
|
-
"@tsconfig/node14": "^1.0
|
|
112
|
-
"@types/dedent": "^0.7.0",
|
|
110
|
+
"@tsconfig/node14": "^14.1.0",
|
|
113
111
|
"@types/eslint": "^8.4.6",
|
|
114
112
|
"@types/jest": "^29.0.0",
|
|
115
113
|
"@types/node": "^14.18.26",
|
|
116
|
-
"@types/prettier": "^2.0.0",
|
|
117
114
|
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
|
118
115
|
"@typescript-eslint/parser": "^5.0.0",
|
|
119
116
|
"babel-jest": "^29.0.0",
|
|
120
117
|
"babel-plugin-replace-ts-export-assignment": "^0.0.2",
|
|
121
|
-
"dedent": "^
|
|
122
|
-
"eslint": "^
|
|
123
|
-
"eslint-config-prettier": "^
|
|
124
|
-
"eslint-doc-generator": "^0.
|
|
118
|
+
"dedent": "^1.5.0",
|
|
119
|
+
"eslint": "^7.0.0 || ^8.0.0",
|
|
120
|
+
"eslint-config-prettier": "^9.0.0",
|
|
121
|
+
"eslint-doc-generator": "^1.0.0",
|
|
125
122
|
"eslint-plugin-eslint-comments": "^3.1.2",
|
|
126
123
|
"eslint-plugin-eslint-plugin": "^5.0.6",
|
|
127
124
|
"eslint-plugin-import": "^2.25.1",
|
|
128
125
|
"eslint-plugin-node": "^11.0.0",
|
|
129
|
-
"eslint-plugin-prettier": "^
|
|
126
|
+
"eslint-plugin-prettier": "^5.0.0",
|
|
130
127
|
"eslint-remote-tester": "^3.0.0",
|
|
131
|
-
"eslint-remote-tester-repositories": "~0.0
|
|
128
|
+
"eslint-remote-tester-repositories": "~1.0.0",
|
|
132
129
|
"husky": "^8.0.1",
|
|
133
130
|
"is-ci": "^3.0.0",
|
|
134
131
|
"jest": "^29.0.0",
|
|
135
|
-
"jest-runner-eslint": "^
|
|
132
|
+
"jest-runner-eslint": "^2.0.0",
|
|
136
133
|
"lint-staged": "^13.0.3",
|
|
137
134
|
"markdown-link-check": "^3.10.2",
|
|
138
135
|
"pinst": "^3.0.0",
|
|
139
|
-
"prettier": "^
|
|
140
|
-
"rimraf": "^
|
|
141
|
-
"semantic-release": "^
|
|
136
|
+
"prettier": "^3.0.0",
|
|
137
|
+
"rimraf": "^5.0.0",
|
|
138
|
+
"semantic-release": "^22.0.0",
|
|
142
139
|
"semver": "^7.3.5",
|
|
143
140
|
"ts-node": "^10.2.1",
|
|
144
|
-
"typescript": "^
|
|
141
|
+
"typescript": "^5.0.4"
|
|
145
142
|
},
|
|
146
143
|
"peerDependencies": {
|
|
147
|
-
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
|
148
|
-
"eslint": "^7.0.0 || ^8.0.0"
|
|
144
|
+
"@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0",
|
|
145
|
+
"eslint": "^7.0.0 || ^8.0.0",
|
|
146
|
+
"jest": "*"
|
|
149
147
|
},
|
|
150
148
|
"peerDependenciesMeta": {
|
|
151
149
|
"@typescript-eslint/eslint-plugin": {
|
|
@@ -155,8 +153,11 @@
|
|
|
155
153
|
"optional": true
|
|
156
154
|
}
|
|
157
155
|
},
|
|
158
|
-
"packageManager": "yarn@3.3
|
|
156
|
+
"packageManager": "yarn@3.6.3",
|
|
159
157
|
"engines": {
|
|
160
158
|
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
|
159
|
+
},
|
|
160
|
+
"publishConfig": {
|
|
161
|
+
"provenance": true
|
|
161
162
|
}
|
|
162
163
|
}
|