eslint-plugin-jest 24.4.3 → 24.5.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 +16 -0
- package/README.md +72 -49
- package/docs/rules/no-deprecated-functions.md +5 -0
- package/docs/rules/prefer-expect-resolves.md +53 -0
- package/docs/rules/prefer-to-be.md +53 -0
- package/docs/rules/require-top-level-describe.md +28 -0
- package/docs/rules/valid-title.md +30 -2
- package/lib/index.js +1 -1
- 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/prefer-expect-resolves.js +48 -0
- package/lib/rules/prefer-to-be.js +126 -0
- package/lib/rules/require-top-level-describe.js +40 -6
- package/lib/rules/utils.js +3 -1
- package/lib/rules/valid-title.js +47 -47
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
# [24.5.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.4.3...v24.5.0) (2021-09-29)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **no-deprecated-functions:** remove `process.cwd` from resolve paths ([#889](https://github.com/jest-community/eslint-plugin-jest/issues/889)) ([6940488](https://github.com/jest-community/eslint-plugin-jest/commit/6940488d7b5a47577e2823e6d4385b511c5becf4))
|
|
7
|
+
* **no-identical-title:** always consider `.each` titles unique ([#910](https://github.com/jest-community/eslint-plugin-jest/issues/910)) ([a41a40e](https://github.com/jest-community/eslint-plugin-jest/commit/a41a40eafaf1db444ba940cccd2014cb0dc41be9))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* create `prefer-expect-resolves` rule ([#822](https://github.com/jest-community/eslint-plugin-jest/issues/822)) ([2556020](https://github.com/jest-community/eslint-plugin-jest/commit/2556020a777f9daaf1d362a04e3f990415e82db8))
|
|
13
|
+
* create `prefer-to-be` rule ([#864](https://github.com/jest-community/eslint-plugin-jest/issues/864)) ([3a64aea](https://github.com/jest-community/eslint-plugin-jest/commit/3a64aea5bdc55465f1ef34f1426ae626d6c8a230))
|
|
14
|
+
* **require-top-level-describe:** support enforcing max num of describes ([#912](https://github.com/jest-community/eslint-plugin-jest/issues/912)) ([14a2d13](https://github.com/jest-community/eslint-plugin-jest/commit/14a2d1391c9f6f52509316542f45df35853c9b79))
|
|
15
|
+
* **valid-title:** allow custom matcher messages ([#913](https://github.com/jest-community/eslint-plugin-jest/issues/913)) ([ffc9392](https://github.com/jest-community/eslint-plugin-jest/commit/ffc93921348b0d4a394125f665d2bb09148ea37e))
|
|
16
|
+
|
|
1
17
|
## [24.4.3](https://github.com/jest-community/eslint-plugin-jest/compare/v24.4.2...v24.4.3) (2021-09-28)
|
|
2
18
|
|
|
3
19
|
|
package/README.md
CHANGED
|
@@ -59,23 +59,43 @@ doing:
|
|
|
59
59
|
This is included in all configs shared by this plugin, so can be omitted if
|
|
60
60
|
extending them.
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
depending on the version of `jest` being used.
|
|
62
|
+
### Jest `version` setting
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
The behaviour of some rules (specifically [`no-deprecated-functions`][]) change
|
|
65
|
+
depending on the version of Jest being used.
|
|
66
|
+
|
|
67
|
+
By default, this plugin will attempt to determine to locate Jest using
|
|
68
|
+
`require.resolve`, meaning it will start looking in the closest `node_modules`
|
|
69
|
+
folder to the file being linted and work its way up.
|
|
70
|
+
|
|
71
|
+
Since we cache the automatically determined version, if you're linting
|
|
72
|
+
sub-folders that have different versions of Jest, you may find that the wrong
|
|
73
|
+
version of Jest is considered when linting. You can work around this by
|
|
74
|
+
providing the Jest version explicitly in nested ESLint configs:
|
|
68
75
|
|
|
69
76
|
```json
|
|
70
77
|
{
|
|
71
78
|
"settings": {
|
|
72
79
|
"jest": {
|
|
73
|
-
"version":
|
|
80
|
+
"version": 27
|
|
74
81
|
}
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
```
|
|
78
85
|
|
|
86
|
+
To avoid hard-coding a number, you can also fetch it from the installed version
|
|
87
|
+
of Jest if you use a JavaScript config file such as `.eslintrc.js`:
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
module.exports = {
|
|
91
|
+
settings: {
|
|
92
|
+
jest: {
|
|
93
|
+
version: require('jest/package.json').version,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
```
|
|
98
|
+
|
|
79
99
|
## Shareable configurations
|
|
80
100
|
|
|
81
101
|
### Recommended
|
|
@@ -130,49 +150,51 @@ installations requiring long-term consistency.
|
|
|
130
150
|
|
|
131
151
|
<!-- begin base rules list -->
|
|
132
152
|
|
|
133
|
-
| Rule | Description
|
|
134
|
-
| ---------------------------------------------------------------------------- |
|
|
135
|
-
| [consistent-test-it](docs/rules/consistent-test-it.md) | Have control over `test` and `it` usages
|
|
136
|
-
| [expect-expect](docs/rules/expect-expect.md) | Enforce assertion to be made in a test body
|
|
137
|
-
| [lowercase-name](docs/rules/lowercase-name.md) | Enforce lowercase test names
|
|
138
|
-
| [max-nested-describe](docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls
|
|
139
|
-
| [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods
|
|
140
|
-
| [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests
|
|
141
|
-
| [no-conditional-expect](docs/rules/no-conditional-expect.md) | Prevent calling `expect` conditionally
|
|
142
|
-
| [no-deprecated-functions](docs/rules/no-deprecated-functions.md) | Disallow use of deprecated functions
|
|
143
|
-
| [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests
|
|
144
|
-
| [no-done-callback](docs/rules/no-done-callback.md) | Avoid using a callback in asynchronous tests and hooks
|
|
145
|
-
| [no-duplicate-hooks](docs/rules/no-duplicate-hooks.md) | Disallow duplicate setup and teardown hooks
|
|
146
|
-
| [no-export](docs/rules/no-export.md) | Disallow using `exports` in files containing tests
|
|
147
|
-
| [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests
|
|
148
|
-
| [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks
|
|
149
|
-
| [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles
|
|
150
|
-
| [no-if](docs/rules/no-if.md) | Disallow conditional logic
|
|
151
|
-
| [no-interpolation-in-snapshots](docs/rules/no-interpolation-in-snapshots.md) | Disallow string interpolation inside snapshots
|
|
152
|
-
| [no-jasmine-globals](docs/rules/no-jasmine-globals.md) | Disallow Jasmine globals
|
|
153
|
-
| [no-jest-import](docs/rules/no-jest-import.md) | Disallow importing Jest
|
|
154
|
-
| [no-large-snapshots](docs/rules/no-large-snapshots.md) | disallow large snapshots
|
|
155
|
-
| [no-mocks-import](docs/rules/no-mocks-import.md) | Disallow manually importing from `__mocks__`
|
|
156
|
-
| [no-restricted-matchers](docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers
|
|
157
|
-
| [no-standalone-expect](docs/rules/no-standalone-expect.md) | Disallow using `expect` outside of `it` or `test` blocks
|
|
158
|
-
| [no-test-prefixes](docs/rules/no-test-prefixes.md) | Use `.only` and `.skip` over `f` and `x`
|
|
159
|
-
| [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests
|
|
160
|
-
| [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()`
|
|
161
|
-
| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()`
|
|
162
|
-
| [prefer-
|
|
163
|
-
| [prefer-
|
|
164
|
-
| [prefer-
|
|
165
|
-
| [prefer-
|
|
166
|
-
| [prefer-to-be
|
|
167
|
-
| [prefer-to-
|
|
168
|
-
| [prefer-to-
|
|
169
|
-
| [prefer-
|
|
170
|
-
| [
|
|
171
|
-
| [
|
|
172
|
-
| [
|
|
173
|
-
| [
|
|
174
|
-
| [valid-
|
|
175
|
-
| [valid-
|
|
153
|
+
| Rule | Description | Configurations | Fixable |
|
|
154
|
+
| ---------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------- | ------------ |
|
|
155
|
+
| [consistent-test-it](docs/rules/consistent-test-it.md) | Have control over `test` and `it` usages | | ![fixable][] |
|
|
156
|
+
| [expect-expect](docs/rules/expect-expect.md) | Enforce assertion to be made in a test body | ![recommended][] | |
|
|
157
|
+
| [lowercase-name](docs/rules/lowercase-name.md) | Enforce lowercase test names | | ![fixable][] |
|
|
158
|
+
| [max-nested-describe](docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls | | |
|
|
159
|
+
| [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods | ![style][] | ![fixable][] |
|
|
160
|
+
| [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests | ![recommended][] | |
|
|
161
|
+
| [no-conditional-expect](docs/rules/no-conditional-expect.md) | Prevent calling `expect` conditionally | ![recommended][] | |
|
|
162
|
+
| [no-deprecated-functions](docs/rules/no-deprecated-functions.md) | Disallow use of deprecated functions | ![recommended][] | ![fixable][] |
|
|
163
|
+
| [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | ![recommended][] | |
|
|
164
|
+
| [no-done-callback](docs/rules/no-done-callback.md) | Avoid using a callback in asynchronous tests and hooks | ![recommended][] | ![suggest][] |
|
|
165
|
+
| [no-duplicate-hooks](docs/rules/no-duplicate-hooks.md) | Disallow duplicate setup and teardown hooks | | |
|
|
166
|
+
| [no-export](docs/rules/no-export.md) | Disallow using `exports` in files containing tests | ![recommended][] | |
|
|
167
|
+
| [no-focused-tests](docs/rules/no-focused-tests.md) | Disallow focused tests | ![recommended][] | ![suggest][] |
|
|
168
|
+
| [no-hooks](docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | |
|
|
169
|
+
| [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | ![recommended][] | |
|
|
170
|
+
| [no-if](docs/rules/no-if.md) | Disallow conditional logic | | |
|
|
171
|
+
| [no-interpolation-in-snapshots](docs/rules/no-interpolation-in-snapshots.md) | Disallow string interpolation inside snapshots | ![recommended][] | |
|
|
172
|
+
| [no-jasmine-globals](docs/rules/no-jasmine-globals.md) | Disallow Jasmine globals | ![recommended][] | ![fixable][] |
|
|
173
|
+
| [no-jest-import](docs/rules/no-jest-import.md) | Disallow importing Jest | ![recommended][] | |
|
|
174
|
+
| [no-large-snapshots](docs/rules/no-large-snapshots.md) | disallow large snapshots | | |
|
|
175
|
+
| [no-mocks-import](docs/rules/no-mocks-import.md) | Disallow manually importing from `__mocks__` | ![recommended][] | |
|
|
176
|
+
| [no-restricted-matchers](docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers | | |
|
|
177
|
+
| [no-standalone-expect](docs/rules/no-standalone-expect.md) | Disallow using `expect` outside of `it` or `test` blocks | ![recommended][] | |
|
|
178
|
+
| [no-test-prefixes](docs/rules/no-test-prefixes.md) | Use `.only` and `.skip` over `f` and `x` | ![recommended][] | ![fixable][] |
|
|
179
|
+
| [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests | | |
|
|
180
|
+
| [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` | | |
|
|
181
|
+
| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | ![suggest][] |
|
|
182
|
+
| [prefer-expect-resolves](docs/rules/prefer-expect-resolves.md) | Prefer `await expect(...).resolves` over `expect(await ...)` syntax | | ![fixable][] |
|
|
183
|
+
| [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md) | Suggest having hooks before any test cases | | |
|
|
184
|
+
| [prefer-spy-on](docs/rules/prefer-spy-on.md) | Suggest using `jest.spyOn()` | | ![fixable][] |
|
|
185
|
+
| [prefer-strict-equal](docs/rules/prefer-strict-equal.md) | Suggest using `toStrictEqual()` | | ![suggest][] |
|
|
186
|
+
| [prefer-to-be](docs/rules/prefer-to-be.md) | Suggest using `toBe()` for primitive literals | | ![fixable][] |
|
|
187
|
+
| [prefer-to-be-null](docs/rules/prefer-to-be-null.md) | Suggest using `toBeNull()` | ![style][] | ![fixable][] |
|
|
188
|
+
| [prefer-to-be-undefined](docs/rules/prefer-to-be-undefined.md) | Suggest using `toBeUndefined()` | ![style][] | ![fixable][] |
|
|
189
|
+
| [prefer-to-contain](docs/rules/prefer-to-contain.md) | Suggest using `toContain()` | ![style][] | ![fixable][] |
|
|
190
|
+
| [prefer-to-have-length](docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` | ![style][] | ![fixable][] |
|
|
191
|
+
| [prefer-todo](docs/rules/prefer-todo.md) | Suggest using `test.todo` | | ![fixable][] |
|
|
192
|
+
| [require-to-throw-message](docs/rules/require-to-throw-message.md) | Require a message for `toThrow()` | | |
|
|
193
|
+
| [require-top-level-describe](docs/rules/require-top-level-describe.md) | Require test cases and hooks to be inside a `describe` block | | |
|
|
194
|
+
| [valid-describe](docs/rules/valid-describe.md) | Enforce valid `describe()` callback | ![recommended][] | |
|
|
195
|
+
| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage | ![recommended][] | |
|
|
196
|
+
| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Enforce having return statement when testing with promises | ![recommended][] | |
|
|
197
|
+
| [valid-title](docs/rules/valid-title.md) | Enforce valid titles | ![recommended][] | ![fixable][] |
|
|
176
198
|
|
|
177
199
|
<!-- end base rules list -->
|
|
178
200
|
|
|
@@ -226,3 +248,4 @@ https://github.com/istanbuljs/eslint-plugin-istanbul
|
|
|
226
248
|
[suggest]: https://img.shields.io/badge/-suggest-yellow.svg
|
|
227
249
|
[fixable]: https://img.shields.io/badge/-fixable-green.svg
|
|
228
250
|
[style]: https://img.shields.io/badge/-style-blue.svg
|
|
251
|
+
[`no-deprecated-functions`]: docs/rules/no-deprecated-functions.md
|
|
@@ -6,6 +6,11 @@ either been renamed for clarity, or replaced with more powerful APIs.
|
|
|
6
6
|
While typically these deprecated functions are kept in the codebase for a number
|
|
7
7
|
of majors, eventually they are removed completely.
|
|
8
8
|
|
|
9
|
+
This rule requires knowing which version of Jest you're using - see
|
|
10
|
+
[this section of the readme](../../README.md#jest-version-setting) for details
|
|
11
|
+
on how that is obtained automatically and how you can explicitly provide a
|
|
12
|
+
version if needed.
|
|
13
|
+
|
|
9
14
|
## Rule details
|
|
10
15
|
|
|
11
16
|
This rule warns about calls to deprecated functions, and provides details on
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Prefer `await expect(...).resolves` over `expect(await ...)` syntax (`prefer-expect-resolves`)
|
|
2
|
+
|
|
3
|
+
When working with promises, there are two primary ways you can test the resolved
|
|
4
|
+
value:
|
|
5
|
+
|
|
6
|
+
1. use the `resolve` modifier on `expect`
|
|
7
|
+
(`await expect(...).resolves.<matcher>` style)
|
|
8
|
+
2. `await` the promise and assert against its result
|
|
9
|
+
(`expect(await ...).<matcher>` style)
|
|
10
|
+
|
|
11
|
+
While the second style is arguably less dependent on `jest`, if the promise
|
|
12
|
+
rejects it will be treated as a general error, resulting in less predictable
|
|
13
|
+
behaviour and output from `jest`.
|
|
14
|
+
|
|
15
|
+
Additionally, favoring the first style ensures consistency with its `rejects`
|
|
16
|
+
counterpart, as there is no way of "awaiting" a rejection.
|
|
17
|
+
|
|
18
|
+
## Rule details
|
|
19
|
+
|
|
20
|
+
This rule triggers a warning if an `await` is done within an `expect`, and
|
|
21
|
+
recommends using `resolves` instead.
|
|
22
|
+
|
|
23
|
+
Examples of **incorrect** code for this rule
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
it('passes', async () => {
|
|
27
|
+
expect(await someValue()).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('is true', async () => {
|
|
31
|
+
const myPromise = Promise.resolve(true);
|
|
32
|
+
|
|
33
|
+
expect(await myPromise).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Examples of **correct** code for this rule
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
it('passes', async () => {
|
|
41
|
+
await expect(someValue()).resolves.toBe(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('is true', async () => {
|
|
45
|
+
const myPromise = Promise.resolve(true);
|
|
46
|
+
|
|
47
|
+
await expect(myPromise).resolves.toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('errors', async () => {
|
|
51
|
+
await expect(Promise.rejects('oh noes!')).rejects.toThrow('oh noes!');
|
|
52
|
+
});
|
|
53
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Suggest using `toBe()` for primitive literals (`prefer-to-be`)
|
|
2
|
+
|
|
3
|
+
When asserting against primitive literals such as numbers and strings, the
|
|
4
|
+
equality matchers all operate the same, but read slightly differently in code.
|
|
5
|
+
|
|
6
|
+
This rule recommends using the `toBe` matcher in these situations, as it forms
|
|
7
|
+
the most grammatically natural sentence. For `null`, `undefined`, and `NaN` this
|
|
8
|
+
rule recommends using their specific `toBe` matchers, as they give better error
|
|
9
|
+
messages as well.
|
|
10
|
+
|
|
11
|
+
## Rule details
|
|
12
|
+
|
|
13
|
+
This rule triggers a warning if `toEqual()` or `toStrictEqual()` are used to
|
|
14
|
+
assert a primitive literal value such as numbers, strings, and booleans.
|
|
15
|
+
|
|
16
|
+
The following patterns are considered warnings:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
expect(value).not.toEqual(5);
|
|
20
|
+
expect(getMessage()).toStrictEqual('hello world');
|
|
21
|
+
expect(loadMessage()).resolves.toEqual('hello world');
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The following pattern is not warning:
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
expect(value).not.toBe(5);
|
|
28
|
+
expect(getMessage()).toBe('hello world');
|
|
29
|
+
expect(loadMessage()).resolves.toBe('hello world');
|
|
30
|
+
expect(didError).not.toBe(true);
|
|
31
|
+
|
|
32
|
+
expect(catchError()).toStrictEqual({ message: 'oh noes!' });
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For `null`, `undefined`, and `NaN`, this rule triggers a warning if `toBe` is
|
|
36
|
+
used to assert against those literal values instead of their more specific
|
|
37
|
+
`toBe` counterparts:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
expect(value).not.toBe(undefined);
|
|
41
|
+
expect(getMessage()).toBe(null);
|
|
42
|
+
expect(countMessages()).resolves.not.toBe(NaN);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The following pattern is not warning:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
expect(value).toBeDefined();
|
|
49
|
+
expect(getMessage()).toBeNull();
|
|
50
|
+
expect(countMessages()).resolves.not.toBeNaN();
|
|
51
|
+
|
|
52
|
+
expect(catchError()).toStrictEqual({ message: undefined });
|
|
53
|
+
```
|
|
@@ -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.
|
|
@@ -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
|
}), {});
|
|
@@ -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
|
|
|
@@ -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;
|
|
@@ -0,0 +1,126 @@
|
|
|
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
|
+
const isNullLiteral = node => node.type === _experimentalUtils.AST_NODE_TYPES.Literal && node.value === null;
|
|
13
|
+
/**
|
|
14
|
+
* Checks if the given `ParsedEqualityMatcherCall` is a call to one of the equality matchers,
|
|
15
|
+
* with a `null` literal as the sole argument.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const isNullEqualityMatcher = matcher => isNullLiteral(getFirstArgument(matcher));
|
|
20
|
+
|
|
21
|
+
const isFirstArgumentIdentifier = (matcher, name) => (0, _utils.isIdentifier)(getFirstArgument(matcher), name);
|
|
22
|
+
|
|
23
|
+
const isPrimitiveLiteral = matcher => getFirstArgument(matcher).type === _experimentalUtils.AST_NODE_TYPES.Literal;
|
|
24
|
+
|
|
25
|
+
const getFirstArgument = matcher => {
|
|
26
|
+
return (0, _utils.followTypeAssertionChain)(matcher.arguments[0]);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const reportPreferToBe = (context, whatToBe, matcher, modifier) => {
|
|
30
|
+
const modifierNode = (modifier === null || modifier === void 0 ? void 0 : modifier.negation) || (modifier === null || modifier === void 0 ? void 0 : modifier.node);
|
|
31
|
+
context.report({
|
|
32
|
+
messageId: `useToBe${whatToBe}`,
|
|
33
|
+
|
|
34
|
+
fix(fixer) {
|
|
35
|
+
var _matcher$arguments;
|
|
36
|
+
|
|
37
|
+
const fixes = [fixer.replaceText(matcher.node.property, `toBe${whatToBe}`)];
|
|
38
|
+
|
|
39
|
+
if ((_matcher$arguments = matcher.arguments) !== null && _matcher$arguments !== void 0 && _matcher$arguments.length && whatToBe !== '') {
|
|
40
|
+
fixes.push(fixer.remove(matcher.arguments[0]));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (modifierNode) {
|
|
44
|
+
fixes.push(fixer.removeRange([modifierNode.property.range[0] - 1, modifierNode.property.range[1]]));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return fixes;
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
node: matcher.node.property
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
var _default = (0, _utils.createRule)({
|
|
55
|
+
name: __filename,
|
|
56
|
+
meta: {
|
|
57
|
+
docs: {
|
|
58
|
+
category: 'Best Practices',
|
|
59
|
+
description: 'Suggest using `toBe()` for primitive literals',
|
|
60
|
+
recommended: false
|
|
61
|
+
},
|
|
62
|
+
messages: {
|
|
63
|
+
useToBe: 'Use `toBe` when expecting primitive literals',
|
|
64
|
+
useToBeUndefined: 'Use `toBeUndefined` instead',
|
|
65
|
+
useToBeDefined: 'Use `toBeDefined` instead',
|
|
66
|
+
useToBeNull: 'Use `toBeNull` instead',
|
|
67
|
+
useToBeNaN: 'Use `toBeNaN` instead'
|
|
68
|
+
},
|
|
69
|
+
fixable: 'code',
|
|
70
|
+
type: 'suggestion',
|
|
71
|
+
schema: []
|
|
72
|
+
},
|
|
73
|
+
defaultOptions: [],
|
|
74
|
+
|
|
75
|
+
create(context) {
|
|
76
|
+
return {
|
|
77
|
+
CallExpression(node) {
|
|
78
|
+
if (!(0, _utils.isExpectCall)(node)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const {
|
|
83
|
+
matcher,
|
|
84
|
+
modifier
|
|
85
|
+
} = (0, _utils.parseExpectCall)(node);
|
|
86
|
+
|
|
87
|
+
if (!matcher) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (((modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.not || modifier !== null && modifier !== void 0 && modifier.negation) && ['toBeUndefined', 'toBeDefined'].includes(matcher.name)) {
|
|
92
|
+
reportPreferToBe(context, matcher.name === 'toBeDefined' ? 'Undefined' : 'Defined', matcher, modifier);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!(0, _utils.isParsedEqualityMatcherCall)(matcher)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (isNullEqualityMatcher(matcher)) {
|
|
101
|
+
reportPreferToBe(context, 'Null', matcher);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (isFirstArgumentIdentifier(matcher, 'undefined')) {
|
|
106
|
+
const name = (modifier === null || modifier === void 0 ? void 0 : modifier.name) === _utils.ModifierName.not || modifier !== null && modifier !== void 0 && modifier.negation ? 'Defined' : 'Undefined';
|
|
107
|
+
reportPreferToBe(context, name, matcher, modifier);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (isFirstArgumentIdentifier(matcher, 'NaN')) {
|
|
112
|
+
reportPreferToBe(context, 'NaN', matcher);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (isPrimitiveLiteral(matcher) && matcher.name !== _utils.EqualityMatcher.toBe) {
|
|
117
|
+
reportPreferToBe(context, '', matcher);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
exports.default = _default;
|
|
@@ -7,6 +7,12 @@ exports.default = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _utils = require("./utils");
|
|
9
9
|
|
|
10
|
+
const messages = {
|
|
11
|
+
tooManyDescribes: 'There should not be more than {{ max }} describe{{ s }} at the top level',
|
|
12
|
+
unexpectedTestCase: 'All test cases must be wrapped in a describe block.',
|
|
13
|
+
unexpectedHook: 'All hooks must be wrapped in a describe block.'
|
|
14
|
+
};
|
|
15
|
+
|
|
10
16
|
var _default = (0, _utils.createRule)({
|
|
11
17
|
name: __filename,
|
|
12
18
|
meta: {
|
|
@@ -15,21 +21,49 @@ var _default = (0, _utils.createRule)({
|
|
|
15
21
|
description: 'Require test cases and hooks to be inside a `describe` block',
|
|
16
22
|
recommended: false
|
|
17
23
|
},
|
|
18
|
-
messages
|
|
19
|
-
unexpectedTestCase: 'All test cases must be wrapped in a describe block.',
|
|
20
|
-
unexpectedHook: 'All hooks must be wrapped in a describe block.'
|
|
21
|
-
},
|
|
24
|
+
messages,
|
|
22
25
|
type: 'suggestion',
|
|
23
|
-
schema: [
|
|
26
|
+
schema: [{
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: {
|
|
29
|
+
maxNumberOfTopLevelDescribes: {
|
|
30
|
+
type: 'number',
|
|
31
|
+
minimum: 1
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
additionalProperties: false
|
|
35
|
+
}]
|
|
24
36
|
},
|
|
25
|
-
defaultOptions: [],
|
|
37
|
+
defaultOptions: [{}],
|
|
26
38
|
|
|
27
39
|
create(context) {
|
|
40
|
+
var _context$options$;
|
|
41
|
+
|
|
42
|
+
const {
|
|
43
|
+
maxNumberOfTopLevelDescribes = Infinity
|
|
44
|
+
} = (_context$options$ = context.options[0]) !== null && _context$options$ !== void 0 ? _context$options$ : {};
|
|
45
|
+
let numberOfTopLevelDescribeBlocks = 0;
|
|
28
46
|
let numberOfDescribeBlocks = 0;
|
|
29
47
|
return {
|
|
30
48
|
CallExpression(node) {
|
|
31
49
|
if ((0, _utils.isDescribeCall)(node)) {
|
|
32
50
|
numberOfDescribeBlocks++;
|
|
51
|
+
|
|
52
|
+
if (numberOfDescribeBlocks === 1) {
|
|
53
|
+
numberOfTopLevelDescribeBlocks++;
|
|
54
|
+
|
|
55
|
+
if (numberOfTopLevelDescribeBlocks > maxNumberOfTopLevelDescribes) {
|
|
56
|
+
context.report({
|
|
57
|
+
node,
|
|
58
|
+
messageId: 'tooManyDescribes',
|
|
59
|
+
data: {
|
|
60
|
+
max: maxNumberOfTopLevelDescribes,
|
|
61
|
+
s: maxNumberOfTopLevelDescribes === 1 ? '' : 's'
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
33
67
|
return;
|
|
34
68
|
}
|
|
35
69
|
|
package/lib/rules/utils.js
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getNodeName = getNodeName;
|
|
7
|
-
exports.scopeHasLocalReference = exports.isDescribeCall = exports.isTestCaseCall = exports.getTestCallExpressionsFromDeclaredVariables = exports.isHook = exports.isFunction = exports.TestCaseProperty = exports.DescribeProperty = exports.HookName = exports.TestCaseName = exports.DescribeAlias = exports.parseExpectCall = exports.isParsedEqualityMatcherCall = exports.EqualityMatcher = exports.ModifierName = exports.isExpectMember = exports.isExpectCall = exports.getAccessorValue = exports.isSupportedAccessor = exports.hasOnlyOneArgument = exports.getStringValue = exports.isStringNode = exports.followTypeAssertionChain = exports.createRule = void 0;
|
|
7
|
+
exports.scopeHasLocalReference = exports.isDescribeCall = exports.isTestCaseCall = exports.getTestCallExpressionsFromDeclaredVariables = exports.isHook = exports.isFunction = exports.TestCaseProperty = exports.DescribeProperty = exports.HookName = exports.TestCaseName = exports.DescribeAlias = exports.parseExpectCall = exports.isParsedEqualityMatcherCall = exports.EqualityMatcher = exports.ModifierName = exports.isExpectMember = exports.isExpectCall = exports.getAccessorValue = exports.isSupportedAccessor = exports.isIdentifier = exports.hasOnlyOneArgument = exports.getStringValue = exports.isStringNode = exports.followTypeAssertionChain = exports.createRule = void 0;
|
|
8
8
|
|
|
9
9
|
var _path = require("path");
|
|
10
10
|
|
|
@@ -151,6 +151,8 @@ const isIdentifier = (node, name) => node.type === _experimentalUtils.AST_NODE_T
|
|
|
151
151
|
*/
|
|
152
152
|
|
|
153
153
|
|
|
154
|
+
exports.isIdentifier = isIdentifier;
|
|
155
|
+
|
|
154
156
|
const isSupportedAccessor = (node, value) => isIdentifier(node, value) || isStringNode(node, value);
|
|
155
157
|
/**
|
|
156
158
|
* Gets the value of the given `AccessorNode`,
|
package/lib/rules/valid-title.js
CHANGED
|
@@ -25,23 +25,38 @@ const doesBinaryExpressionContainStringNode = binaryExp => {
|
|
|
25
25
|
|
|
26
26
|
const quoteStringValue = node => node.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral ? `\`${node.quasis[0].value.raw}\`` : node.raw;
|
|
27
27
|
|
|
28
|
+
const compileMatcherPattern = matcherMaybeWithMessage => {
|
|
29
|
+
const [matcher, message] = Array.isArray(matcherMaybeWithMessage) ? matcherMaybeWithMessage : [matcherMaybeWithMessage];
|
|
30
|
+
return [new RegExp(matcher, 'u'), message];
|
|
31
|
+
};
|
|
32
|
+
|
|
28
33
|
const compileMatcherPatterns = matchers => {
|
|
29
|
-
if (typeof matchers === 'string') {
|
|
30
|
-
const
|
|
34
|
+
if (typeof matchers === 'string' || Array.isArray(matchers)) {
|
|
35
|
+
const compiledMatcher = compileMatcherPattern(matchers);
|
|
31
36
|
return {
|
|
32
|
-
describe:
|
|
33
|
-
test:
|
|
34
|
-
it:
|
|
37
|
+
describe: compiledMatcher,
|
|
38
|
+
test: compiledMatcher,
|
|
39
|
+
it: compiledMatcher
|
|
35
40
|
};
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
return {
|
|
39
|
-
describe: matchers.describe ?
|
|
40
|
-
test: matchers.test ?
|
|
41
|
-
it: matchers.it ?
|
|
44
|
+
describe: matchers.describe ? compileMatcherPattern(matchers.describe) : null,
|
|
45
|
+
test: matchers.test ? compileMatcherPattern(matchers.test) : null,
|
|
46
|
+
it: matchers.it ? compileMatcherPattern(matchers.it) : null
|
|
42
47
|
};
|
|
43
48
|
};
|
|
44
49
|
|
|
50
|
+
const MatcherAndMessageSchema = {
|
|
51
|
+
type: 'array',
|
|
52
|
+
items: {
|
|
53
|
+
type: 'string'
|
|
54
|
+
},
|
|
55
|
+
minItems: 1,
|
|
56
|
+
maxItems: 2,
|
|
57
|
+
additionalItems: false
|
|
58
|
+
};
|
|
59
|
+
|
|
45
60
|
var _default = (0, _utils.createRule)({
|
|
46
61
|
name: __filename,
|
|
47
62
|
meta: {
|
|
@@ -57,7 +72,9 @@ var _default = (0, _utils.createRule)({
|
|
|
57
72
|
accidentalSpace: 'should not have leading or trailing spaces',
|
|
58
73
|
disallowedWord: '"{{ word }}" is not allowed in test titles.',
|
|
59
74
|
mustNotMatch: '{{ jestFunctionName }} should not match {{ pattern }}',
|
|
60
|
-
mustMatch: '{{ jestFunctionName }} should match {{ pattern }}'
|
|
75
|
+
mustMatch: '{{ jestFunctionName }} should match {{ pattern }}',
|
|
76
|
+
mustNotMatchCustom: '{{ message }}',
|
|
77
|
+
mustMatchCustom: '{{ message }}'
|
|
61
78
|
},
|
|
62
79
|
type: 'suggestion',
|
|
63
80
|
schema: [{
|
|
@@ -72,43 +89,22 @@ var _default = (0, _utils.createRule)({
|
|
|
72
89
|
items: {
|
|
73
90
|
type: 'string'
|
|
74
91
|
}
|
|
75
|
-
}
|
|
76
|
-
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
patternProperties: {
|
|
95
|
+
[/^must(?:Not)?Match$/u.source]: {
|
|
77
96
|
oneOf: [{
|
|
78
97
|
type: 'string'
|
|
79
|
-
}, {
|
|
98
|
+
}, MatcherAndMessageSchema, {
|
|
80
99
|
type: 'object',
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
type: 'string'
|
|
84
|
-
},
|
|
85
|
-
test: {
|
|
86
|
-
type: 'string'
|
|
87
|
-
},
|
|
88
|
-
it: {
|
|
89
|
-
type: 'string'
|
|
90
|
-
}
|
|
100
|
+
propertyNames: {
|
|
101
|
+
enum: ['describe', 'test', 'it']
|
|
91
102
|
},
|
|
92
|
-
additionalProperties:
|
|
93
|
-
|
|
94
|
-
},
|
|
95
|
-
mustMatch: {
|
|
96
|
-
oneOf: [{
|
|
97
|
-
type: 'string'
|
|
98
|
-
}, {
|
|
99
|
-
type: 'object',
|
|
100
|
-
properties: {
|
|
101
|
-
describe: {
|
|
103
|
+
additionalProperties: {
|
|
104
|
+
oneOf: [{
|
|
102
105
|
type: 'string'
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
type: 'string'
|
|
106
|
-
},
|
|
107
|
-
it: {
|
|
108
|
-
type: 'string'
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
additionalProperties: false
|
|
106
|
+
}, MatcherAndMessageSchema]
|
|
107
|
+
}
|
|
112
108
|
}]
|
|
113
109
|
}
|
|
114
110
|
},
|
|
@@ -132,6 +128,8 @@ var _default = (0, _utils.createRule)({
|
|
|
132
128
|
const mustMatchPatterns = compileMatcherPatterns(mustMatch !== null && mustMatch !== void 0 ? mustMatch : {});
|
|
133
129
|
return {
|
|
134
130
|
CallExpression(node) {
|
|
131
|
+
var _mustNotMatchPatterns, _mustMatchPatterns$je;
|
|
132
|
+
|
|
135
133
|
if (!(0, _utils.isDescribeCall)(node) && !(0, _utils.isTestCaseCall)(node)) {
|
|
136
134
|
return;
|
|
137
135
|
}
|
|
@@ -205,32 +203,34 @@ var _default = (0, _utils.createRule)({
|
|
|
205
203
|
}
|
|
206
204
|
|
|
207
205
|
const [jestFunctionName] = nodeName.split('.');
|
|
208
|
-
const mustNotMatchPattern = mustNotMatchPatterns[jestFunctionName];
|
|
206
|
+
const [mustNotMatchPattern, mustNotMatchMessage] = (_mustNotMatchPatterns = mustNotMatchPatterns[jestFunctionName]) !== null && _mustNotMatchPatterns !== void 0 ? _mustNotMatchPatterns : [];
|
|
209
207
|
|
|
210
208
|
if (mustNotMatchPattern) {
|
|
211
209
|
if (mustNotMatchPattern.test(title)) {
|
|
212
210
|
context.report({
|
|
213
|
-
messageId: 'mustNotMatch',
|
|
211
|
+
messageId: mustNotMatchMessage ? 'mustNotMatchCustom' : 'mustNotMatch',
|
|
214
212
|
node: argument,
|
|
215
213
|
data: {
|
|
216
214
|
jestFunctionName,
|
|
217
|
-
pattern: mustNotMatchPattern
|
|
215
|
+
pattern: mustNotMatchPattern,
|
|
216
|
+
message: mustNotMatchMessage
|
|
218
217
|
}
|
|
219
218
|
});
|
|
220
219
|
return;
|
|
221
220
|
}
|
|
222
221
|
}
|
|
223
222
|
|
|
224
|
-
const mustMatchPattern = mustMatchPatterns[jestFunctionName];
|
|
223
|
+
const [mustMatchPattern, mustMatchMessage] = (_mustMatchPatterns$je = mustMatchPatterns[jestFunctionName]) !== null && _mustMatchPatterns$je !== void 0 ? _mustMatchPatterns$je : [];
|
|
225
224
|
|
|
226
225
|
if (mustMatchPattern) {
|
|
227
226
|
if (!mustMatchPattern.test(title)) {
|
|
228
227
|
context.report({
|
|
229
|
-
messageId: 'mustMatch',
|
|
228
|
+
messageId: mustMatchMessage ? 'mustMatchCustom' : 'mustMatch',
|
|
230
229
|
node: argument,
|
|
231
230
|
data: {
|
|
232
231
|
jestFunctionName,
|
|
233
|
-
pattern: mustMatchPattern
|
|
232
|
+
pattern: mustMatchPattern,
|
|
233
|
+
message: mustMatchMessage
|
|
234
234
|
}
|
|
235
235
|
});
|
|
236
236
|
return;
|