eslint-plugin-jest 21.21.0 → 21.24.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 +4 -0
- package/docs/rules/expect-expect.md +51 -4
- package/docs/rules/no-alias-methods.md +46 -0
- package/docs/rules/require-tothrow-message.md +29 -0
- package/index.js +4 -0
- package/package.json +2 -4
- package/rules/__tests__/expect-expect.test.js +29 -0
- package/rules/__tests__/no-alias-methods.test.js +157 -0
- package/rules/__tests__/no-disabled-tests.test.js +34 -1
- package/rules/__tests__/prefer-strict-equal.test.js +4 -1
- package/rules/__tests__/require-tothrow-message.test.js +52 -0
- package/rules/expect-expect.js +18 -2
- package/rules/no-alias-methods.js +57 -0
- package/rules/no-disabled-tests.js +41 -1
- package/rules/prefer-strict-equal.js +10 -3
- package/rules/require-tothrow-message.js +39 -0
package/README.md
CHANGED
|
@@ -83,6 +83,7 @@ for more information about extending configuration files.
|
|
|
83
83
|
| [consistent-test-it][] | Enforce consistent test or it keyword | | ![fixable-green][] |
|
|
84
84
|
| [expect-expect][] | Enforce assertion to be made in a test body | | |
|
|
85
85
|
| [lowercase-name][] | Disallow capitalized test names | | ![fixable-green][] |
|
|
86
|
+
| [no-alias-methods][] | Disallow alias methods | | |
|
|
86
87
|
| [no-disabled-tests][] | Disallow disabled tests | ![recommended][] | |
|
|
87
88
|
| [no-focused-tests][] | Disallow focused tests | ![recommended][] | |
|
|
88
89
|
| [no-hooks][] | Disallow setup and teardown hooks | | |
|
|
@@ -98,6 +99,7 @@ for more information about extending configuration files.
|
|
|
98
99
|
| [prefer-to-be-undefined][] | Suggest using `toBeUndefined()` | | ![fixable-green][] |
|
|
99
100
|
| [prefer-to-have-length][] | Suggest using `toHaveLength()` | ![recommended][] | ![fixable-green][] |
|
|
100
101
|
| [prefer-inline-snapshots][] | Suggest using `toMatchInlineSnapshot()` | | ![fixable-green][] |
|
|
102
|
+
| [require-tothrow-message][] | Require that `toThrow()` and `toThrowError` includes a message | | |
|
|
101
103
|
| [valid-describe][] | Enforce valid `describe()` callback | | |
|
|
102
104
|
| [valid-expect-in-promise][] | Enforce having return statement when testing with promises | | |
|
|
103
105
|
| [valid-expect][] | Enforce valid `expect()` usage | ![recommended][] | |
|
|
@@ -110,6 +112,7 @@ for more information about extending configuration files.
|
|
|
110
112
|
[consistent-test-it]: docs/rules/consistent-test-it.md
|
|
111
113
|
[expect-expect]: docs/rules/expect-expect.md
|
|
112
114
|
[lowercase-name]: docs/rules/lowercase-name.md
|
|
115
|
+
[no-alias-methods]: docs/rules/no-alias-methods.md
|
|
113
116
|
[no-disabled-tests]: docs/rules/no-disabled-tests.md
|
|
114
117
|
[no-focused-tests]: docs/rules/no-focused-tests.md
|
|
115
118
|
[no-hooks]: docs/rules/no-hooks.md
|
|
@@ -125,6 +128,7 @@ for more information about extending configuration files.
|
|
|
125
128
|
[prefer-to-be-undefined]: docs/rules/prefer-to-be-undefined.md
|
|
126
129
|
[prefer-to-have-length]: docs/rules/prefer-to-have-length.md
|
|
127
130
|
[prefer-inline-snapshots]: docs/rules/prefer-inline-snapshots.md
|
|
131
|
+
[require-tothrow-message]: docs/rules/require-tothrow-message.md
|
|
128
132
|
[valid-describe]: docs/rules/valid-describe.md
|
|
129
133
|
[valid-expect-in-promise]: docs/rules/valid-expect-in-promise.md
|
|
130
134
|
[valid-expect]: docs/rules/valid-expect.md
|
|
@@ -7,9 +7,7 @@ Ensure that there is at least one `expect` call made in a test.
|
|
|
7
7
|
This rule triggers when there is no call made to `expect` in a test, to prevent
|
|
8
8
|
users from forgetting to add assertions.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
The following patterns are considered warnings:
|
|
10
|
+
Examples of **incorrect** code for this rule:
|
|
13
11
|
|
|
14
12
|
```js
|
|
15
13
|
it('should be a test', () => {
|
|
@@ -18,7 +16,7 @@ it('should be a test', () => {
|
|
|
18
16
|
test('should assert something', () => {});
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
Examples of **correct** code for this rule:
|
|
22
20
|
|
|
23
21
|
```js
|
|
24
22
|
it('should be a test', () => {
|
|
@@ -28,3 +26,52 @@ it('should work with callbacks/async', () => {
|
|
|
28
26
|
somePromise().then(res => expect(res).toBe('passed'));
|
|
29
27
|
});
|
|
30
28
|
```
|
|
29
|
+
|
|
30
|
+
## Options
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"jest/expect-expect": [
|
|
35
|
+
"error",
|
|
36
|
+
{
|
|
37
|
+
"assertFunctionNames": ["expect"]
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### `assertFunctionNames`
|
|
44
|
+
|
|
45
|
+
This array option whitelists the assertion function names to look for.
|
|
46
|
+
|
|
47
|
+
Examples of **incorrect** code for the `{ "assertFunctionNames": ["expect"] }`
|
|
48
|
+
option:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect"] }] */
|
|
52
|
+
|
|
53
|
+
import { expectSaga } from 'redux-saga-test-plan';
|
|
54
|
+
import { addSaga } from '../src/sagas';
|
|
55
|
+
|
|
56
|
+
test('returns sum', () =>
|
|
57
|
+
expectSaga(addSaga, 1, 1)
|
|
58
|
+
.returns(2)
|
|
59
|
+
.run();
|
|
60
|
+
);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Examples of **correct** code for the
|
|
64
|
+
`{ "assertFunctionNames": ["expect", "expectSaga"] }` option:
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "expectSaga"] }] */
|
|
68
|
+
|
|
69
|
+
import { expectSaga } from 'redux-saga-test-plan';
|
|
70
|
+
import { addSaga } from '../src/sagas';
|
|
71
|
+
|
|
72
|
+
test('returns sum', () =>
|
|
73
|
+
expectSaga(addSaga, 1, 1)
|
|
74
|
+
.returns(2)
|
|
75
|
+
.run();
|
|
76
|
+
);
|
|
77
|
+
```
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Don't use alias methods (no-alias-methods)
|
|
2
|
+
|
|
3
|
+
Several Jest methods have alias names, such as `toThrow` having the alias of
|
|
4
|
+
`toThrowError`. This rule ensures that only the canonical name as used in the
|
|
5
|
+
Jest documentation is used in the code. This makes it easier to search for all
|
|
6
|
+
occurrences of the method within code, and it ensures consistency among the
|
|
7
|
+
method names used.
|
|
8
|
+
|
|
9
|
+
## Rule details
|
|
10
|
+
|
|
11
|
+
This rule triggers a warning if the alias name, rather than the canonical name,
|
|
12
|
+
of a method is used.
|
|
13
|
+
|
|
14
|
+
### Default configuration
|
|
15
|
+
|
|
16
|
+
The following patterns are considered warnings:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
expect(a).toBeCalled();
|
|
20
|
+
expect(a).toBeCalledTimes();
|
|
21
|
+
expect(a).toBeCalledWith();
|
|
22
|
+
expect(a).lastCalledWith();
|
|
23
|
+
expect(a).nthCalledWith();
|
|
24
|
+
expect(a).toReturn();
|
|
25
|
+
expect(a).toReturnTimes();
|
|
26
|
+
expect(a).toReturnWith();
|
|
27
|
+
expect(a).lastReturnedWith();
|
|
28
|
+
expect(a).nthReturnedWith();
|
|
29
|
+
expect(a).toThrowError();
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The following patterns are not considered warnings:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
expect(a).toHaveBeenCalled();
|
|
36
|
+
expect(a).toHaveBeenCalledTimes();
|
|
37
|
+
expect(a).toHaveBeenCalledWith();
|
|
38
|
+
expect(a).toHaveBeenLastCalledWith();
|
|
39
|
+
expect(a).toHaveBeenNthCalledWith();
|
|
40
|
+
expect(a).toHaveReturned();
|
|
41
|
+
expect(a).toHaveReturnedTimes();
|
|
42
|
+
expect(a).toHaveReturnedWith();
|
|
43
|
+
expect(a).toHaveLastReturnedWith();
|
|
44
|
+
expect(a).toHaveNthReturnedWith();
|
|
45
|
+
expect(a).toThrow();
|
|
46
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Require a message for `toThrow()` (require-tothrow-message)
|
|
2
|
+
|
|
3
|
+
`toThrow()`, and its alias `toThrowError()`, are used to check if an error is
|
|
4
|
+
thrown by a function call, such as in `expect(() => a()).toThrow()`. However, if
|
|
5
|
+
no message is defined, then the test will pass for any thrown error. Requiring a
|
|
6
|
+
message ensures that the intended error is thrown.
|
|
7
|
+
|
|
8
|
+
## Rule details
|
|
9
|
+
|
|
10
|
+
This rule triggers a warning if `toThrow()` or `toThrowError()` is used without
|
|
11
|
+
an error message.
|
|
12
|
+
|
|
13
|
+
### Default configuration
|
|
14
|
+
|
|
15
|
+
The following patterns are considered warnings:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
expect(() => a()).toThrow();
|
|
19
|
+
|
|
20
|
+
expect(() => a()).toThrowError();
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The following patterns are not considered warnings:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
expect(() => a()).toThrow('a');
|
|
27
|
+
|
|
28
|
+
expect(() => a()).toThrowError('a');
|
|
29
|
+
```
|
package/index.js
CHANGED
|
@@ -21,6 +21,8 @@ const preferExpectAssertions = require('./rules/prefer-expect-assertions');
|
|
|
21
21
|
const validExpectInPromise = require('./rules/valid-expect-in-promise');
|
|
22
22
|
const preferInlineSnapshots = require('./rules/prefer-inline-snapshots');
|
|
23
23
|
const preferStrictEqual = require('./rules/prefer-strict-equal');
|
|
24
|
+
const requireTothrowMessage = require('./rules/require-tothrow-message');
|
|
25
|
+
const noAliasMethods = require('./rules/no-alias-methods');
|
|
24
26
|
|
|
25
27
|
const snapshotProcessor = require('./processors/snapshot-processor');
|
|
26
28
|
|
|
@@ -89,5 +91,7 @@ module.exports = {
|
|
|
89
91
|
'valid-expect-in-promise': validExpectInPromise,
|
|
90
92
|
'prefer-inline-snapshots': preferInlineSnapshots,
|
|
91
93
|
'prefer-strict-equal': preferStrictEqual,
|
|
94
|
+
'require-tothrow-message': requireTothrowMessage,
|
|
95
|
+
'no-alias-methods': noAliasMethods,
|
|
92
96
|
},
|
|
93
97
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-jest",
|
|
3
|
-
"version": "21.
|
|
3
|
+
"version": "21.24.0",
|
|
4
4
|
"description": "Eslint rules for Jest",
|
|
5
5
|
"repository": "jest-community/eslint-plugin-jest",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,9 +46,7 @@
|
|
|
46
46
|
"jest-runner-eslint": "^0.4.0",
|
|
47
47
|
"lint-staged": "^7.0.0",
|
|
48
48
|
"prettier": "^1.10.2",
|
|
49
|
-
"prettylint": "^1.0.0"
|
|
50
|
-
"semantic-release": "^15.0.2",
|
|
51
|
-
"travis-deploy-once": "^4.3.1"
|
|
49
|
+
"prettylint": "^1.0.0"
|
|
52
50
|
},
|
|
53
51
|
"prettier": {
|
|
54
52
|
"proseWrap": "always",
|
|
@@ -14,6 +14,15 @@ ruleTester.run('expect-expect', rule, {
|
|
|
14
14
|
'it("should pass", () => expect(true).toBeDefined())',
|
|
15
15
|
'test("should pass", () => expect(true).toBeDefined())',
|
|
16
16
|
'it("should pass", () => somePromise().then(() => expect(true).toBeDefined()))',
|
|
17
|
+
{
|
|
18
|
+
code:
|
|
19
|
+
'test("should pass", () => { expect(true).toBeDefined(); foo(true).toBe(true); })',
|
|
20
|
+
options: [{ assertFunctionNames: ['expect', 'foo'] }],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
code: 'it("should return undefined",() => expectSaga(mySaga).returns());',
|
|
24
|
+
options: [{ assertFunctionNames: ['expectSaga'] }],
|
|
25
|
+
},
|
|
17
26
|
],
|
|
18
27
|
|
|
19
28
|
invalid: [
|
|
@@ -44,5 +53,25 @@ ruleTester.run('expect-expect', rule, {
|
|
|
44
53
|
},
|
|
45
54
|
],
|
|
46
55
|
},
|
|
56
|
+
{
|
|
57
|
+
code: 'test("should fail", () => { foo(true).toBe(true); })',
|
|
58
|
+
options: [{ assertFunctionNames: ['expect'] }],
|
|
59
|
+
errors: [
|
|
60
|
+
{
|
|
61
|
+
message: 'Test has no assertions',
|
|
62
|
+
type: 'CallExpression',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
code: 'it("should also fail",() => expectSaga(mySaga).returns());',
|
|
68
|
+
options: [{ assertFunctionNames: ['expect'] }],
|
|
69
|
+
errors: [
|
|
70
|
+
{
|
|
71
|
+
message: 'Test has no assertions',
|
|
72
|
+
type: 'CallExpression',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
47
76
|
],
|
|
48
77
|
});
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
const rule = require('../no-alias-methods');
|
|
5
|
+
|
|
6
|
+
const ruleTester = new RuleTester();
|
|
7
|
+
|
|
8
|
+
ruleTester.run('no-alias-methods', rule, {
|
|
9
|
+
valid: [
|
|
10
|
+
'expect(a).toHaveBeenCalled()',
|
|
11
|
+
'expect(a).toHaveBeenCalledTimes()',
|
|
12
|
+
'expect(a).toHaveBeenCalledWith()',
|
|
13
|
+
'expect(a).toHaveBeenLastCalledWith()',
|
|
14
|
+
'expect(a).toHaveBeenNthCalledWith()',
|
|
15
|
+
'expect(a).toHaveReturned()',
|
|
16
|
+
'expect(a).toHaveReturnedTimes()',
|
|
17
|
+
'expect(a).toHaveReturnedWith()',
|
|
18
|
+
'expect(a).toHaveLastReturnedWith()',
|
|
19
|
+
'expect(a).toHaveNthReturnedWith()',
|
|
20
|
+
'expect(a).toThrow()',
|
|
21
|
+
],
|
|
22
|
+
|
|
23
|
+
invalid: [
|
|
24
|
+
{
|
|
25
|
+
code: 'expect(a).toBeCalled()',
|
|
26
|
+
errors: [
|
|
27
|
+
{
|
|
28
|
+
message:
|
|
29
|
+
'Replace toBeCalled() with its canonical name of toHaveBeenCalled()',
|
|
30
|
+
column: 11,
|
|
31
|
+
line: 1,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
output: 'expect(a).toHaveBeenCalled()',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
code: 'expect(a).toBeCalledTimes()',
|
|
38
|
+
errors: [
|
|
39
|
+
{
|
|
40
|
+
message:
|
|
41
|
+
'Replace toBeCalledTimes() with its canonical name of toHaveBeenCalledTimes()',
|
|
42
|
+
column: 11,
|
|
43
|
+
line: 1,
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
output: 'expect(a).toHaveBeenCalledTimes()',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
code: 'expect(a).toBeCalledWith()',
|
|
50
|
+
errors: [
|
|
51
|
+
{
|
|
52
|
+
message:
|
|
53
|
+
'Replace toBeCalledWith() with its canonical name of toHaveBeenCalledWith()',
|
|
54
|
+
column: 11,
|
|
55
|
+
line: 1,
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
output: 'expect(a).toHaveBeenCalledWith()',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
code: 'expect(a).lastCalledWith()',
|
|
62
|
+
errors: [
|
|
63
|
+
{
|
|
64
|
+
message:
|
|
65
|
+
'Replace lastCalledWith() with its canonical name of toHaveBeenLastCalledWith()',
|
|
66
|
+
column: 11,
|
|
67
|
+
line: 1,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
output: 'expect(a).toHaveBeenLastCalledWith()',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
code: 'expect(a).nthCalledWith()',
|
|
74
|
+
errors: [
|
|
75
|
+
{
|
|
76
|
+
message:
|
|
77
|
+
'Replace nthCalledWith() with its canonical name of toHaveBeenNthCalledWith()',
|
|
78
|
+
column: 11,
|
|
79
|
+
line: 1,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
output: 'expect(a).toHaveBeenNthCalledWith()',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
code: 'expect(a).toReturn()',
|
|
86
|
+
errors: [
|
|
87
|
+
{
|
|
88
|
+
message:
|
|
89
|
+
'Replace toReturn() with its canonical name of toHaveReturned()',
|
|
90
|
+
column: 11,
|
|
91
|
+
line: 1,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
output: 'expect(a).toHaveReturned()',
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
code: 'expect(a).toReturnTimes()',
|
|
98
|
+
errors: [
|
|
99
|
+
{
|
|
100
|
+
message:
|
|
101
|
+
'Replace toReturnTimes() with its canonical name of toHaveReturnedTimes()',
|
|
102
|
+
column: 11,
|
|
103
|
+
line: 1,
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
output: 'expect(a).toHaveReturnedTimes()',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
code: 'expect(a).toReturnWith()',
|
|
110
|
+
errors: [
|
|
111
|
+
{
|
|
112
|
+
message:
|
|
113
|
+
'Replace toReturnWith() with its canonical name of toHaveReturnedWith()',
|
|
114
|
+
column: 11,
|
|
115
|
+
line: 1,
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
output: 'expect(a).toHaveReturnedWith()',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
code: 'expect(a).lastReturnedWith()',
|
|
122
|
+
errors: [
|
|
123
|
+
{
|
|
124
|
+
message:
|
|
125
|
+
'Replace lastReturnedWith() with its canonical name of toHaveLastReturnedWith()',
|
|
126
|
+
column: 11,
|
|
127
|
+
line: 1,
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
output: 'expect(a).toHaveLastReturnedWith()',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
code: 'expect(a).nthReturnedWith()',
|
|
134
|
+
errors: [
|
|
135
|
+
{
|
|
136
|
+
message:
|
|
137
|
+
'Replace nthReturnedWith() with its canonical name of toHaveNthReturnedWith()',
|
|
138
|
+
column: 11,
|
|
139
|
+
line: 1,
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
output: 'expect(a).toHaveNthReturnedWith()',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
code: 'expect(a).toThrowError()',
|
|
146
|
+
errors: [
|
|
147
|
+
{
|
|
148
|
+
message:
|
|
149
|
+
'Replace toThrowError() with its canonical name of toThrow()',
|
|
150
|
+
column: 11,
|
|
151
|
+
line: 1,
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
output: 'expect(a).toThrow()',
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
});
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
const RuleTester = require('eslint').RuleTester;
|
|
4
4
|
const rule = require('../no-disabled-tests');
|
|
5
5
|
|
|
6
|
-
const ruleTester = new RuleTester(
|
|
6
|
+
const ruleTester = new RuleTester({
|
|
7
|
+
parserOptions: {
|
|
8
|
+
sourceType: 'module',
|
|
9
|
+
},
|
|
10
|
+
});
|
|
7
11
|
|
|
8
12
|
ruleTester.run('no-disabled-tests', rule, {
|
|
9
13
|
valid: [
|
|
@@ -17,6 +21,35 @@ ruleTester.run('no-disabled-tests', rule, {
|
|
|
17
21
|
'var calledSkip = it.skip; calledSkip.call(it)',
|
|
18
22
|
'({ f: function () {} }).f()',
|
|
19
23
|
'(a || b).f()',
|
|
24
|
+
[
|
|
25
|
+
'import { pending } from "actions"',
|
|
26
|
+
'',
|
|
27
|
+
'test("foo", () => {',
|
|
28
|
+
' expect(pending()).toEqual({})',
|
|
29
|
+
'})',
|
|
30
|
+
].join('\n'),
|
|
31
|
+
[
|
|
32
|
+
'const { pending } = require("actions")',
|
|
33
|
+
'',
|
|
34
|
+
'test("foo", () => {',
|
|
35
|
+
' expect(pending()).toEqual({})',
|
|
36
|
+
'})',
|
|
37
|
+
].join('\n'),
|
|
38
|
+
[
|
|
39
|
+
'test("foo", () => {',
|
|
40
|
+
' const pending = getPending()',
|
|
41
|
+
' expect(pending()).toEqual({})',
|
|
42
|
+
'})',
|
|
43
|
+
].join('\n'),
|
|
44
|
+
[
|
|
45
|
+
'test("foo", () => {',
|
|
46
|
+
' expect(pending()).toEqual({})',
|
|
47
|
+
'})',
|
|
48
|
+
'',
|
|
49
|
+
'function pending() {',
|
|
50
|
+
' return {}',
|
|
51
|
+
'}',
|
|
52
|
+
].join('\n'),
|
|
20
53
|
],
|
|
21
54
|
|
|
22
55
|
invalid: [
|
|
@@ -6,7 +6,10 @@ const rule = require('../prefer-strict-equal');
|
|
|
6
6
|
const ruleTester = new RuleTester();
|
|
7
7
|
|
|
8
8
|
ruleTester.run('prefer-strict-equal', rule, {
|
|
9
|
-
valid: [
|
|
9
|
+
valid: [
|
|
10
|
+
'expect(something).toStrictEqual(somethingElse);',
|
|
11
|
+
"a().toEqual('b')",
|
|
12
|
+
],
|
|
10
13
|
invalid: [
|
|
11
14
|
{
|
|
12
15
|
code: 'expect(something).toEqual(somethingElse);',
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const RuleTester = require('eslint').RuleTester;
|
|
4
|
+
const rule = require('../require-tothrow-message');
|
|
5
|
+
|
|
6
|
+
const ruleTester = new RuleTester({
|
|
7
|
+
parserOptions: {
|
|
8
|
+
ecmaVersion: 6,
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
ruleTester.run('require-tothrow-message', rule, {
|
|
13
|
+
valid: [
|
|
14
|
+
// String
|
|
15
|
+
"expect(() => { throw new Error('a'); }).toThrow('a');",
|
|
16
|
+
"expect(() => { throw new Error('a'); }).toThrowError('a');",
|
|
17
|
+
|
|
18
|
+
// Template literal
|
|
19
|
+
"const a = 'a'; expect(() => { throw new Error('a'); }).toThrow(`${a}`);",
|
|
20
|
+
|
|
21
|
+
// Regex
|
|
22
|
+
"expect(() => { throw new Error('a'); }).toThrow(/^a$/);",
|
|
23
|
+
|
|
24
|
+
// Function
|
|
25
|
+
"expect(() => { throw new Error('a'); })" +
|
|
26
|
+
".toThrow((() => { return 'a'; })());",
|
|
27
|
+
|
|
28
|
+
// Allow no message for `not`.
|
|
29
|
+
"expect(() => { throw new Error('a'); }).not.toThrow();",
|
|
30
|
+
],
|
|
31
|
+
|
|
32
|
+
invalid: [
|
|
33
|
+
// Empty toThrow
|
|
34
|
+
{
|
|
35
|
+
code: "expect(() => { throw new Error('a'); }).toThrow();",
|
|
36
|
+
errors: [
|
|
37
|
+
{ message: 'Add an error message to toThrow()', column: 41, line: 1 },
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
// Empty toThrowError
|
|
41
|
+
{
|
|
42
|
+
code: "expect(() => { throw new Error('a'); }).toThrowError();",
|
|
43
|
+
errors: [
|
|
44
|
+
{
|
|
45
|
+
message: 'Add an error message to toThrowError()',
|
|
46
|
+
column: 41,
|
|
47
|
+
line: 1,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
});
|
package/rules/expect-expect.js
CHANGED
|
@@ -12,10 +12,26 @@ module.exports = {
|
|
|
12
12
|
docs: {
|
|
13
13
|
url: getDocsUrl(__filename),
|
|
14
14
|
},
|
|
15
|
+
schema: [
|
|
16
|
+
{
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
assertFunctionNames: {
|
|
20
|
+
type: 'array',
|
|
21
|
+
items: [{ type: 'string' }],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
additionalProperties: false,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
15
27
|
},
|
|
16
28
|
create(context) {
|
|
17
29
|
// variables should be defined here
|
|
18
30
|
const unchecked = [];
|
|
31
|
+
const assertFunctionNames =
|
|
32
|
+
context.options[0] && context.options[0].assertFunctionNames
|
|
33
|
+
? context.options[0].assertFunctionNames
|
|
34
|
+
: ['expect'];
|
|
19
35
|
|
|
20
36
|
//----------------------------------------------------------------------
|
|
21
37
|
// Helpers
|
|
@@ -23,8 +39,8 @@ module.exports = {
|
|
|
23
39
|
const isExpectCall = node =>
|
|
24
40
|
// if we're not calling a function, ignore
|
|
25
41
|
node.type === 'CallExpression' &&
|
|
26
|
-
// if we're not calling
|
|
27
|
-
node.callee.name
|
|
42
|
+
// if we're not calling allowed assertion
|
|
43
|
+
assertFunctionNames.some(name => name === node.callee.name);
|
|
28
44
|
//----------------------------------------------------------------------
|
|
29
45
|
// Public
|
|
30
46
|
//----------------------------------------------------------------------
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const expectCase = require('./util').expectCase;
|
|
4
|
+
const getDocsUrl = require('./util').getDocsUrl;
|
|
5
|
+
const method = require('./util').method;
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
meta: {
|
|
9
|
+
docs: {
|
|
10
|
+
url: getDocsUrl(__filename),
|
|
11
|
+
},
|
|
12
|
+
fixable: 'code',
|
|
13
|
+
},
|
|
14
|
+
create(context) {
|
|
15
|
+
// The Jest methods which have aliases. The canonical name is the first
|
|
16
|
+
// index of each item.
|
|
17
|
+
const methodNames = [
|
|
18
|
+
['toHaveBeenCalled', 'toBeCalled'],
|
|
19
|
+
['toHaveBeenCalledTimes', 'toBeCalledTimes'],
|
|
20
|
+
['toHaveBeenCalledWith', 'toBeCalledWith'],
|
|
21
|
+
['toHaveBeenLastCalledWith', 'lastCalledWith'],
|
|
22
|
+
['toHaveBeenNthCalledWith', 'nthCalledWith'],
|
|
23
|
+
['toHaveReturned', 'toReturn'],
|
|
24
|
+
['toHaveReturnedTimes', 'toReturnTimes'],
|
|
25
|
+
['toHaveReturnedWith', 'toReturnWith'],
|
|
26
|
+
['toHaveLastReturnedWith', 'lastReturnedWith'],
|
|
27
|
+
['toHaveNthReturnedWith', 'nthReturnedWith'],
|
|
28
|
+
['toThrow', 'toThrowError'],
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
CallExpression(node) {
|
|
33
|
+
if (!expectCase(node)) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Check if the method used matches any of ours.
|
|
38
|
+
const propertyName = method(node) && method(node).name;
|
|
39
|
+
const methodItem = methodNames.find(item => item[1] === propertyName);
|
|
40
|
+
|
|
41
|
+
if (methodItem) {
|
|
42
|
+
context.report({
|
|
43
|
+
message: `Replace {{ replace }}() with its canonical name of {{ canonical }}()`,
|
|
44
|
+
data: {
|
|
45
|
+
replace: methodItem[1],
|
|
46
|
+
canonical: methodItem[0],
|
|
47
|
+
},
|
|
48
|
+
node: method(node),
|
|
49
|
+
fix(fixer) {
|
|
50
|
+
return [fixer.replaceText(method(node), methodItem[0])];
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -19,6 +19,33 @@ function getName(node) {
|
|
|
19
19
|
return null;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function collectReferences(scope) {
|
|
23
|
+
const locals = new Set();
|
|
24
|
+
const unresolved = new Set();
|
|
25
|
+
|
|
26
|
+
let currentScope = scope;
|
|
27
|
+
|
|
28
|
+
while (currentScope !== null) {
|
|
29
|
+
for (const ref of currentScope.variables) {
|
|
30
|
+
const isReferenceDefined = ref.defs.some(def => {
|
|
31
|
+
return def.type !== 'ImplicitGlobalVariable';
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (isReferenceDefined) {
|
|
35
|
+
locals.add(ref.name);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
for (const ref of currentScope.through) {
|
|
40
|
+
unresolved.add(ref.identifier.name);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
currentScope = currentScope.upper;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { locals, unresolved };
|
|
47
|
+
}
|
|
48
|
+
|
|
22
49
|
module.exports = {
|
|
23
50
|
meta: {
|
|
24
51
|
docs: {
|
|
@@ -58,7 +85,19 @@ module.exports = {
|
|
|
58
85
|
context.report({ message: 'Skipped test', node });
|
|
59
86
|
break;
|
|
60
87
|
|
|
61
|
-
case 'pending':
|
|
88
|
+
case 'pending': {
|
|
89
|
+
const references = collectReferences(context.getScope());
|
|
90
|
+
|
|
91
|
+
if (
|
|
92
|
+
// `pending` was found as a local variable or function declaration.
|
|
93
|
+
references.locals.has('pending') ||
|
|
94
|
+
// `pending` was not found as an unresolved reference,
|
|
95
|
+
// meaning it is likely not an implicit global reference.
|
|
96
|
+
!references.unresolved.has('pending')
|
|
97
|
+
) {
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
|
|
62
101
|
if (testDepth > 0) {
|
|
63
102
|
context.report({
|
|
64
103
|
message: 'Call to pending() within test',
|
|
@@ -76,6 +115,7 @@ module.exports = {
|
|
|
76
115
|
});
|
|
77
116
|
}
|
|
78
117
|
break;
|
|
118
|
+
}
|
|
79
119
|
|
|
80
120
|
case 'xdescribe':
|
|
81
121
|
context.report({ message: 'Disabled test suite', node });
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const expectCase = require('./util').expectCase;
|
|
3
4
|
const getDocsUrl = require('./util').getDocsUrl;
|
|
5
|
+
const method = require('./util').method;
|
|
4
6
|
|
|
5
7
|
module.exports = {
|
|
6
8
|
meta: {
|
|
@@ -12,14 +14,19 @@ module.exports = {
|
|
|
12
14
|
create(context) {
|
|
13
15
|
return {
|
|
14
16
|
CallExpression(node) {
|
|
15
|
-
|
|
17
|
+
if (!expectCase(node)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const propertyName = method(node) && method(node).name;
|
|
22
|
+
|
|
16
23
|
if (propertyName === 'toEqual') {
|
|
17
24
|
context.report({
|
|
18
25
|
fix(fixer) {
|
|
19
|
-
return [fixer.replaceText(node
|
|
26
|
+
return [fixer.replaceText(method(node), 'toStrictEqual')];
|
|
20
27
|
},
|
|
21
28
|
message: 'Use toStrictEqual() instead',
|
|
22
|
-
node: node
|
|
29
|
+
node: method(node),
|
|
23
30
|
});
|
|
24
31
|
}
|
|
25
32
|
},
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const argument = require('./util').argument;
|
|
4
|
+
const expectCase = require('./util').expectCase;
|
|
5
|
+
const getDocsUrl = require('./util').getDocsUrl;
|
|
6
|
+
const method = require('./util').method;
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
meta: {
|
|
10
|
+
docs: {
|
|
11
|
+
url: getDocsUrl(__filename),
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
create(context) {
|
|
15
|
+
return {
|
|
16
|
+
CallExpression(node) {
|
|
17
|
+
if (!expectCase(node)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const propertyName = method(node) && method(node).name;
|
|
22
|
+
|
|
23
|
+
// Look for `toThrow` calls with no arguments.
|
|
24
|
+
if (
|
|
25
|
+
['toThrow', 'toThrowError'].indexOf(propertyName) > -1 &&
|
|
26
|
+
!argument(node)
|
|
27
|
+
) {
|
|
28
|
+
context.report({
|
|
29
|
+
message: `Add an error message to {{ propertyName }}()`,
|
|
30
|
+
data: {
|
|
31
|
+
propertyName,
|
|
32
|
+
},
|
|
33
|
+
node: method(node),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
};
|