eslint-plugin-jest 24.4.2 → 26.1.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 +75 -50
- package/docs/rules/expect-expect.md +42 -1
- package/docs/rules/max-nested-describe.md +4 -5
- package/docs/rules/no-conditional-expect.md +57 -3
- package/docs/rules/no-conditional-in-test.md +79 -0
- package/docs/rules/no-deprecated-functions.md +5 -0
- package/docs/rules/no-done-callback.md +3 -3
- package/docs/rules/no-if.md +5 -0
- package/docs/rules/no-standalone-expect.md +3 -3
- package/docs/rules/no-test-return-statement.md +1 -2
- package/docs/rules/prefer-comparison-matcher.md +55 -0
- package/docs/rules/prefer-equality-matcher.md +29 -0
- package/docs/rules/prefer-expect-assertions.md +126 -0
- package/docs/rules/prefer-expect-resolves.md +53 -0
- package/docs/rules/prefer-hooks-on-top.md +72 -48
- package/docs/rules/{lowercase-name.md → prefer-lowercase-title.md} +7 -7
- package/docs/rules/prefer-snapshot-hint.md +188 -0
- package/docs/rules/prefer-to-be.md +53 -0
- package/docs/rules/require-hook.md +187 -0
- package/docs/rules/require-top-level-describe.md +28 -0
- package/docs/rules/{valid-describe.md → valid-describe-callback.md} +1 -1
- package/docs/rules/valid-expect-in-promise.md +55 -14
- package/docs/rules/valid-expect.md +13 -0
- package/docs/rules/valid-title.md +30 -2
- package/lib/index.js +2 -3
- package/lib/processors/snapshot-processor.js +1 -1
- package/lib/rules/consistent-test-it.js +20 -20
- package/lib/rules/detectJestVersion.js +29 -0
- package/lib/rules/expect-expect.js +25 -11
- package/lib/rules/max-nested-describe.js +5 -5
- package/lib/rules/no-conditional-expect.js +9 -9
- package/lib/rules/no-conditional-in-test.js +60 -0
- package/lib/rules/no-deprecated-functions.js +14 -32
- package/lib/rules/no-done-callback.js +10 -10
- package/lib/rules/no-export.js +6 -6
- package/lib/rules/no-focused-tests.js +11 -11
- package/lib/rules/no-identical-title.js +3 -3
- package/lib/rules/no-if.js +13 -11
- package/lib/rules/no-interpolation-in-snapshots.js +6 -6
- package/lib/rules/no-jasmine-globals.js +10 -10
- package/lib/rules/no-large-snapshots.js +11 -11
- package/lib/rules/no-standalone-expect.js +14 -14
- package/lib/rules/no-test-prefixes.js +6 -6
- package/lib/rules/no-test-return-statement.js +8 -8
- package/lib/rules/prefer-comparison-matcher.js +139 -0
- package/lib/rules/prefer-equality-matcher.js +98 -0
- package/lib/rules/prefer-expect-assertions.js +93 -11
- package/lib/rules/prefer-expect-resolves.js +48 -0
- package/lib/rules/prefer-hooks-on-top.js +1 -1
- package/lib/rules/{lowercase-name.js → prefer-lowercase-title.js} +20 -1
- package/lib/rules/prefer-snapshot-hint.js +112 -0
- package/lib/rules/prefer-spy-on.js +9 -9
- package/lib/rules/prefer-to-be.js +136 -0
- package/lib/rules/prefer-to-contain.js +19 -67
- package/lib/rules/prefer-to-have-length.js +9 -14
- package/lib/rules/prefer-todo.js +9 -9
- package/lib/rules/require-hook.js +121 -0
- package/lib/rules/require-top-level-describe.js +40 -6
- package/lib/rules/utils.js +34 -30
- package/lib/rules/{valid-describe.js → valid-describe-callback.js} +9 -9
- package/lib/rules/valid-expect-in-promise.js +336 -67
- package/lib/rules/valid-expect.js +36 -19
- package/lib/rules/valid-title.js +61 -61
- package/package.json +40 -27
- package/CHANGELOG.md +0 -513
- package/docs/rules/no-expect-resolves.md +0 -47
- package/docs/rules/no-truthy-falsy.md +0 -53
- package/docs/rules/no-try-expect.md +0 -63
- package/docs/rules/prefer-inline-snapshots.md +0 -51
- package/docs/rules/prefer-to-be-null.md +0 -33
- package/docs/rules/prefer-to-be-undefined.md +0 -33
- package/lib/rules/no-expect-resolves.js +0 -40
- package/lib/rules/no-truthy-falsy.js +0 -58
- package/lib/rules/no-try-expect.js +0 -89
- package/lib/rules/prefer-inline-snapshots.js +0 -69
- package/lib/rules/prefer-to-be-null.js +0 -67
- package/lib/rules/prefer-to-be-undefined.js +0 -67
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Require setup and teardown code to be within a hook (`require-hook`)
|
|
2
|
+
|
|
3
|
+
Often while writing tests you have some setup work that needs to happen before
|
|
4
|
+
tests run, and you have some finishing work that needs to happen after tests
|
|
5
|
+
run. Jest provides helper functions to handle this.
|
|
6
|
+
|
|
7
|
+
It's common when writing tests to need to perform setup work that needs to
|
|
8
|
+
happen before tests run, and finishing work after tests run.
|
|
9
|
+
|
|
10
|
+
Because Jest executes all `describe` handlers in a test file _before_ it
|
|
11
|
+
executes any of the actual tests, it's important to ensure setup and teardown
|
|
12
|
+
work is done inside `before*` and `after*` handlers respectively, rather than
|
|
13
|
+
inside the `describe` blocks.
|
|
14
|
+
|
|
15
|
+
## Rule details
|
|
16
|
+
|
|
17
|
+
This rule flags any expression that is either at the toplevel of a test file or
|
|
18
|
+
directly within the body of a `describe`, _except_ for the following:
|
|
19
|
+
|
|
20
|
+
- `import` statements
|
|
21
|
+
- `const` variables
|
|
22
|
+
- `let` _declarations_, and initializations to `null` or `undefined`
|
|
23
|
+
- Classes
|
|
24
|
+
- Types
|
|
25
|
+
- Calls to the standard Jest globals
|
|
26
|
+
|
|
27
|
+
This rule flags any function calls within test files that are directly within
|
|
28
|
+
the body of a `describe`, and suggests wrapping them in one of the four
|
|
29
|
+
lifecycle hooks.
|
|
30
|
+
|
|
31
|
+
Here is a slightly contrived test file showcasing some common cases that would
|
|
32
|
+
be flagged:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
import { database, isCity } from '../database';
|
|
36
|
+
import { Logger } from '../../../src/Logger';
|
|
37
|
+
import { loadCities } from '../api';
|
|
38
|
+
|
|
39
|
+
jest.mock('../api');
|
|
40
|
+
|
|
41
|
+
const initializeCityDatabase = () => {
|
|
42
|
+
database.addCity('Vienna');
|
|
43
|
+
database.addCity('San Juan');
|
|
44
|
+
database.addCity('Wellington');
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const clearCityDatabase = () => {
|
|
48
|
+
database.clear();
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
initializeCityDatabase();
|
|
52
|
+
|
|
53
|
+
test('that persists cities', () => {
|
|
54
|
+
expect(database.cities.length).toHaveLength(3);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('city database has Vienna', () => {
|
|
58
|
+
expect(isCity('Vienna')).toBeTruthy();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('city database has San Juan', () => {
|
|
62
|
+
expect(isCity('San Juan')).toBeTruthy();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('when loading cities from the api', () => {
|
|
66
|
+
let consoleWarnSpy = jest.spyOn(console, 'warn');
|
|
67
|
+
|
|
68
|
+
loadCities.mockResolvedValue(['Wellington', 'London']);
|
|
69
|
+
|
|
70
|
+
it('does not duplicate cities', async () => {
|
|
71
|
+
await database.loadCities();
|
|
72
|
+
|
|
73
|
+
expect(database.cities).toHaveLength(4);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('logs any duplicates', async () => {
|
|
77
|
+
await database.loadCities();
|
|
78
|
+
|
|
79
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
80
|
+
'Ignored duplicate cities: Wellington',
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
clearCityDatabase();
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Here is the same slightly contrived test file showcasing the same common cases
|
|
89
|
+
but in ways that would be **not** flagged:
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
import { database, isCity } from '../database';
|
|
93
|
+
import { Logger } from '../../../src/Logger';
|
|
94
|
+
import { loadCities } from '../api';
|
|
95
|
+
|
|
96
|
+
jest.mock('../api');
|
|
97
|
+
|
|
98
|
+
const initializeCityDatabase = () => {
|
|
99
|
+
database.addCity('Vienna');
|
|
100
|
+
database.addCity('San Juan');
|
|
101
|
+
database.addCity('Wellington');
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const clearCityDatabase = () => {
|
|
105
|
+
database.clear();
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
beforeEach(() => {
|
|
109
|
+
initializeCityDatabase();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('that persists cities', () => {
|
|
113
|
+
expect(database.cities.length).toHaveLength(3);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('city database has Vienna', () => {
|
|
117
|
+
expect(isCity('Vienna')).toBeTruthy();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('city database has San Juan', () => {
|
|
121
|
+
expect(isCity('San Juan')).toBeTruthy();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('when loading cities from the api', () => {
|
|
125
|
+
let consoleWarnSpy;
|
|
126
|
+
|
|
127
|
+
beforeEach(() => {
|
|
128
|
+
consoleWarnSpy = jest.spyOn(console, 'warn');
|
|
129
|
+
loadCities.mockResolvedValue(['Wellington', 'London']);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('does not duplicate cities', async () => {
|
|
133
|
+
await database.loadCities();
|
|
134
|
+
|
|
135
|
+
expect(database.cities).toHaveLength(4);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('logs any duplicates', async () => {
|
|
139
|
+
await database.loadCities();
|
|
140
|
+
|
|
141
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
142
|
+
'Ignored duplicate cities: Wellington',
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
afterEach(() => {
|
|
148
|
+
clearCityDatabase();
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Options
|
|
153
|
+
|
|
154
|
+
If there are methods that you want to call outside of hooks and tests, you can
|
|
155
|
+
mark them as allowed using the `allowedFunctionCalls` option.
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"jest/require-hook": [
|
|
160
|
+
"error",
|
|
161
|
+
{
|
|
162
|
+
"allowedFunctionCalls": ["enableAutoDestroy"]
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Examples of **correct** code when using
|
|
169
|
+
`{ "allowedFunctionCalls": ["enableAutoDestroy"] }` option:
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
/* eslint jest/require-hook: ["error", { "allowedFunctionCalls": ["enableAutoDestroy"] }] */
|
|
173
|
+
|
|
174
|
+
import { enableAutoDestroy, mount } from '@vue/test-utils';
|
|
175
|
+
import { initDatabase, tearDownDatabase } from './databaseUtils';
|
|
176
|
+
|
|
177
|
+
enableAutoDestroy(afterEach);
|
|
178
|
+
|
|
179
|
+
beforeEach(initDatabase);
|
|
180
|
+
afterEach(tearDownDatabase);
|
|
181
|
+
|
|
182
|
+
describe('Foo', () => {
|
|
183
|
+
test('always returns 42', () => {
|
|
184
|
+
expect(global.getAnswer()).toBe(42);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
```
|
|
@@ -47,6 +47,34 @@ describe('test suite', () => {
|
|
|
47
47
|
});
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
You can also enforce a limit on the number of describes allowed at the top-level
|
|
51
|
+
using the `maxNumberOfTopLevelDescribes` option:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"jest/require-top-level-describe": [
|
|
56
|
+
"error",
|
|
57
|
+
{
|
|
58
|
+
"maxNumberOfTopLevelDescribes": 2
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Examples of **incorrect** code with the above config:
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
describe('test suite', () => {
|
|
68
|
+
it('test', () => {});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('test suite', () => {});
|
|
72
|
+
|
|
73
|
+
describe('test suite', () => {});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
This option defaults to `Infinity`, allowing any number of top-level describes.
|
|
77
|
+
|
|
50
78
|
## When Not To Use It
|
|
51
79
|
|
|
52
80
|
Don't use this rule on non-jest test files.
|
|
@@ -1,31 +1,72 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ensure promises that have expectations in their chain are valid (`valid-expect-in-promise`)
|
|
2
2
|
|
|
3
|
-
Ensure
|
|
4
|
-
promise
|
|
3
|
+
Ensure promises that include expectations are returned or awaited.
|
|
5
4
|
|
|
6
5
|
## Rule details
|
|
7
6
|
|
|
8
|
-
This rule
|
|
9
|
-
|
|
7
|
+
This rule flags any promises within the body of a test that include expectations
|
|
8
|
+
that have either not been returned or awaited.
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
The following pattern is considered warning:
|
|
10
|
+
The following patterns is considered warning:
|
|
14
11
|
|
|
15
12
|
```js
|
|
16
|
-
it('
|
|
17
|
-
|
|
18
|
-
expect(
|
|
13
|
+
it('promises a person', () => {
|
|
14
|
+
api.getPersonByName('bob').then(person => {
|
|
15
|
+
expect(person).toHaveProperty('name', 'Bob');
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('promises a counted person', () => {
|
|
20
|
+
const promise = api.getPersonByName('bob').then(person => {
|
|
21
|
+
expect(person).toHaveProperty('name', 'Bob');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
promise.then(() => {
|
|
25
|
+
expect(analytics.gottenPeopleCount).toBe(1);
|
|
19
26
|
});
|
|
20
27
|
});
|
|
28
|
+
|
|
29
|
+
it('promises multiple people', () => {
|
|
30
|
+
const firstPromise = api.getPersonByName('bob').then(person => {
|
|
31
|
+
expect(person).toHaveProperty('name', 'Bob');
|
|
32
|
+
});
|
|
33
|
+
const secondPromise = api.getPersonByName('alice').then(person => {
|
|
34
|
+
expect(person).toHaveProperty('name', 'Alice');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return Promise.any([firstPromise, secondPromise]);
|
|
38
|
+
});
|
|
21
39
|
```
|
|
22
40
|
|
|
23
41
|
The following pattern is not warning:
|
|
24
42
|
|
|
25
43
|
```js
|
|
26
|
-
it('
|
|
27
|
-
|
|
28
|
-
expect(
|
|
44
|
+
it('promises a person', async () => {
|
|
45
|
+
await api.getPersonByName('bob').then(person => {
|
|
46
|
+
expect(person).toHaveProperty('name', 'Bob');
|
|
29
47
|
});
|
|
30
48
|
});
|
|
49
|
+
|
|
50
|
+
it('promises a counted person', () => {
|
|
51
|
+
let promise = api.getPersonByName('bob').then(person => {
|
|
52
|
+
expect(person).toHaveProperty('name', 'Bob');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
promise = promise.then(() => {
|
|
56
|
+
expect(analytics.gottenPeopleCount).toBe(1);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return promise;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('promises multiple people', () => {
|
|
63
|
+
const firstPromise = api.getPersonByName('bob').then(person => {
|
|
64
|
+
expect(person).toHaveProperty('name', 'Bob');
|
|
65
|
+
});
|
|
66
|
+
const secondPromise = api.getPersonByName('alice').then(person => {
|
|
67
|
+
expect(person).toHaveProperty('name', 'Alice');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return Promise.allSettled([firstPromise, secondPromise]);
|
|
71
|
+
});
|
|
31
72
|
```
|
|
@@ -38,6 +38,11 @@ This rule is enabled by default.
|
|
|
38
38
|
type: 'boolean',
|
|
39
39
|
default: false,
|
|
40
40
|
},
|
|
41
|
+
asyncMatchers: {
|
|
42
|
+
type: 'array',
|
|
43
|
+
items: { type: 'string' },
|
|
44
|
+
default: ['toResolve', 'toReject'],
|
|
45
|
+
},
|
|
41
46
|
minArgs: {
|
|
42
47
|
type: 'number',
|
|
43
48
|
minimum: 1,
|
|
@@ -78,6 +83,14 @@ test('test1', async () => {
|
|
|
78
83
|
test('test2', () => expect(Promise.resolve(2)).resolves.toBe(2));
|
|
79
84
|
```
|
|
80
85
|
|
|
86
|
+
### `asyncMatchers`
|
|
87
|
+
|
|
88
|
+
Allows specifying which matchers return promises, and so should be considered
|
|
89
|
+
async when checking if an `expect` should be returned or awaited.
|
|
90
|
+
|
|
91
|
+
By default, this has a list of all the async matchers provided by
|
|
92
|
+
`jest-extended` (namely, `toResolve` and `toReject`).
|
|
93
|
+
|
|
81
94
|
### `minArgs` & `maxArgs`
|
|
82
95
|
|
|
83
96
|
Enforces the minimum and maximum number of arguments that `expect` can take, and
|
|
@@ -198,8 +198,9 @@ describe('the proper way to handle things', () => {});
|
|
|
198
198
|
Defaults: `{}`
|
|
199
199
|
|
|
200
200
|
Allows enforcing that titles must match or must not match a given Regular
|
|
201
|
-
Expression. An object can be provided to apply
|
|
202
|
-
|
|
201
|
+
Expression, with an optional message. An object can be provided to apply
|
|
202
|
+
different Regular Expressions (with optional messages) to specific Jest test
|
|
203
|
+
function groups (`describe`, `test`, and `it`).
|
|
203
204
|
|
|
204
205
|
Examples of **incorrect** code when using `mustMatch`:
|
|
205
206
|
|
|
@@ -226,3 +227,30 @@ describe('the tests that will be run', () => {});
|
|
|
226
227
|
test('that the stuff works', () => {});
|
|
227
228
|
xtest('that errors that thrown have messages', () => {});
|
|
228
229
|
```
|
|
230
|
+
|
|
231
|
+
Optionally you can provide a custom message to show for a particular matcher by
|
|
232
|
+
using a tuple at any level where you can provide a matcher:
|
|
233
|
+
|
|
234
|
+
```js
|
|
235
|
+
const prefixes = ['when', 'with', 'without', 'if', 'unless', 'for'];
|
|
236
|
+
const prefixesList = prefixes.join(' - \n');
|
|
237
|
+
|
|
238
|
+
module.exports = {
|
|
239
|
+
rules: {
|
|
240
|
+
'jest/valid-title': [
|
|
241
|
+
'error',
|
|
242
|
+
{
|
|
243
|
+
mustNotMatch: ['\\.$', 'Titles should not end with a full-stop'],
|
|
244
|
+
mustMatch: {
|
|
245
|
+
describe: [
|
|
246
|
+
new RegExp(`^(?:[A-Z]|\\b(${prefixes.join('|')})\\b`, 'u').source,
|
|
247
|
+
`Describe titles should either start with a capital letter or one of the following prefixes: ${prefixesList}`,
|
|
248
|
+
],
|
|
249
|
+
test: [/[^A-Z]/u.source],
|
|
250
|
+
it: /[^A-Z]/u.source,
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
],
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
```
|
package/lib/index.js
CHANGED
|
@@ -25,7 +25,7 @@ const importDefault = moduleName => // eslint-disable-next-line @typescript-esli
|
|
|
25
25
|
interopRequireDefault(require(moduleName)).default;
|
|
26
26
|
|
|
27
27
|
const rulesDir = (0, _path.join)(__dirname, 'rules');
|
|
28
|
-
const excludedFiles = ['__tests__', 'utils'];
|
|
28
|
+
const excludedFiles = ['__tests__', 'detectJestVersion', 'utils'];
|
|
29
29
|
const rules = (0, _fs.readdirSync)(rulesDir).map(rule => (0, _path.parse)(rule).name).filter(rule => !excludedFiles.includes(rule)).reduce((acc, curr) => ({ ...acc,
|
|
30
30
|
[curr]: importDefault((0, _path.join)(rulesDir, curr))
|
|
31
31
|
}), {});
|
|
@@ -52,8 +52,7 @@ module.exports = {
|
|
|
52
52
|
plugins: ['jest'],
|
|
53
53
|
rules: {
|
|
54
54
|
'jest/no-alias-methods': 'warn',
|
|
55
|
-
'jest/prefer-to-be
|
|
56
|
-
'jest/prefer-to-be-undefined': 'error',
|
|
55
|
+
'jest/prefer-to-be': 'error',
|
|
57
56
|
'jest/prefer-to-contain': 'error',
|
|
58
57
|
'jest/prefer-to-have-length': 'error'
|
|
59
58
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.preprocess = exports.postprocess = void 0;
|
|
7
7
|
|
|
8
8
|
// https://eslint.org/docs/developer-guide/working-with-plugins#processors-in-plugins
|
|
9
9
|
// https://github.com/typescript-eslint/typescript-eslint/issues/808
|
|
@@ -5,13 +5,13 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _utils = require("@typescript-eslint/utils");
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _utils2 = require("./utils");
|
|
11
11
|
|
|
12
|
-
const buildFixer = (callee, nodeName, preferredTestKeyword) => fixer => [fixer.replaceText(callee.type ===
|
|
12
|
+
const buildFixer = (callee, nodeName, preferredTestKeyword) => fixer => [fixer.replaceText(callee.type === _utils.AST_NODE_TYPES.MemberExpression ? callee.object : callee, getPreferredNodeName(nodeName, preferredTestKeyword))];
|
|
13
13
|
|
|
14
|
-
var _default = (0,
|
|
14
|
+
var _default = (0, _utils2.createRule)({
|
|
15
15
|
name: __filename,
|
|
16
16
|
meta: {
|
|
17
17
|
docs: {
|
|
@@ -28,10 +28,10 @@ var _default = (0, _utils.createRule)({
|
|
|
28
28
|
type: 'object',
|
|
29
29
|
properties: {
|
|
30
30
|
fn: {
|
|
31
|
-
enum: [
|
|
31
|
+
enum: [_utils2.TestCaseName.it, _utils2.TestCaseName.test]
|
|
32
32
|
},
|
|
33
33
|
withinDescribe: {
|
|
34
|
-
enum: [
|
|
34
|
+
enum: [_utils2.TestCaseName.it, _utils2.TestCaseName.test]
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
additionalProperties: false
|
|
@@ -39,30 +39,30 @@ var _default = (0, _utils.createRule)({
|
|
|
39
39
|
type: 'suggestion'
|
|
40
40
|
},
|
|
41
41
|
defaultOptions: [{
|
|
42
|
-
fn:
|
|
43
|
-
withinDescribe:
|
|
42
|
+
fn: _utils2.TestCaseName.test,
|
|
43
|
+
withinDescribe: _utils2.TestCaseName.it
|
|
44
44
|
}],
|
|
45
45
|
|
|
46
46
|
create(context) {
|
|
47
47
|
const configObj = context.options[0] || {};
|
|
48
|
-
const testKeyword = configObj.fn ||
|
|
49
|
-
const testKeywordWithinDescribe = configObj.withinDescribe || configObj.fn ||
|
|
48
|
+
const testKeyword = configObj.fn || _utils2.TestCaseName.test;
|
|
49
|
+
const testKeywordWithinDescribe = configObj.withinDescribe || configObj.fn || _utils2.TestCaseName.it;
|
|
50
50
|
let describeNestingLevel = 0;
|
|
51
51
|
return {
|
|
52
52
|
CallExpression(node) {
|
|
53
|
-
const nodeName = (0,
|
|
53
|
+
const nodeName = (0, _utils2.getNodeName)(node.callee);
|
|
54
54
|
|
|
55
55
|
if (!nodeName) {
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
if ((0,
|
|
59
|
+
if ((0, _utils2.isDescribeCall)(node)) {
|
|
60
60
|
describeNestingLevel++;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
const funcNode = node.callee.type ===
|
|
63
|
+
const funcNode = node.callee.type === _utils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _utils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
|
|
64
64
|
|
|
65
|
-
if ((0,
|
|
65
|
+
if ((0, _utils2.isTestCaseCall)(node) && describeNestingLevel === 0 && !nodeName.includes(testKeyword)) {
|
|
66
66
|
const oppositeTestKeyword = getOppositeTestKeyword(testKeyword);
|
|
67
67
|
context.report({
|
|
68
68
|
messageId: 'consistentMethod',
|
|
@@ -75,7 +75,7 @@ var _default = (0, _utils.createRule)({
|
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
if ((0,
|
|
78
|
+
if ((0, _utils2.isTestCaseCall)(node) && describeNestingLevel > 0 && !nodeName.includes(testKeywordWithinDescribe)) {
|
|
79
79
|
const oppositeTestKeyword = getOppositeTestKeyword(testKeywordWithinDescribe);
|
|
80
80
|
context.report({
|
|
81
81
|
messageId: 'consistentMethodWithinDescribe',
|
|
@@ -90,7 +90,7 @@ var _default = (0, _utils.createRule)({
|
|
|
90
90
|
},
|
|
91
91
|
|
|
92
92
|
'CallExpression:exit'(node) {
|
|
93
|
-
if ((0,
|
|
93
|
+
if ((0, _utils2.isDescribeCall)(node)) {
|
|
94
94
|
describeNestingLevel--;
|
|
95
95
|
}
|
|
96
96
|
}
|
|
@@ -103,7 +103,7 @@ var _default = (0, _utils.createRule)({
|
|
|
103
103
|
exports.default = _default;
|
|
104
104
|
|
|
105
105
|
function getPreferredNodeName(nodeName, preferredTestKeyword) {
|
|
106
|
-
if (nodeName ===
|
|
106
|
+
if (nodeName === _utils2.TestCaseName.fit) {
|
|
107
107
|
return 'test.only';
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -111,9 +111,9 @@ function getPreferredNodeName(nodeName, preferredTestKeyword) {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
function getOppositeTestKeyword(test) {
|
|
114
|
-
if (test ===
|
|
115
|
-
return
|
|
114
|
+
if (test === _utils2.TestCaseName.test) {
|
|
115
|
+
return _utils2.TestCaseName.it;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
return
|
|
118
|
+
return _utils2.TestCaseName.test;
|
|
119
119
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.detectJestVersion = void 0;
|
|
7
|
+
let cachedJestVersion = null;
|
|
8
|
+
|
|
9
|
+
const detectJestVersion = () => {
|
|
10
|
+
if (cachedJestVersion) {
|
|
11
|
+
return cachedJestVersion;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const jestPath = require.resolve('jest/package.json');
|
|
16
|
+
|
|
17
|
+
const jestPackageJson = // eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
18
|
+
require(jestPath);
|
|
19
|
+
|
|
20
|
+
if (jestPackageJson.version) {
|
|
21
|
+
const [majorVersion] = jestPackageJson.version.split('.');
|
|
22
|
+
return cachedJestVersion = parseInt(majorVersion, 10);
|
|
23
|
+
}
|
|
24
|
+
} catch {}
|
|
25
|
+
|
|
26
|
+
throw new Error('Unable to detect Jest version - please ensure jest package is installed, or otherwise set version explicitly');
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
exports.detectJestVersion = detectJestVersion;
|
|
@@ -5,9 +5,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _utils = require("@typescript-eslint/utils");
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _utils2 = require("./utils");
|
|
11
11
|
|
|
12
12
|
/*
|
|
13
13
|
* This implementation is adapted from eslint-plugin-jasmine.
|
|
@@ -28,7 +28,7 @@ function matchesAssertFunctionName(nodeName, patterns) {
|
|
|
28
28
|
}).join('\\.')}(\\.|$)`, 'ui').test(nodeName));
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
var _default = (0,
|
|
31
|
+
var _default = (0, _utils2.createRule)({
|
|
32
32
|
name: __filename,
|
|
33
33
|
meta: {
|
|
34
34
|
docs: {
|
|
@@ -47,6 +47,12 @@ var _default = (0, _utils.createRule)({
|
|
|
47
47
|
items: [{
|
|
48
48
|
type: 'string'
|
|
49
49
|
}]
|
|
50
|
+
},
|
|
51
|
+
additionalTestBlockFunctions: {
|
|
52
|
+
type: 'array',
|
|
53
|
+
items: {
|
|
54
|
+
type: 'string'
|
|
55
|
+
}
|
|
50
56
|
}
|
|
51
57
|
},
|
|
52
58
|
additionalProperties: false
|
|
@@ -54,21 +60,23 @@ var _default = (0, _utils.createRule)({
|
|
|
54
60
|
type: 'suggestion'
|
|
55
61
|
},
|
|
56
62
|
defaultOptions: [{
|
|
57
|
-
assertFunctionNames: ['expect']
|
|
63
|
+
assertFunctionNames: ['expect'],
|
|
64
|
+
additionalTestBlockFunctions: []
|
|
58
65
|
}],
|
|
59
66
|
|
|
60
67
|
create(context, [{
|
|
61
|
-
assertFunctionNames = ['expect']
|
|
68
|
+
assertFunctionNames = ['expect'],
|
|
69
|
+
additionalTestBlockFunctions = []
|
|
62
70
|
}]) {
|
|
63
71
|
const unchecked = [];
|
|
64
72
|
|
|
65
73
|
function checkCallExpressionUsed(nodes) {
|
|
66
74
|
for (const node of nodes) {
|
|
67
|
-
const index = node.type ===
|
|
75
|
+
const index = node.type === _utils.AST_NODE_TYPES.CallExpression ? unchecked.indexOf(node) : -1;
|
|
68
76
|
|
|
69
|
-
if (node.type ===
|
|
77
|
+
if (node.type === _utils.AST_NODE_TYPES.FunctionDeclaration) {
|
|
70
78
|
const declaredVariables = context.getDeclaredVariables(node);
|
|
71
|
-
const testCallExpressions = (0,
|
|
79
|
+
const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
|
|
72
80
|
checkCallExpressionUsed(testCallExpressions);
|
|
73
81
|
}
|
|
74
82
|
|
|
@@ -81,11 +89,17 @@ var _default = (0, _utils.createRule)({
|
|
|
81
89
|
|
|
82
90
|
return {
|
|
83
91
|
CallExpression(node) {
|
|
84
|
-
|
|
92
|
+
var _getNodeName;
|
|
93
|
+
|
|
94
|
+
const name = (_getNodeName = (0, _utils2.getNodeName)(node.callee)) !== null && _getNodeName !== void 0 ? _getNodeName : '';
|
|
95
|
+
|
|
96
|
+
if ((0, _utils2.isTestCaseCall)(node) || additionalTestBlockFunctions.includes(name)) {
|
|
97
|
+
if (node.callee.type === _utils.AST_NODE_TYPES.MemberExpression && (0, _utils2.isSupportedAccessor)(node.callee.property, 'todo')) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
85
100
|
|
|
86
|
-
if (name === _utils.TestCaseName.it || name === _utils.TestCaseName.test) {
|
|
87
101
|
unchecked.push(node);
|
|
88
|
-
} else if (
|
|
102
|
+
} else if (matchesAssertFunctionName(name, assertFunctionNames)) {
|
|
89
103
|
// Return early in case of nested `it` statements.
|
|
90
104
|
checkCallExpressionUsed(context.getAncestors());
|
|
91
105
|
}
|
|
@@ -5,11 +5,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _utils = require("@typescript-eslint/utils");
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _utils2 = require("./utils");
|
|
11
11
|
|
|
12
|
-
var _default = (0,
|
|
12
|
+
var _default = (0, _utils2.createRule)({
|
|
13
13
|
name: __filename,
|
|
14
14
|
meta: {
|
|
15
15
|
docs: {
|
|
@@ -46,7 +46,7 @@ var _default = (0, _utils.createRule)({
|
|
|
46
46
|
parent
|
|
47
47
|
} = node;
|
|
48
48
|
|
|
49
|
-
if ((parent === null || parent === void 0 ? void 0 : parent.type) !==
|
|
49
|
+
if ((parent === null || parent === void 0 ? void 0 : parent.type) !== _utils.AST_NODE_TYPES.CallExpression || !(0, _utils2.isDescribeCall)(parent)) {
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -69,7 +69,7 @@ var _default = (0, _utils.createRule)({
|
|
|
69
69
|
parent
|
|
70
70
|
} = node;
|
|
71
71
|
|
|
72
|
-
if ((parent === null || parent === void 0 ? void 0 : parent.type) ===
|
|
72
|
+
if ((parent === null || parent === void 0 ? void 0 : parent.type) === _utils.AST_NODE_TYPES.CallExpression && (0, _utils2.isDescribeCall)(parent)) {
|
|
73
73
|
describeCallbackStack.pop();
|
|
74
74
|
}
|
|
75
75
|
}
|