eslint-plugin-jest 25.0.0-next.4 → 25.0.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/CHANGELOG.md +138 -0
- package/README.md +71 -49
- package/docs/rules/max-nested-describe.md +4 -5
- package/docs/rules/no-conditional-expect.md +57 -3
- package/docs/rules/no-deprecated-functions.md +5 -0
- package/docs/rules/no-done-callback.md +3 -3
- package/docs/rules/no-standalone-expect.md +3 -3
- package/docs/rules/no-test-return-statement.md +1 -2
- package/docs/rules/prefer-expect-resolves.md +53 -0
- package/docs/rules/{lowercase-name.md → prefer-lowercase-title.md} +1 -1
- package/docs/rules/prefer-to-be.md +53 -0
- package/docs/rules/require-hook.md +149 -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-title.md +30 -2
- package/lib/index.js +2 -3
- package/lib/rules/detectJestVersion.js +29 -0
- package/lib/rules/no-deprecated-functions.js +9 -27
- package/lib/rules/no-identical-title.js +3 -3
- package/lib/rules/no-large-snapshots.js +1 -3
- package/lib/rules/prefer-expect-resolves.js +48 -0
- package/lib/rules/{lowercase-name.js → prefer-lowercase-title.js} +20 -1
- package/lib/rules/prefer-to-be.js +129 -0
- package/lib/rules/require-hook.js +87 -0
- package/lib/rules/require-top-level-describe.js +40 -6
- package/lib/rules/utils.js +6 -4
- package/lib/rules/{valid-describe.js → valid-describe-callback.js} +0 -0
- package/lib/rules/valid-expect-in-promise.js +252 -68
- package/lib/rules/valid-expect.js +10 -4
- package/lib/rules/valid-title.js +47 -47
- package/package.json +5 -5
- package/docs/rules/prefer-to-be-null.md +0 -33
- package/docs/rules/prefer-to-be-undefined.md +0 -33
- package/lib/rules/prefer-to-be-null.js +0 -67
- package/lib/rules/prefer-to-be-undefined.js +0 -67
|
@@ -0,0 +1,149 @@
|
|
|
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_
|
|
23
|
+
- Types
|
|
24
|
+
- Calls to the standard Jest globals
|
|
25
|
+
|
|
26
|
+
This rule flags any function calls within test files that are directly within
|
|
27
|
+
the body of a `describe`, and suggests wrapping them in one of the four
|
|
28
|
+
lifecycle hooks.
|
|
29
|
+
|
|
30
|
+
Here is a slightly contrived test file showcasing some common cases that would
|
|
31
|
+
be flagged:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
import { database, isCity } from '../database';
|
|
35
|
+
import { Logger } from '../../../src/Logger';
|
|
36
|
+
import { loadCities } from '../api';
|
|
37
|
+
|
|
38
|
+
jest.mock('../api');
|
|
39
|
+
|
|
40
|
+
const initializeCityDatabase = () => {
|
|
41
|
+
database.addCity('Vienna');
|
|
42
|
+
database.addCity('San Juan');
|
|
43
|
+
database.addCity('Wellington');
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const clearCityDatabase = () => {
|
|
47
|
+
database.clear();
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
initializeCityDatabase();
|
|
51
|
+
|
|
52
|
+
test('that persists cities', () => {
|
|
53
|
+
expect(database.cities.length).toHaveLength(3);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('city database has Vienna', () => {
|
|
57
|
+
expect(isCity('Vienna')).toBeTruthy();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('city database has San Juan', () => {
|
|
61
|
+
expect(isCity('San Juan')).toBeTruthy();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('when loading cities from the api', () => {
|
|
65
|
+
let consoleWarnSpy = jest.spyOn(console, 'warn');
|
|
66
|
+
|
|
67
|
+
loadCities.mockResolvedValue(['Wellington', 'London']);
|
|
68
|
+
|
|
69
|
+
it('does not duplicate cities', async () => {
|
|
70
|
+
await database.loadCities();
|
|
71
|
+
|
|
72
|
+
expect(database.cities).toHaveLength(4);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('logs any duplicates', async () => {
|
|
76
|
+
await database.loadCities();
|
|
77
|
+
|
|
78
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
79
|
+
'Ignored duplicate cities: Wellington',
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
clearCityDatabase();
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Here is the same slightly contrived test file showcasing the same common cases
|
|
88
|
+
but in ways that would be **not** flagged:
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
import { database, isCity } from '../database';
|
|
92
|
+
import { Logger } from '../../../src/Logger';
|
|
93
|
+
import { loadCities } from '../api';
|
|
94
|
+
|
|
95
|
+
jest.mock('../api');
|
|
96
|
+
|
|
97
|
+
const initializeCityDatabase = () => {
|
|
98
|
+
database.addCity('Vienna');
|
|
99
|
+
database.addCity('San Juan');
|
|
100
|
+
database.addCity('Wellington');
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const clearCityDatabase = () => {
|
|
104
|
+
database.clear();
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
beforeEach(() => {
|
|
108
|
+
initializeCityDatabase();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('that persists cities', () => {
|
|
112
|
+
expect(database.cities.length).toHaveLength(3);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('city database has Vienna', () => {
|
|
116
|
+
expect(isCity('Vienna')).toBeTruthy();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('city database has San Juan', () => {
|
|
120
|
+
expect(isCity('San Juan')).toBeTruthy();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('when loading cities from the api', () => {
|
|
124
|
+
let consoleWarnSpy;
|
|
125
|
+
|
|
126
|
+
beforeEach(() => {
|
|
127
|
+
consoleWarnSpy = jest.spyOn(console, 'warn');
|
|
128
|
+
loadCities.mockResolvedValue(['Wellington', 'London']);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('does not duplicate cities', async () => {
|
|
132
|
+
await database.loadCities();
|
|
133
|
+
|
|
134
|
+
expect(database.cities).toHaveLength(4);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('logs any duplicates', async () => {
|
|
138
|
+
await database.loadCities();
|
|
139
|
+
|
|
140
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
141
|
+
'Ignored duplicate cities: Wellington',
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
afterEach(() => {
|
|
147
|
+
clearCityDatabase();
|
|
148
|
+
});
|
|
149
|
+
```
|
|
@@ -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
|
```
|
|
@@ -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
|
}
|
|
@@ -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;
|
|
@@ -3,39 +3,21 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.default =
|
|
6
|
+
exports.default = void 0;
|
|
7
7
|
|
|
8
8
|
var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
9
9
|
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
let cachedJestVersion = null;
|
|
13
|
-
/** @internal */
|
|
10
|
+
var _detectJestVersion = require("./detectJestVersion");
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
exports._clearCachedJestVersion = _clearCachedJestVersion;
|
|
12
|
+
var _utils = require("./utils");
|
|
18
13
|
|
|
19
|
-
const
|
|
20
|
-
if (
|
|
21
|
-
return
|
|
14
|
+
const parseJestVersion = rawVersion => {
|
|
15
|
+
if (typeof rawVersion === 'number') {
|
|
16
|
+
return rawVersion;
|
|
22
17
|
}
|
|
23
18
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
paths: [process.cwd()]
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const jestPackageJson = // eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
30
|
-
require(jestPath);
|
|
31
|
-
|
|
32
|
-
if (jestPackageJson.version) {
|
|
33
|
-
const [majorVersion] = jestPackageJson.version.split('.');
|
|
34
|
-
return cachedJestVersion = parseInt(majorVersion, 10);
|
|
35
|
-
}
|
|
36
|
-
} catch {}
|
|
37
|
-
|
|
38
|
-
throw new Error('Unable to detect Jest version - please ensure jest package is installed, or otherwise set version explicitly');
|
|
19
|
+
const [majorVersion] = rawVersion.split('.');
|
|
20
|
+
return parseInt(majorVersion, 10);
|
|
39
21
|
};
|
|
40
22
|
|
|
41
23
|
var _default = (0, _utils.createRule)({
|
|
@@ -58,7 +40,7 @@ var _default = (0, _utils.createRule)({
|
|
|
58
40
|
create(context) {
|
|
59
41
|
var _context$settings, _context$settings$jes;
|
|
60
42
|
|
|
61
|
-
const jestVersion = ((_context$settings = context.settings) === null || _context$settings === void 0 ? void 0 : (_context$settings$jes = _context$settings.jest) === null || _context$settings$jes === void 0 ? void 0 : _context$settings$jes.version) || detectJestVersion();
|
|
43
|
+
const jestVersion = parseJestVersion(((_context$settings = context.settings) === null || _context$settings === void 0 ? void 0 : (_context$settings$jes = _context$settings.jest) === null || _context$settings$jes === void 0 ? void 0 : _context$settings$jes.version) || (0, _detectJestVersion.detectJestVersion)());
|
|
62
44
|
const deprecations = { ...(jestVersion >= 15 && {
|
|
63
45
|
'jest.resetModuleRegistry': 'jest.resetModules'
|
|
64
46
|
}),
|
|
@@ -5,8 +5,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
9
|
-
|
|
10
8
|
var _utils = require("./utils");
|
|
11
9
|
|
|
12
10
|
const newDescribeContext = () => ({
|
|
@@ -35,13 +33,15 @@ var _default = (0, _utils.createRule)({
|
|
|
35
33
|
const contexts = [newDescribeContext()];
|
|
36
34
|
return {
|
|
37
35
|
CallExpression(node) {
|
|
36
|
+
var _getNodeName;
|
|
37
|
+
|
|
38
38
|
const currentLayer = contexts[contexts.length - 1];
|
|
39
39
|
|
|
40
40
|
if ((0, _utils.isDescribeCall)(node)) {
|
|
41
41
|
contexts.push(newDescribeContext());
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
if (node.callee
|
|
44
|
+
if ((_getNodeName = (0, _utils.getNodeName)(node.callee)) !== null && _getNodeName !== void 0 && _getNodeName.endsWith('.each')) {
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -100,8 +100,6 @@ var _default = (0, _utils.createRule)({
|
|
|
100
100
|
|
|
101
101
|
return {
|
|
102
102
|
CallExpression(node) {
|
|
103
|
-
var _matcher$node$parent;
|
|
104
|
-
|
|
105
103
|
if (!(0, _utils.isExpectCall)(node)) {
|
|
106
104
|
return;
|
|
107
105
|
}
|
|
@@ -110,7 +108,7 @@ var _default = (0, _utils.createRule)({
|
|
|
110
108
|
matcher
|
|
111
109
|
} = (0, _utils.parseExpectCall)(node);
|
|
112
110
|
|
|
113
|
-
if ((matcher === null || matcher === void 0 ? void 0 :
|
|
111
|
+
if ((matcher === null || matcher === void 0 ? void 0 : matcher.node.parent.type) !== _experimentalUtils.AST_NODE_TYPES.CallExpression) {
|
|
114
112
|
return;
|
|
115
113
|
}
|
|
116
114
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
9
|
+
|
|
10
|
+
var _utils = require("./utils");
|
|
11
|
+
|
|
12
|
+
var _default = (0, _utils.createRule)({
|
|
13
|
+
name: __filename,
|
|
14
|
+
meta: {
|
|
15
|
+
docs: {
|
|
16
|
+
category: 'Best Practices',
|
|
17
|
+
description: 'Prefer `await expect(...).resolves` over `expect(await ...)` syntax',
|
|
18
|
+
recommended: false
|
|
19
|
+
},
|
|
20
|
+
fixable: 'code',
|
|
21
|
+
messages: {
|
|
22
|
+
expectResolves: 'Use `await expect(...).resolves instead.'
|
|
23
|
+
},
|
|
24
|
+
schema: [],
|
|
25
|
+
type: 'suggestion'
|
|
26
|
+
},
|
|
27
|
+
defaultOptions: [],
|
|
28
|
+
create: context => ({
|
|
29
|
+
CallExpression(node) {
|
|
30
|
+
const [awaitNode] = node.arguments;
|
|
31
|
+
|
|
32
|
+
if ((0, _utils.isExpectCall)(node) && (awaitNode === null || awaitNode === void 0 ? void 0 : awaitNode.type) === _experimentalUtils.AST_NODE_TYPES.AwaitExpression) {
|
|
33
|
+
context.report({
|
|
34
|
+
node: node.arguments[0],
|
|
35
|
+
messageId: 'expectResolves',
|
|
36
|
+
|
|
37
|
+
fix(fixer) {
|
|
38
|
+
return [fixer.insertTextBefore(node, 'await '), fixer.removeRange([awaitNode.range[0], awaitNode.argument.range[0]]), fixer.insertTextAfter(node, '.resolves')];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
})
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
exports.default = _default;
|
|
@@ -21,6 +21,24 @@ const findNodeNameAndArgument = node => {
|
|
|
21
21
|
return [(0, _utils.getNodeName)(node).split('.')[0], node.arguments[0]];
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
const populateIgnores = ignore => {
|
|
25
|
+
const ignores = [];
|
|
26
|
+
|
|
27
|
+
if (ignore.includes(_utils.DescribeAlias.describe)) {
|
|
28
|
+
ignores.push(...Object.keys(_utils.DescribeAlias));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (ignore.includes(_utils.TestCaseName.test)) {
|
|
32
|
+
ignores.push(...Object.keys(_utils.TestCaseName));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (ignore.includes(_utils.TestCaseName.it)) {
|
|
36
|
+
ignores.push(...Object.keys(_utils.TestCaseName));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return ignores;
|
|
40
|
+
};
|
|
41
|
+
|
|
24
42
|
var _default = (0, _utils.createRule)({
|
|
25
43
|
name: __filename,
|
|
26
44
|
meta: {
|
|
@@ -70,6 +88,7 @@ var _default = (0, _utils.createRule)({
|
|
|
70
88
|
allowedPrefixes = [],
|
|
71
89
|
ignoreTopLevelDescribe
|
|
72
90
|
}]) {
|
|
91
|
+
const ignores = populateIgnores(ignore);
|
|
73
92
|
let numberOfDescribeBlocks = 0;
|
|
74
93
|
return {
|
|
75
94
|
CallExpression(node) {
|
|
@@ -96,7 +115,7 @@ var _default = (0, _utils.createRule)({
|
|
|
96
115
|
|
|
97
116
|
const firstCharacter = description.charAt(0);
|
|
98
117
|
|
|
99
|
-
if (!firstCharacter || firstCharacter === firstCharacter.toLowerCase() ||
|
|
118
|
+
if (!firstCharacter || firstCharacter === firstCharacter.toLowerCase() || ignores.includes(name)) {
|
|
100
119
|
return;
|
|
101
120
|
}
|
|
102
121
|
|