eslint-plugin-jest 23.3.0 → 23.7.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 +45 -0
- package/README.md +3 -3
- package/docs/rules/expect-expect.md +24 -1
- package/docs/rules/valid-title.md +45 -3
- package/lib/rules/consistent-test-it.js +8 -20
- package/lib/rules/expect-expect.js +35 -9
- package/lib/rules/lowercase-name.js +8 -29
- package/lib/rules/no-commented-out-tests.js +1 -1
- package/lib/rules/no-expect-resolves.js +1 -11
- package/lib/rules/no-export.js +1 -1
- package/lib/rules/no-if.js +19 -9
- package/lib/rules/no-jasmine-globals.js +2 -2
- package/lib/rules/no-large-snapshots.js +2 -2
- package/lib/rules/no-standalone-expect.js +1 -7
- package/lib/rules/no-test-callback.js +3 -1
- package/lib/rules/no-test-return-statement.js +16 -5
- package/lib/rules/no-truthy-falsy.js +5 -7
- package/lib/rules/no-try-expect.js +18 -0
- package/lib/rules/prefer-expect-assertions.js +1 -1
- package/lib/rules/prefer-todo.js +16 -16
- package/lib/rules/utils.js +17 -1
- package/lib/rules/valid-expect.js +39 -49
- package/lib/rules/valid-title.js +33 -15
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,48 @@
|
|
|
1
|
+
# [23.7.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.6.0...v23.7.0) (2020-02-07)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **expect-expect:** use `u` flag in regex
|
|
6
|
+
([#532](https://github.com/jest-community/eslint-plugin-jest/issues/532))
|
|
7
|
+
([c12b725](https://github.com/jest-community/eslint-plugin-jest/commit/c12b7251ef1506073d268973b93c7fc9fbcf50af))
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
- **valid-title:** support `disallowedWords` option
|
|
12
|
+
([#522](https://github.com/jest-community/eslint-plugin-jest/issues/522))
|
|
13
|
+
([38bbe93](https://github.com/jest-community/eslint-plugin-jest/commit/38bbe93794ed456c6e9e5d7be848b2aeb55ce0ba))
|
|
14
|
+
|
|
15
|
+
# [23.6.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.5.0...v23.6.0) (2020-01-12)
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
- **no-if:** support `switch` statements
|
|
20
|
+
([#515](https://github.com/jest-community/eslint-plugin-jest/issues/515))
|
|
21
|
+
([be4e49d](https://github.com/jest-community/eslint-plugin-jest/commit/be4e49dcecd64711e743f5e09d1ff24e4c6e1648))
|
|
22
|
+
|
|
23
|
+
# [23.5.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.4.0...v23.5.0) (2020-01-12)
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
- **expect-expect:** support glob patterns for assertFunctionNames
|
|
28
|
+
([#509](https://github.com/jest-community/eslint-plugin-jest/issues/509))
|
|
29
|
+
([295ca9a](https://github.com/jest-community/eslint-plugin-jest/commit/295ca9a6969c77fadaa1a42d76e89cae992520a6))
|
|
30
|
+
- **valid-expect:** refactor `valid-expect` linting messages
|
|
31
|
+
([#501](https://github.com/jest-community/eslint-plugin-jest/issues/501))
|
|
32
|
+
([7338362](https://github.com/jest-community/eslint-plugin-jest/commit/7338362420eb4970f99be2016bb4ded5732797e3))
|
|
33
|
+
|
|
34
|
+
# [23.4.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.3.0...v23.4.0) (2020-01-10)
|
|
35
|
+
|
|
36
|
+
### Features
|
|
37
|
+
|
|
38
|
+
- **expect-expect:** support chained function names
|
|
39
|
+
([#471](https://github.com/jest-community/eslint-plugin-jest/issues/471))
|
|
40
|
+
([#508](https://github.com/jest-community/eslint-plugin-jest/issues/508))
|
|
41
|
+
([beb1aec](https://github.com/jest-community/eslint-plugin-jest/commit/beb1aececee80589c182e95bc64ef01d97eb5e78))
|
|
42
|
+
- **rules:** add support for function declaration as test case
|
|
43
|
+
([#504](https://github.com/jest-community/eslint-plugin-jest/issues/504))
|
|
44
|
+
([ac7fa48](https://github.com/jest-community/eslint-plugin-jest/commit/ac7fa487d05705bee1b2d5264d5096f0232ae1e1))
|
|
45
|
+
|
|
1
46
|
# [23.3.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.2.0...v23.3.0) (2020-01-04)
|
|
2
47
|
|
|
3
48
|
### Features
|
package/README.md
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
[](https://github.com/jest-community/eslint-plugin-jest/actions)
|
|
2
|
-
[](https://renovatebot.com/)
|
|
3
|
-
|
|
4
1
|
<div align="center">
|
|
5
2
|
<a href="https://eslint.org/">
|
|
6
3
|
<img width="150" height="150" src="https://eslint.org/assets/img/logo.svg">
|
|
@@ -12,6 +9,9 @@
|
|
|
12
9
|
<p>ESLint plugin for Jest</p>
|
|
13
10
|
</div>
|
|
14
11
|
|
|
12
|
+
[](https://github.com/jest-community/eslint-plugin-jest/actions)
|
|
13
|
+
[](https://renovatebot.com/)
|
|
14
|
+
|
|
15
15
|
## Installation
|
|
16
16
|
|
|
17
17
|
```
|
|
@@ -42,7 +42,9 @@ it('should work with callbacks/async', () => {
|
|
|
42
42
|
|
|
43
43
|
### `assertFunctionNames`
|
|
44
44
|
|
|
45
|
-
This array option whitelists the assertion function names to look for.
|
|
45
|
+
This array option whitelists the assertion function names to look for. Function
|
|
46
|
+
names can use wildcards like `request.*.expect`, `request.**.expect`,
|
|
47
|
+
`request.*.expect*`
|
|
46
48
|
|
|
47
49
|
Examples of **incorrect** code for the `{ "assertFunctionNames": ["expect"] }`
|
|
48
50
|
option:
|
|
@@ -75,3 +77,24 @@ test('returns sum', () =>
|
|
|
75
77
|
.run();
|
|
76
78
|
);
|
|
77
79
|
```
|
|
80
|
+
|
|
81
|
+
Examples of **correct** code for working with the HTTP assertions library
|
|
82
|
+
[SuperTest](https://www.npmjs.com/package/supertest) with the
|
|
83
|
+
`{ "assertFunctionNames": ["expect", "request.*.expect"] }` option:
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "request.*.expect"] }] */
|
|
87
|
+
const request = require('supertest');
|
|
88
|
+
const express = require('express');
|
|
89
|
+
|
|
90
|
+
const app = express();
|
|
91
|
+
|
|
92
|
+
describe('GET /user', function() {
|
|
93
|
+
it('responds with json', function(done) {
|
|
94
|
+
request(app)
|
|
95
|
+
.get('/user')
|
|
96
|
+
.expect('Content-Type', /json/)
|
|
97
|
+
.expect(200, done);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
```
|
|
@@ -45,7 +45,7 @@ xtest('foo', () => {});
|
|
|
45
45
|
|
|
46
46
|
Titles for test blocks should always be a string literal or expression.
|
|
47
47
|
|
|
48
|
-
This is also applied to describe blocks by default, but can be turned off via
|
|
48
|
+
This is also applied to `describe` blocks by default, but can be turned off via
|
|
49
49
|
the `ignoreTypeOfDescribeName` option:
|
|
50
50
|
|
|
51
51
|
Examples of **incorrect** code for this rule:
|
|
@@ -87,7 +87,7 @@ describe(6, function() {});
|
|
|
87
87
|
|
|
88
88
|
**duplicatePrefix**
|
|
89
89
|
|
|
90
|
-
A describe/ test block should not start with duplicatePrefix
|
|
90
|
+
A `describe` / `test` block should not start with `duplicatePrefix`
|
|
91
91
|
|
|
92
92
|
Examples of **incorrect** code for this rule
|
|
93
93
|
|
|
@@ -117,7 +117,7 @@ describe('foo', () => {
|
|
|
117
117
|
|
|
118
118
|
**accidentalSpace**
|
|
119
119
|
|
|
120
|
-
A describe/ test block should not contain accidentalSpace
|
|
120
|
+
A `describe` / `test` block should not contain accidentalSpace
|
|
121
121
|
|
|
122
122
|
Examples of **incorrect** code for this rule
|
|
123
123
|
|
|
@@ -148,3 +148,45 @@ describe('foo', () => {
|
|
|
148
148
|
test('bar', () => {});
|
|
149
149
|
});
|
|
150
150
|
```
|
|
151
|
+
|
|
152
|
+
## Options
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
interface {
|
|
156
|
+
ignoreTypeOfDescribeName?: boolean;
|
|
157
|
+
disallowedWords?: string[];
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### `ignoreTypeOfDescribeName`
|
|
162
|
+
|
|
163
|
+
Default: `false`
|
|
164
|
+
|
|
165
|
+
When enabled, the type of the first argument to `describe` blocks won't be
|
|
166
|
+
checked.
|
|
167
|
+
|
|
168
|
+
#### `disallowedWords`
|
|
169
|
+
|
|
170
|
+
Default: `[]`
|
|
171
|
+
|
|
172
|
+
A string array of words that are not allowed to be used in test titles. Matching
|
|
173
|
+
is not case-sensitive, and looks for complete words:
|
|
174
|
+
|
|
175
|
+
Examples of **incorrect** code using `disallowedWords`:
|
|
176
|
+
|
|
177
|
+
```js
|
|
178
|
+
// with disallowedWords: ['correct', 'all', 'every', 'properly']
|
|
179
|
+
describe('the correct way to do things', () => {});
|
|
180
|
+
it('has ALL the things', () => {});
|
|
181
|
+
xdescribe('every single one of them', () => {});
|
|
182
|
+
test(`that the value is set properly`, () => {});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Examples of **correct** code when using `disallowedWords`:
|
|
186
|
+
|
|
187
|
+
```js
|
|
188
|
+
// with disallowedWords: ['correct', 'all', 'every', 'properly']
|
|
189
|
+
it('correctly sets the value', () => {});
|
|
190
|
+
test('that everything is as it should be', () => {});
|
|
191
|
+
describe('the proper way to handle things', () => {});
|
|
192
|
+
```
|
|
@@ -9,6 +9,8 @@ var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
|
9
9
|
|
|
10
10
|
var _utils = require("./utils");
|
|
11
11
|
|
|
12
|
+
const buildFixer = (callee, nodeName, preferredTestKeyword) => fixer => [fixer.replaceText(callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression ? callee.object : callee, getPreferredNodeName(nodeName, preferredTestKeyword))];
|
|
13
|
+
|
|
12
14
|
var _default = (0, _utils.createRule)({
|
|
13
15
|
name: __filename,
|
|
14
16
|
meta: {
|
|
@@ -67,13 +69,7 @@ var _default = (0, _utils.createRule)({
|
|
|
67
69
|
testKeyword,
|
|
68
70
|
oppositeTestKeyword
|
|
69
71
|
},
|
|
70
|
-
|
|
71
|
-
fix(fixer) {
|
|
72
|
-
const nodeToReplace = node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression ? node.callee.object : node.callee;
|
|
73
|
-
const fixedNodeName = getPreferredNodeName(nodeName, testKeyword);
|
|
74
|
-
return [fixer.replaceText(nodeToReplace, fixedNodeName)];
|
|
75
|
-
}
|
|
76
|
-
|
|
72
|
+
fix: buildFixer(node.callee, nodeName, testKeyword)
|
|
77
73
|
});
|
|
78
74
|
}
|
|
79
75
|
|
|
@@ -86,13 +82,7 @@ var _default = (0, _utils.createRule)({
|
|
|
86
82
|
testKeywordWithinDescribe,
|
|
87
83
|
oppositeTestKeyword
|
|
88
84
|
},
|
|
89
|
-
|
|
90
|
-
fix(fixer) {
|
|
91
|
-
const nodeToReplace = node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression ? node.callee.object : node.callee;
|
|
92
|
-
const fixedNodeName = getPreferredNodeName(nodeName, testKeywordWithinDescribe);
|
|
93
|
-
return [fixer.replaceText(nodeToReplace, fixedNodeName)];
|
|
94
|
-
}
|
|
95
|
-
|
|
85
|
+
fix: buildFixer(node.callee, nodeName, testKeywordWithinDescribe)
|
|
96
86
|
});
|
|
97
87
|
}
|
|
98
88
|
},
|
|
@@ -111,13 +101,11 @@ var _default = (0, _utils.createRule)({
|
|
|
111
101
|
exports.default = _default;
|
|
112
102
|
|
|
113
103
|
function getPreferredNodeName(nodeName, preferredTestKeyword) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return 'test.only';
|
|
117
|
-
|
|
118
|
-
default:
|
|
119
|
-
return nodeName.startsWith('f') || nodeName.startsWith('x') ? nodeName.charAt(0) + preferredTestKeyword : preferredTestKeyword;
|
|
104
|
+
if (nodeName === _utils.TestCaseName.fit) {
|
|
105
|
+
return 'test.only';
|
|
120
106
|
}
|
|
107
|
+
|
|
108
|
+
return nodeName.startsWith('f') || nodeName.startsWith('x') ? nodeName.charAt(0) + preferredTestKeyword : preferredTestKeyword;
|
|
121
109
|
}
|
|
122
110
|
|
|
123
111
|
function getOppositeTestKeyword(test) {
|
|
@@ -13,6 +13,21 @@ var _utils = require("./utils");
|
|
|
13
13
|
* This implementation is adapted from eslint-plugin-jasmine.
|
|
14
14
|
* MIT license, Remco Haszing.
|
|
15
15
|
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Checks if node names returned by getNodeName matches any of the given star patterns
|
|
19
|
+
* Pattern examples:
|
|
20
|
+
* request.*.expect
|
|
21
|
+
* request.**.expect
|
|
22
|
+
* request.**.expect*
|
|
23
|
+
*/
|
|
24
|
+
function matchesAssertFunctionName(nodeName, patterns) {
|
|
25
|
+
return patterns.some(p => new RegExp(`^${p.split('.').map(x => {
|
|
26
|
+
if (x === '**') return '[a-z\\.]*';
|
|
27
|
+
return x.replace(/\*/gu, '[a-z]*');
|
|
28
|
+
}).join('\\.')}(\\.|$)`, 'ui').test(nodeName));
|
|
29
|
+
}
|
|
30
|
+
|
|
16
31
|
var _default = (0, _utils.createRule)({
|
|
17
32
|
name: __filename,
|
|
18
33
|
meta: {
|
|
@@ -46,22 +61,33 @@ var _default = (0, _utils.createRule)({
|
|
|
46
61
|
assertFunctionNames = ['expect']
|
|
47
62
|
}]) {
|
|
48
63
|
const unchecked = [];
|
|
64
|
+
|
|
65
|
+
function checkCallExpressionUsed(nodes) {
|
|
66
|
+
for (const node of nodes) {
|
|
67
|
+
const index = node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? unchecked.indexOf(node) : -1;
|
|
68
|
+
|
|
69
|
+
if (node.type === _experimentalUtils.AST_NODE_TYPES.FunctionDeclaration) {
|
|
70
|
+
const declaredVariables = context.getDeclaredVariables(node);
|
|
71
|
+
const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
|
|
72
|
+
checkCallExpressionUsed(testCallExpressions);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (index !== -1) {
|
|
76
|
+
unchecked.splice(index, 1);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
49
82
|
return {
|
|
50
83
|
CallExpression(node) {
|
|
51
84
|
const name = (0, _utils.getNodeName)(node.callee);
|
|
52
85
|
|
|
53
86
|
if (name === _utils.TestCaseName.it || name === _utils.TestCaseName.test) {
|
|
54
87
|
unchecked.push(node);
|
|
55
|
-
} else if (name &&
|
|
88
|
+
} else if (name && matchesAssertFunctionName(name, assertFunctionNames)) {
|
|
56
89
|
// Return early in case of nested `it` statements.
|
|
57
|
-
|
|
58
|
-
const index = ancestor.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? unchecked.indexOf(ancestor) : -1;
|
|
59
|
-
|
|
60
|
-
if (index !== -1) {
|
|
61
|
-
unchecked.splice(index, 1);
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
90
|
+
checkCallExpressionUsed(context.getAncestors());
|
|
65
91
|
}
|
|
66
92
|
},
|
|
67
93
|
|
|
@@ -9,44 +9,24 @@ var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
|
9
9
|
|
|
10
10
|
var _utils = require("./utils");
|
|
11
11
|
|
|
12
|
-
const hasStringAsFirstArgument = node => node.arguments
|
|
12
|
+
const hasStringAsFirstArgument = node => node.arguments[0] && (0, _utils.isStringNode)(node.arguments[0]);
|
|
13
13
|
|
|
14
14
|
const isJestFunctionWithLiteralArg = node => ((0, _utils.isTestCase)(node) || (0, _utils.isDescribe)(node)) && node.callee.type === _experimentalUtils.AST_NODE_TYPES.Identifier && hasStringAsFirstArgument(node);
|
|
15
15
|
|
|
16
|
-
const testDescription = argument => {
|
|
17
|
-
if (argument.type === _experimentalUtils.AST_NODE_TYPES.Literal) {
|
|
18
|
-
const {
|
|
19
|
-
value
|
|
20
|
-
} = argument;
|
|
21
|
-
|
|
22
|
-
if (typeof value === 'string') {
|
|
23
|
-
return value;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return argument.quasis[0].value.raw;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
16
|
const jestFunctionName = (node, allowedPrefixes) => {
|
|
33
|
-
const description =
|
|
17
|
+
const description = (0, _utils.getStringValue)(node.arguments[0]);
|
|
34
18
|
|
|
35
|
-
if (
|
|
19
|
+
if (allowedPrefixes.some(name => description.startsWith(name))) {
|
|
36
20
|
return null;
|
|
37
21
|
}
|
|
38
22
|
|
|
39
23
|
const firstCharacter = description.charAt(0);
|
|
40
24
|
|
|
41
|
-
if (!firstCharacter) {
|
|
25
|
+
if (!firstCharacter || firstCharacter === firstCharacter.toLowerCase()) {
|
|
42
26
|
return null;
|
|
43
27
|
}
|
|
44
28
|
|
|
45
|
-
|
|
46
|
-
return node.callee.name;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return null;
|
|
29
|
+
return node.callee.name;
|
|
50
30
|
};
|
|
51
31
|
|
|
52
32
|
var _default = (0, _utils.createRule)({
|
|
@@ -103,15 +83,14 @@ var _default = (0, _utils.createRule)({
|
|
|
103
83
|
if (erroneousMethod && !ignore.includes(node.callee.name)) {
|
|
104
84
|
context.report({
|
|
105
85
|
messageId: 'unexpectedLowercase',
|
|
86
|
+
node: node.arguments[0],
|
|
106
87
|
data: {
|
|
107
88
|
method: erroneousMethod
|
|
108
89
|
},
|
|
109
|
-
node,
|
|
110
90
|
|
|
111
91
|
fix(fixer) {
|
|
112
|
-
const [firstArg] = node.arguments;
|
|
113
|
-
|
|
114
|
-
const description = testDescription(firstArg);
|
|
92
|
+
const [firstArg] = node.arguments;
|
|
93
|
+
const description = (0, _utils.getStringValue)(firstArg);
|
|
115
94
|
const rangeIgnoringQuotes = [firstArg.range[0] + 1, firstArg.range[1] - 1];
|
|
116
95
|
const newDescription = description.substring(0, 1).toLowerCase() + description.substring(1);
|
|
117
96
|
return [fixer.replaceTextRange(rangeIgnoringQuotes, newDescription)];
|
|
@@ -8,7 +8,7 @@ exports.default = void 0;
|
|
|
8
8
|
var _utils = require("./utils");
|
|
9
9
|
|
|
10
10
|
function hasTests(node) {
|
|
11
|
-
return /^\s*[xf]?(test|it|describe)(\.\w+|\[['"]\w+['"]\])?\s*\(/
|
|
11
|
+
return /^\s*[xf]?(test|it|describe)(\.\w+|\[['"]\w+['"]\])?\s*\(/mu.test(node.value);
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
var _default = (0, _utils.createRule)({
|
|
@@ -5,18 +5,8 @@ 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
|
-
function isIdentifierResolves(node) {
|
|
13
|
-
return node.property.type === _experimentalUtils.AST_NODE_TYPES.Identifier && node.property.name === 'resolves';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function isExpectResolves(node) {
|
|
17
|
-
return (0, _utils.isExpectCall)(node.object) && isIdentifierResolves(node);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
10
|
var _default = (0, _utils.createRule)({
|
|
21
11
|
name: __filename,
|
|
22
12
|
meta: {
|
|
@@ -34,7 +24,7 @@ var _default = (0, _utils.createRule)({
|
|
|
34
24
|
defaultOptions: [],
|
|
35
25
|
create: context => ({
|
|
36
26
|
MemberExpression(node) {
|
|
37
|
-
if (
|
|
27
|
+
if ((0, _utils.isExpectCall)(node.object) && (0, _utils.isSupportedAccessor)(node.property, _utils.ModifierName.resolves)) {
|
|
38
28
|
context.report({
|
|
39
29
|
node: node.property,
|
|
40
30
|
messageId: 'expectResolves'
|
package/lib/rules/no-export.js
CHANGED
|
@@ -63,7 +63,7 @@ var _default = (0, _utils.createRule)({
|
|
|
63
63
|
} = object);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
if ('name' in object && object.name === 'module' && property.type === _experimentalUtils.AST_NODE_TYPES.Identifier && /^exports
|
|
66
|
+
if ('name' in object && object.name === 'module' && property.type === _experimentalUtils.AST_NODE_TYPES.Identifier && /^exports?$/u.test(property.name)) {
|
|
67
67
|
exportNodes.push(node);
|
|
68
68
|
}
|
|
69
69
|
}
|
package/lib/rules/no-if.js
CHANGED
|
@@ -5,14 +5,20 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
var _utils = require("./utils");
|
|
9
|
-
|
|
10
8
|
var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
11
9
|
|
|
10
|
+
var _utils = require("./utils");
|
|
11
|
+
|
|
12
12
|
const testCaseNames = new Set([...Object.keys(_utils.TestCaseName), 'it.only', 'it.concurrent.only', 'it.skip', 'it.concurrent.skip', 'test.only', 'test.concurrent.only', 'test.skip', 'test.concurrent.skip', 'fit.concurrent']);
|
|
13
13
|
|
|
14
14
|
const isTestArrowFunction = node => node.parent !== undefined && node.parent.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && testCaseNames.has((0, _utils.getNodeName)(node.parent.callee));
|
|
15
15
|
|
|
16
|
+
const conditionName = {
|
|
17
|
+
[_experimentalUtils.AST_NODE_TYPES.ConditionalExpression]: 'conditional',
|
|
18
|
+
[_experimentalUtils.AST_NODE_TYPES.SwitchStatement]: 'switch',
|
|
19
|
+
[_experimentalUtils.AST_NODE_TYPES.IfStatement]: 'if'
|
|
20
|
+
};
|
|
21
|
+
|
|
16
22
|
var _default = (0, _utils.createRule)({
|
|
17
23
|
name: __filename,
|
|
18
24
|
meta: {
|
|
@@ -22,8 +28,7 @@ var _default = (0, _utils.createRule)({
|
|
|
22
28
|
recommended: false
|
|
23
29
|
},
|
|
24
30
|
messages: {
|
|
25
|
-
|
|
26
|
-
noConditional: 'Tests should not contain conditional statements.'
|
|
31
|
+
noConditionalExpect: 'Test should not contain { condition } statements.'
|
|
27
32
|
},
|
|
28
33
|
schema: [],
|
|
29
34
|
type: 'suggestion'
|
|
@@ -36,13 +41,15 @@ var _default = (0, _utils.createRule)({
|
|
|
36
41
|
function validate(node) {
|
|
37
42
|
const lastElementInStack = stack[stack.length - 1];
|
|
38
43
|
|
|
39
|
-
if (stack.length === 0 || lastElementInStack
|
|
44
|
+
if (stack.length === 0 || !lastElementInStack) {
|
|
40
45
|
return;
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
const messageId = node.type === _experimentalUtils.AST_NODE_TYPES.ConditionalExpression ? 'noConditional' : 'noIf';
|
|
44
48
|
context.report({
|
|
45
|
-
|
|
49
|
+
data: {
|
|
50
|
+
condition: conditionName[node.type]
|
|
51
|
+
},
|
|
52
|
+
messageId: 'noConditionalExpect',
|
|
46
53
|
node
|
|
47
54
|
});
|
|
48
55
|
}
|
|
@@ -56,8 +63,10 @@ var _default = (0, _utils.createRule)({
|
|
|
56
63
|
stack.push(false);
|
|
57
64
|
},
|
|
58
65
|
|
|
59
|
-
FunctionDeclaration() {
|
|
60
|
-
|
|
66
|
+
FunctionDeclaration(node) {
|
|
67
|
+
const declaredVariables = context.getDeclaredVariables(node);
|
|
68
|
+
const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
|
|
69
|
+
stack.push(testCallExpressions.length > 0);
|
|
61
70
|
},
|
|
62
71
|
|
|
63
72
|
ArrowFunctionExpression(node) {
|
|
@@ -65,6 +74,7 @@ var _default = (0, _utils.createRule)({
|
|
|
65
74
|
},
|
|
66
75
|
|
|
67
76
|
IfStatement: validate,
|
|
77
|
+
SwitchStatement: validate,
|
|
68
78
|
ConditionalExpression: validate,
|
|
69
79
|
|
|
70
80
|
'CallExpression:exit'() {
|
|
@@ -127,14 +127,14 @@ var _default = (0, _utils.createRule)({
|
|
|
127
127
|
},
|
|
128
128
|
|
|
129
129
|
MemberExpression(node) {
|
|
130
|
-
if (
|
|
130
|
+
if ((0, _utils.isSupportedAccessor)(node.object, 'jasmine')) {
|
|
131
131
|
const {
|
|
132
132
|
parent,
|
|
133
133
|
property
|
|
134
134
|
} = node;
|
|
135
135
|
|
|
136
136
|
if (parent && parent.type === _experimentalUtils.AST_NODE_TYPES.AssignmentExpression) {
|
|
137
|
-
if (
|
|
137
|
+
if ((0, _utils.isSupportedAccessor)(property, 'DEFAULT_TIMEOUT_INTERVAL')) {
|
|
138
138
|
const {
|
|
139
139
|
right
|
|
140
140
|
} = parent;
|
|
@@ -5,10 +5,10 @@ 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 _path = require("path");
|
|
11
9
|
|
|
10
|
+
var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
11
|
+
|
|
12
12
|
var _utils = require("./utils");
|
|
13
13
|
|
|
14
14
|
const reportOnViolation = (context, node, {
|
|
@@ -38,13 +38,7 @@ const getBlockType = stmt => {
|
|
|
38
38
|
return null;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
const isEach = node =>
|
|
42
|
-
if (node && node.callee && node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee.callee && node.callee.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && node.callee.callee.property && node.callee.callee.property.type === _experimentalUtils.AST_NODE_TYPES.Identifier && node.callee.callee.property.name === 'each' && node.callee.callee.object && node.callee.callee.object.type === _experimentalUtils.AST_NODE_TYPES.Identifier && _utils.TestCaseName.hasOwnProperty(node.callee.callee.object.name)) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return false;
|
|
47
|
-
};
|
|
41
|
+
const isEach = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && node.callee.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && node.callee.callee.property.type === _experimentalUtils.AST_NODE_TYPES.Identifier && node.callee.callee.property.name === 'each' && node.callee.callee.object.type === _experimentalUtils.AST_NODE_TYPES.Identifier && _utils.TestCaseName.hasOwnProperty(node.callee.callee.object.name);
|
|
48
42
|
|
|
49
43
|
var _default = (0, _utils.createRule)({
|
|
50
44
|
name: __filename,
|
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
+
var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
9
|
+
|
|
8
10
|
var _utils = require("./utils");
|
|
9
11
|
|
|
10
12
|
var _default = (0, _utils.createRule)({
|
|
@@ -90,7 +92,7 @@ var _default = (0, _utils.createRule)({
|
|
|
90
92
|
let afterReplacement = ')';
|
|
91
93
|
let replaceBefore = true;
|
|
92
94
|
|
|
93
|
-
if (body.type ===
|
|
95
|
+
if (body.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement) {
|
|
94
96
|
const keyword = 'return';
|
|
95
97
|
beforeReplacement = `${keyword} ${beforeReplacement}{`;
|
|
96
98
|
afterReplacement += '}';
|
|
@@ -5,15 +5,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
const BLOCK_STATEMENT = 'BlockStatement';
|
|
10
|
+
var _utils = require("./utils");
|
|
12
11
|
|
|
13
12
|
const getBody = args => {
|
|
14
13
|
const [, secondArg] = args;
|
|
15
14
|
|
|
16
|
-
if (secondArg && (0, _utils.isFunction)(secondArg) && secondArg.body && secondArg.body.type ===
|
|
15
|
+
if (secondArg && (0, _utils.isFunction)(secondArg) && secondArg.body && secondArg.body.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement) {
|
|
17
16
|
return secondArg.body.body;
|
|
18
17
|
}
|
|
19
18
|
|
|
@@ -41,7 +40,19 @@ var _default = (0, _utils.createRule)({
|
|
|
41
40
|
CallExpression(node) {
|
|
42
41
|
if (!(0, _utils.isTestCase)(node)) return;
|
|
43
42
|
const body = getBody(node.arguments);
|
|
44
|
-
const returnStmt = body.find(t => t.type ===
|
|
43
|
+
const returnStmt = body.find(t => t.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement);
|
|
44
|
+
if (!returnStmt) return;
|
|
45
|
+
context.report({
|
|
46
|
+
messageId: 'noReturnValue',
|
|
47
|
+
node: returnStmt
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
FunctionDeclaration(node) {
|
|
52
|
+
const declaredVariables = context.getDeclaredVariables(node);
|
|
53
|
+
const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
|
|
54
|
+
if (testCallExpressions.length === 0) return;
|
|
55
|
+
const returnStmt = node.body.body.find(t => t.type === _experimentalUtils.AST_NODE_TYPES.ReturnStatement);
|
|
45
56
|
if (!returnStmt) return;
|
|
46
57
|
context.report({
|
|
47
58
|
messageId: 'noReturnValue',
|
|
@@ -17,7 +17,7 @@ var _default = (0, _utils.createRule)({
|
|
|
17
17
|
recommended: false
|
|
18
18
|
},
|
|
19
19
|
messages: {
|
|
20
|
-
|
|
20
|
+
avoidMatcher: 'Avoid {{ matcherName }}'
|
|
21
21
|
},
|
|
22
22
|
type: 'suggestion',
|
|
23
23
|
schema: []
|
|
@@ -40,13 +40,11 @@ var _default = (0, _utils.createRule)({
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
context.report({
|
|
43
|
+
messageId: 'avoidMatcher',
|
|
44
|
+
node: matcher.node.property,
|
|
43
45
|
data: {
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
// todo: rename to 'matcherName'
|
|
47
|
-
messageId: 'avoidMessage',
|
|
48
|
-
// todo: rename to 'avoidMatcher'
|
|
49
|
-
node: matcher.node.property
|
|
46
|
+
matcherName: matcher.name
|
|
47
|
+
}
|
|
50
48
|
});
|
|
51
49
|
}
|
|
52
50
|
|
|
@@ -43,6 +43,15 @@ var _default = (0, _utils.createRule)({
|
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
|
|
46
|
+
FunctionDeclaration(node) {
|
|
47
|
+
const declaredVariables = context.getDeclaredVariables(node);
|
|
48
|
+
const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
|
|
49
|
+
|
|
50
|
+
if (testCallExpressions.length > 0) {
|
|
51
|
+
isTest = true;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
46
55
|
CatchClause() {
|
|
47
56
|
if (isTest) {
|
|
48
57
|
++catchDepth;
|
|
@@ -59,6 +68,15 @@ var _default = (0, _utils.createRule)({
|
|
|
59
68
|
if ((0, _utils.isTestCase)(node)) {
|
|
60
69
|
isTest = false;
|
|
61
70
|
}
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
'FunctionDeclaration:exit'(node) {
|
|
74
|
+
const declaredVariables = context.getDeclaredVariables(node);
|
|
75
|
+
const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
|
|
76
|
+
|
|
77
|
+
if (testCallExpressions.length > 0) {
|
|
78
|
+
isTest = false;
|
|
79
|
+
}
|
|
62
80
|
}
|
|
63
81
|
|
|
64
82
|
};
|
|
@@ -21,7 +21,7 @@ const isExpectAssertionsOrHasAssertionsCall = expression => {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const [arg] = expression.arguments;
|
|
24
|
-
return
|
|
24
|
+
return (0, _utils.hasOnlyOneArgument)(expression) && arg.type === _experimentalUtils.AST_NODE_TYPES.Literal && typeof arg.value === 'number' && Number.isInteger(arg.value);
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const getFunctionFirstLine = functionBody => functionBody[0] && functionBody[0].expression;
|
package/lib/rules/prefer-todo.js
CHANGED
|
@@ -9,8 +9,13 @@ var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
|
9
9
|
|
|
10
10
|
var _utils = require("./utils");
|
|
11
11
|
|
|
12
|
-
function
|
|
12
|
+
function isEmptyFunction(node) {
|
|
13
|
+
if (!(0, _utils.isFunction)(node)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
13
16
|
/* istanbul ignore if https://github.com/typescript-eslint/typescript-eslint/issues/734 */
|
|
17
|
+
|
|
18
|
+
|
|
14
19
|
if (!node.body) {
|
|
15
20
|
throw new Error(`Unexpected null while performing prefer-todo - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`);
|
|
16
21
|
}
|
|
@@ -18,12 +23,7 @@ function isFunctionBodyEmpty(node) {
|
|
|
18
23
|
return node.body.type === _experimentalUtils.AST_NODE_TYPES.BlockStatement && node.body.body && !node.body.body.length;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
function
|
|
22
|
-
const [, fn] = node.arguments;
|
|
23
|
-
return fn && (0, _utils.isFunction)(fn) && isFunctionBodyEmpty(fn);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function addTodo(node, fixer) {
|
|
26
|
+
function createTodoFixer(node, fixer) {
|
|
27
27
|
const testName = (0, _utils.getNodeName)(node.callee).split('.').shift();
|
|
28
28
|
return fixer.replaceText(node.callee, `${testName}.todo`);
|
|
29
29
|
}
|
|
@@ -39,8 +39,8 @@ var _default = (0, _utils.createRule)({
|
|
|
39
39
|
recommended: false
|
|
40
40
|
},
|
|
41
41
|
messages: {
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
emptyTest: 'Prefer todo test case over empty test case',
|
|
43
|
+
unimplementedTest: 'Prefer todo test case over unimplemented test case'
|
|
44
44
|
},
|
|
45
45
|
fixable: 'code',
|
|
46
46
|
schema: [],
|
|
@@ -51,25 +51,25 @@ var _default = (0, _utils.createRule)({
|
|
|
51
51
|
create(context) {
|
|
52
52
|
return {
|
|
53
53
|
CallExpression(node) {
|
|
54
|
-
const [
|
|
54
|
+
const [title, callback] = node.arguments;
|
|
55
55
|
|
|
56
|
-
if (!
|
|
56
|
+
if (!title || !isTargetedTestCase(node) || !(0, _utils.isStringNode)(title)) {
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
if (
|
|
60
|
+
if (callback && isEmptyFunction(callback)) {
|
|
61
61
|
context.report({
|
|
62
|
-
messageId: '
|
|
62
|
+
messageId: 'emptyTest',
|
|
63
63
|
node,
|
|
64
|
-
fix: fixer => [fixer.removeRange([
|
|
64
|
+
fix: fixer => [fixer.removeRange([title.range[1], callback.range[1]]), createTodoFixer(node, fixer)]
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
if ((0, _utils.hasOnlyOneArgument)(node)) {
|
|
69
69
|
context.report({
|
|
70
|
-
messageId: '
|
|
70
|
+
messageId: 'unimplementedTest',
|
|
71
71
|
node,
|
|
72
|
-
fix: fixer => [
|
|
72
|
+
fix: fixer => [createTodoFixer(node, fixer)]
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
}
|
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.getJestFunctionArguments = exports.isDescribeEach = exports.isDescribe = exports.isTestCase = 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.getJestFunctionArguments = exports.isDescribeEach = exports.isDescribe = exports.isTestCase = 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;
|
|
8
8
|
|
|
9
9
|
var _path = require("path");
|
|
10
10
|
|
|
@@ -378,6 +378,12 @@ function getNodeName(node) {
|
|
|
378
378
|
|
|
379
379
|
case _experimentalUtils.AST_NODE_TYPES.MemberExpression:
|
|
380
380
|
return joinNames(getNodeName(node.object), getNodeName(node.property));
|
|
381
|
+
|
|
382
|
+
case _experimentalUtils.AST_NODE_TYPES.NewExpression:
|
|
383
|
+
return getNodeName(node.callee);
|
|
384
|
+
|
|
385
|
+
case _experimentalUtils.AST_NODE_TYPES.CallExpression:
|
|
386
|
+
return getNodeName(node.callee);
|
|
381
387
|
}
|
|
382
388
|
|
|
383
389
|
return null;
|
|
@@ -391,6 +397,16 @@ const isHook = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.Id
|
|
|
391
397
|
|
|
392
398
|
exports.isHook = isHook;
|
|
393
399
|
|
|
400
|
+
const getTestCallExpressionsFromDeclaredVariables = declaredVaiables => {
|
|
401
|
+
return declaredVaiables.reduce((acc, {
|
|
402
|
+
references
|
|
403
|
+
}) => acc.concat(references.map(({
|
|
404
|
+
identifier
|
|
405
|
+
}) => identifier.parent).filter(node => !!node && node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression && isTestCase(node))), []);
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
exports.getTestCallExpressionsFromDeclaredVariables = getTestCallExpressionsFromDeclaredVariables;
|
|
409
|
+
|
|
394
410
|
const isTestCase = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.Identifier && TestCaseName.hasOwnProperty(node.callee.name) || node.callee.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === _experimentalUtils.AST_NODE_TYPES.Identifier && TestCaseProperty.hasOwnProperty(node.callee.property.name) && (node.callee.object.type === _experimentalUtils.AST_NODE_TYPES.Identifier && TestCaseName.hasOwnProperty(node.callee.object.name) || node.callee.object.type === _experimentalUtils.AST_NODE_TYPES.MemberExpression && node.callee.object.object.type === _experimentalUtils.AST_NODE_TYPES.Identifier && TestCaseName.hasOwnProperty(node.callee.object.object.name));
|
|
395
411
|
|
|
396
412
|
exports.isTestCase = isTestCase;
|
|
@@ -64,12 +64,10 @@ var _default = (0, _utils.createRule)({
|
|
|
64
64
|
recommended: 'error'
|
|
65
65
|
},
|
|
66
66
|
messages: {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
propertyWithoutMatcher: '"{{ propertyName }}" needs to call a matcher.',
|
|
72
|
-
matcherOnPropertyNotCalled: '"{{ propertyName }}" was not called.',
|
|
67
|
+
incorrectNumberOfArguments: 'Expect takes one and only one argument.',
|
|
68
|
+
modifierUnknown: 'Expect has no modifier named "{{ modifierName }}".',
|
|
69
|
+
matcherNotFound: 'Expect must have a corresponding matcher call.',
|
|
70
|
+
matcherNotCalled: 'Matchers must be called to assert.',
|
|
73
71
|
asyncMustBeAwaited: 'Async assertions must be awaited{{ orReturned }}.',
|
|
74
72
|
promisesWithAsyncAssertionsMustBeAwaited: 'Promises which return async assertions must be awaited{{ orReturned }}.'
|
|
75
73
|
},
|
|
@@ -119,35 +117,39 @@ var _default = (0, _utils.createRule)({
|
|
|
119
117
|
matcher
|
|
120
118
|
} = (0, _utils.parseExpectCall)(node);
|
|
121
119
|
|
|
122
|
-
if (expect.arguments.length
|
|
123
|
-
const secondArgumentLocStart = expect.arguments[1].loc.start;
|
|
124
|
-
const lastArgumentLocEnd = expect.arguments[node.arguments.length - 1].loc.end;
|
|
125
|
-
context.report({
|
|
126
|
-
loc: {
|
|
127
|
-
end: {
|
|
128
|
-
column: lastArgumentLocEnd.column - 1,
|
|
129
|
-
line: lastArgumentLocEnd.line
|
|
130
|
-
},
|
|
131
|
-
start: secondArgumentLocStart
|
|
132
|
-
},
|
|
133
|
-
messageId: 'multipleArgs',
|
|
134
|
-
node
|
|
135
|
-
});
|
|
136
|
-
} else if (expect.arguments.length === 0) {
|
|
120
|
+
if (expect.arguments.length !== 1) {
|
|
137
121
|
const expectLength = (0, _utils.getAccessorValue)(expect.callee).length;
|
|
138
|
-
|
|
139
|
-
|
|
122
|
+
let loc = {
|
|
123
|
+
start: {
|
|
124
|
+
column: node.loc.start.column + expectLength,
|
|
125
|
+
line: node.loc.start.line
|
|
126
|
+
},
|
|
127
|
+
end: {
|
|
128
|
+
column: node.loc.start.column + expectLength + 1,
|
|
129
|
+
line: node.loc.start.line
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
if (expect.arguments.length !== 0) {
|
|
134
|
+
const {
|
|
135
|
+
start
|
|
136
|
+
} = expect.arguments[1].loc;
|
|
137
|
+
const {
|
|
138
|
+
end
|
|
139
|
+
} = expect.arguments[node.arguments.length - 1].loc;
|
|
140
|
+
loc = {
|
|
141
|
+
start,
|
|
140
142
|
end: {
|
|
141
|
-
column:
|
|
142
|
-
line:
|
|
143
|
-
},
|
|
144
|
-
start: {
|
|
145
|
-
column: node.loc.start.column + expectLength,
|
|
146
|
-
line: node.loc.start.line
|
|
143
|
+
column: end.column - 1,
|
|
144
|
+
line: end.line
|
|
147
145
|
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
context.report({
|
|
150
|
+
messageId: 'incorrectNumberOfArguments',
|
|
151
|
+
node,
|
|
152
|
+
loc
|
|
151
153
|
});
|
|
152
154
|
} // something was called on `expect()`
|
|
153
155
|
|
|
@@ -155,12 +157,7 @@ var _default = (0, _utils.createRule)({
|
|
|
155
157
|
if (!matcher) {
|
|
156
158
|
if (modifier) {
|
|
157
159
|
context.report({
|
|
158
|
-
|
|
159
|
-
propertyName: modifier.name
|
|
160
|
-
},
|
|
161
|
-
// todo: rename to 'modifierName'
|
|
162
|
-
messageId: 'propertyWithoutMatcher',
|
|
163
|
-
// todo: rename to 'modifierWithoutMatcher'
|
|
160
|
+
messageId: 'matcherNotFound',
|
|
164
161
|
node: modifier.node.property
|
|
165
162
|
});
|
|
166
163
|
}
|
|
@@ -170,12 +167,10 @@ var _default = (0, _utils.createRule)({
|
|
|
170
167
|
|
|
171
168
|
if (matcher.node.parent && (0, _utils.isExpectMember)(matcher.node.parent)) {
|
|
172
169
|
context.report({
|
|
173
|
-
messageId: '
|
|
174
|
-
// todo: rename to 'invalidModifier'
|
|
170
|
+
messageId: 'modifierUnknown',
|
|
175
171
|
data: {
|
|
176
|
-
|
|
172
|
+
modifierName: matcher.name
|
|
177
173
|
},
|
|
178
|
-
// todo: rename to 'matcherName' (or modifierName?)
|
|
179
174
|
node: matcher.node.property
|
|
180
175
|
});
|
|
181
176
|
return;
|
|
@@ -183,12 +178,7 @@ var _default = (0, _utils.createRule)({
|
|
|
183
178
|
|
|
184
179
|
if (!matcher.arguments) {
|
|
185
180
|
context.report({
|
|
186
|
-
|
|
187
|
-
propertyName: matcher.name
|
|
188
|
-
},
|
|
189
|
-
// todo: rename to 'matcherName'
|
|
190
|
-
messageId: 'matcherOnPropertyNotCalled',
|
|
191
|
-
// todo: rename to 'matcherNotCalled'
|
|
181
|
+
messageId: 'matcherNotCalled',
|
|
192
182
|
node: matcher.node.property
|
|
193
183
|
});
|
|
194
184
|
}
|
|
@@ -237,7 +227,7 @@ var _default = (0, _utils.createRule)({
|
|
|
237
227
|
'CallExpression:exit'(node) {
|
|
238
228
|
if ((0, _utils.isExpectCall)(node) && isNoAssertionsParentNode(node.parent)) {
|
|
239
229
|
context.report({
|
|
240
|
-
messageId: '
|
|
230
|
+
messageId: 'matcherNotFound',
|
|
241
231
|
node
|
|
242
232
|
});
|
|
243
233
|
}
|
package/lib/rules/valid-title.js
CHANGED
|
@@ -23,6 +23,8 @@ const doesBinaryExpressionContainStringNode = binaryExp => {
|
|
|
23
23
|
return (0, _utils.isStringNode)(binaryExp.left);
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
const quoteStringValue = node => node.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral ? `\`${node.quasis[0].value.raw}\`` : node.raw;
|
|
27
|
+
|
|
26
28
|
var _default = (0, _utils.createRule)({
|
|
27
29
|
name: __filename,
|
|
28
30
|
meta: {
|
|
@@ -35,7 +37,8 @@ var _default = (0, _utils.createRule)({
|
|
|
35
37
|
titleMustBeString: 'Title must be a string',
|
|
36
38
|
emptyTitle: '{{ jestFunctionName }} should not have an empty title',
|
|
37
39
|
duplicatePrefix: 'should not have duplicate prefix',
|
|
38
|
-
accidentalSpace: 'should not have leading or trailing spaces'
|
|
40
|
+
accidentalSpace: 'should not have leading or trailing spaces',
|
|
41
|
+
disallowedWord: '"{{ word }}" is not allowed in test titles.'
|
|
39
42
|
},
|
|
40
43
|
type: 'suggestion',
|
|
41
44
|
schema: [{
|
|
@@ -44,6 +47,13 @@ var _default = (0, _utils.createRule)({
|
|
|
44
47
|
ignoreTypeOfDescribeName: {
|
|
45
48
|
type: 'boolean',
|
|
46
49
|
default: false
|
|
50
|
+
},
|
|
51
|
+
disallowedWords: {
|
|
52
|
+
type: 'array',
|
|
53
|
+
items: {
|
|
54
|
+
type: 'string'
|
|
55
|
+
},
|
|
56
|
+
default: []
|
|
47
57
|
}
|
|
48
58
|
},
|
|
49
59
|
additionalProperties: false
|
|
@@ -51,12 +61,15 @@ var _default = (0, _utils.createRule)({
|
|
|
51
61
|
fixable: 'code'
|
|
52
62
|
},
|
|
53
63
|
defaultOptions: [{
|
|
54
|
-
ignoreTypeOfDescribeName: false
|
|
64
|
+
ignoreTypeOfDescribeName: false,
|
|
65
|
+
disallowedWords: []
|
|
55
66
|
}],
|
|
56
67
|
|
|
57
68
|
create(context, [{
|
|
58
|
-
ignoreTypeOfDescribeName
|
|
69
|
+
ignoreTypeOfDescribeName,
|
|
70
|
+
disallowedWords
|
|
59
71
|
}]) {
|
|
72
|
+
const disallowedWordsRegexp = new RegExp(`\\b(${disallowedWords.join('|')})\\b`, 'iu');
|
|
60
73
|
return {
|
|
61
74
|
CallExpression(node) {
|
|
62
75
|
if (!((0, _utils.isDescribe)(node) || (0, _utils.isTestCase)(node)) || !node.arguments.length) {
|
|
@@ -93,16 +106,26 @@ var _default = (0, _utils.createRule)({
|
|
|
93
106
|
return;
|
|
94
107
|
}
|
|
95
108
|
|
|
109
|
+
if (disallowedWords.length > 0) {
|
|
110
|
+
const disallowedMatch = disallowedWordsRegexp.exec(title);
|
|
111
|
+
|
|
112
|
+
if (disallowedMatch) {
|
|
113
|
+
context.report({
|
|
114
|
+
data: {
|
|
115
|
+
word: disallowedMatch[1]
|
|
116
|
+
},
|
|
117
|
+
messageId: 'disallowedWord',
|
|
118
|
+
node: argument
|
|
119
|
+
});
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
96
124
|
if (title.trim().length !== title.length) {
|
|
97
125
|
context.report({
|
|
98
126
|
messageId: 'accidentalSpace',
|
|
99
127
|
node: argument,
|
|
100
|
-
|
|
101
|
-
fix(fixer) {
|
|
102
|
-
const stringValue = argument.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral ? `\`${argument.quasis[0].value.raw}\`` : argument.raw;
|
|
103
|
-
return [fixer.replaceTextRange(argument.range, stringValue.replace(/^([`'"]) +?/, '$1').replace(/ +?([`'"])$/, '$1'))];
|
|
104
|
-
}
|
|
105
|
-
|
|
128
|
+
fix: fixer => [fixer.replaceTextRange(argument.range, quoteStringValue(argument).replace(/^([`'"]) +?/u, '$1').replace(/ +?([`'"])$/u, '$1'))]
|
|
106
129
|
});
|
|
107
130
|
}
|
|
108
131
|
|
|
@@ -113,12 +136,7 @@ var _default = (0, _utils.createRule)({
|
|
|
113
136
|
context.report({
|
|
114
137
|
messageId: 'duplicatePrefix',
|
|
115
138
|
node: argument,
|
|
116
|
-
|
|
117
|
-
fix(fixer) {
|
|
118
|
-
const stringValue = argument.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral ? `\`${argument.quasis[0].value.raw}\`` : argument.raw;
|
|
119
|
-
return [fixer.replaceTextRange(argument.range, stringValue.replace(/^([`'"]).+? /, '$1'))];
|
|
120
|
-
}
|
|
121
|
-
|
|
139
|
+
fix: fixer => [fixer.replaceTextRange(argument.range, quoteStringValue(argument).replace(/^([`'"]).+? /u, '$1'))]
|
|
122
140
|
});
|
|
123
141
|
}
|
|
124
142
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-jest",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.7.0",
|
|
4
4
|
"description": "Eslint rules for Jest",
|
|
5
5
|
"repository": "jest-community/eslint-plugin-jest",
|
|
6
6
|
"license": "MIT",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"eslint-plugin-eslint-comments": "^3.1.2",
|
|
61
61
|
"eslint-plugin-eslint-plugin": "^2.0.0",
|
|
62
62
|
"eslint-plugin-import": "^2.18.0",
|
|
63
|
-
"eslint-plugin-node": "^
|
|
63
|
+
"eslint-plugin-node": "^11.0.0",
|
|
64
64
|
"eslint-plugin-prettier": "^3.0.0",
|
|
65
65
|
"husky": "^3.0.9",
|
|
66
66
|
"jest": "^24.9.0",
|