eslint-plugin-jest 23.4.0 → 23.8.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 +47 -0
- package/README.md +3 -3
- package/docs/rules/expect-expect.md +5 -3
- package/docs/rules/no-large-snapshots.md +10 -2
- package/docs/rules/valid-title.md +45 -3
- package/lib/rules/expect-expect.js +16 -1
- package/lib/rules/no-commented-out-tests.js +1 -1
- package/lib/rules/no-export.js +1 -1
- package/lib/rules/no-if.js +13 -5
- package/lib/rules/no-large-snapshots.js +14 -1
- package/lib/rules/utils.js +6 -16
- package/lib/rules/valid-expect.js +39 -49
- package/lib/rules/valid-title.js +38 -16
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
# [23.8.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.7.0...v23.8.0) (2020-02-23)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **valid-title:** ensure argument node is defined before accessing props
|
|
6
|
+
([#538](https://github.com/jest-community/eslint-plugin-jest/issues/538))
|
|
7
|
+
([7730f75](https://github.com/jest-community/eslint-plugin-jest/commit/7730f757561100559509b756fd362ca33b9ab1d4))
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
- **no-large-snapshots:** add setting to define maxSize by snapshot type
|
|
12
|
+
([#524](https://github.com/jest-community/eslint-plugin-jest/issues/524))
|
|
13
|
+
([0d77300](https://github.com/jest-community/eslint-plugin-jest/commit/0d77300e61adc7a5aa84f34ff4ccc164075d5f41))
|
|
14
|
+
|
|
15
|
+
# [23.7.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.6.0...v23.7.0) (2020-02-07)
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
- **expect-expect:** use `u` flag in regex
|
|
20
|
+
([#532](https://github.com/jest-community/eslint-plugin-jest/issues/532))
|
|
21
|
+
([c12b725](https://github.com/jest-community/eslint-plugin-jest/commit/c12b7251ef1506073d268973b93c7fc9fbcf50af))
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
- **valid-title:** support `disallowedWords` option
|
|
26
|
+
([#522](https://github.com/jest-community/eslint-plugin-jest/issues/522))
|
|
27
|
+
([38bbe93](https://github.com/jest-community/eslint-plugin-jest/commit/38bbe93794ed456c6e9e5d7be848b2aeb55ce0ba))
|
|
28
|
+
|
|
29
|
+
# [23.6.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.5.0...v23.6.0) (2020-01-12)
|
|
30
|
+
|
|
31
|
+
### Features
|
|
32
|
+
|
|
33
|
+
- **no-if:** support `switch` statements
|
|
34
|
+
([#515](https://github.com/jest-community/eslint-plugin-jest/issues/515))
|
|
35
|
+
([be4e49d](https://github.com/jest-community/eslint-plugin-jest/commit/be4e49dcecd64711e743f5e09d1ff24e4c6e1648))
|
|
36
|
+
|
|
37
|
+
# [23.5.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.4.0...v23.5.0) (2020-01-12)
|
|
38
|
+
|
|
39
|
+
### Features
|
|
40
|
+
|
|
41
|
+
- **expect-expect:** support glob patterns for assertFunctionNames
|
|
42
|
+
([#509](https://github.com/jest-community/eslint-plugin-jest/issues/509))
|
|
43
|
+
([295ca9a](https://github.com/jest-community/eslint-plugin-jest/commit/295ca9a6969c77fadaa1a42d76e89cae992520a6))
|
|
44
|
+
- **valid-expect:** refactor `valid-expect` linting messages
|
|
45
|
+
([#501](https://github.com/jest-community/eslint-plugin-jest/issues/501))
|
|
46
|
+
([7338362](https://github.com/jest-community/eslint-plugin-jest/commit/7338362420eb4970f99be2016bb4ded5732797e3))
|
|
47
|
+
|
|
1
48
|
# [23.4.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.3.0...v23.4.0) (2020-01-10)
|
|
2
49
|
|
|
3
50
|
### 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:
|
|
@@ -78,10 +80,10 @@ test('returns sum', () =>
|
|
|
78
80
|
|
|
79
81
|
Examples of **correct** code for working with the HTTP assertions library
|
|
80
82
|
[SuperTest](https://www.npmjs.com/package/supertest) with the
|
|
81
|
-
`{ "assertFunctionNames": ["expect", "request
|
|
83
|
+
`{ "assertFunctionNames": ["expect", "request.*.expect"] }` option:
|
|
82
84
|
|
|
83
85
|
```js
|
|
84
|
-
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "request
|
|
86
|
+
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "request.*.expect"] }] */
|
|
85
87
|
const request = require('supertest');
|
|
86
88
|
const express = require('express');
|
|
87
89
|
|
|
@@ -98,7 +98,7 @@ line 4
|
|
|
98
98
|
|
|
99
99
|
## Options
|
|
100
100
|
|
|
101
|
-
This rule has
|
|
101
|
+
This rule has options for modifying the max number of lines allowed for a
|
|
102
102
|
snapshot:
|
|
103
103
|
|
|
104
104
|
In an `eslintrc` file:
|
|
@@ -106,11 +106,19 @@ In an `eslintrc` file:
|
|
|
106
106
|
```json
|
|
107
107
|
...
|
|
108
108
|
"rules": {
|
|
109
|
-
"jest/no-large-snapshots": ["warn", { "maxSize": 12 }]
|
|
109
|
+
"jest/no-large-snapshots": ["warn", { "maxSize": 12, "inlineMaxSize": 6 }]
|
|
110
110
|
}
|
|
111
111
|
...
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
+
Max number of lines allowed could be defined by snapshot type (Inline and
|
|
115
|
+
External). Use `inlineMaxSize` for
|
|
116
|
+
[Inline Snapshots](https://jestjs.io/docs/en/snapshot-testing#inline-snapshots)
|
|
117
|
+
size and `maxSize` for
|
|
118
|
+
[External Snapshots](https://jestjs.io/docs/en/snapshot-testing#snapshot-testing-with-jest).
|
|
119
|
+
If only `maxSize` is provided on options, the value of `maxSize` will be used to
|
|
120
|
+
both snapshot types (Inline and External).
|
|
121
|
+
|
|
114
122
|
In addition there is an option for whitelisting large snapshot files. Since
|
|
115
123
|
`//eslint` comments will be removed when a `.snap` file is updated, this option
|
|
116
124
|
provides a way of whitelisting large snapshots. The list of whitelistedSnapshots
|
|
@@ -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
|
+
```
|
|
@@ -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: {
|
|
@@ -70,7 +85,7 @@ var _default = (0, _utils.createRule)({
|
|
|
70
85
|
|
|
71
86
|
if (name === _utils.TestCaseName.it || name === _utils.TestCaseName.test) {
|
|
72
87
|
unchecked.push(node);
|
|
73
|
-
} else if (name &&
|
|
88
|
+
} else if (name && matchesAssertFunctionName(name, assertFunctionNames)) {
|
|
74
89
|
// Return early in case of nested `it` statements.
|
|
75
90
|
checkCallExpressionUsed(context.getAncestors());
|
|
76
91
|
}
|
|
@@ -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)({
|
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
|
@@ -13,6 +13,12 @@ const testCaseNames = new Set([...Object.keys(_utils.TestCaseName), 'it.only', '
|
|
|
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
|
}
|
|
@@ -67,6 +74,7 @@ var _default = (0, _utils.createRule)({
|
|
|
67
74
|
},
|
|
68
75
|
|
|
69
76
|
IfStatement: validate,
|
|
77
|
+
SwitchStatement: validate,
|
|
70
78
|
ConditionalExpression: validate,
|
|
71
79
|
|
|
72
80
|
'CallExpression:exit'() {
|
|
@@ -11,6 +11,12 @@ var _experimentalUtils = require("@typescript-eslint/experimental-utils");
|
|
|
11
11
|
|
|
12
12
|
var _utils = require("./utils");
|
|
13
13
|
|
|
14
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
15
|
+
|
|
16
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
17
|
+
|
|
18
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
19
|
+
|
|
14
20
|
const reportOnViolation = (context, node, {
|
|
15
21
|
maxSize: lineLimit = 50,
|
|
16
22
|
whitelistedSnapshots = {}
|
|
@@ -73,6 +79,9 @@ var _default = (0, _utils.createRule)({
|
|
|
73
79
|
maxSize: {
|
|
74
80
|
type: 'number'
|
|
75
81
|
},
|
|
82
|
+
inlineMaxSize: {
|
|
83
|
+
type: 'number'
|
|
84
|
+
},
|
|
76
85
|
whitelistedSnapshots: {
|
|
77
86
|
type: 'object',
|
|
78
87
|
patternProperties: {
|
|
@@ -99,7 +108,11 @@ var _default = (0, _utils.createRule)({
|
|
|
99
108
|
return {
|
|
100
109
|
CallExpression(node) {
|
|
101
110
|
if ('property' in node.callee && ((0, _utils.isSupportedAccessor)(node.callee.property, 'toMatchInlineSnapshot') || (0, _utils.isSupportedAccessor)(node.callee.property, 'toThrowErrorMatchingInlineSnapshot'))) {
|
|
102
|
-
|
|
111
|
+
var _options$inlineMaxSiz;
|
|
112
|
+
|
|
113
|
+
reportOnViolation(context, node, _objectSpread({}, options, {
|
|
114
|
+
maxSize: (_options$inlineMaxSiz = options.inlineMaxSize) !== null && _options$inlineMaxSiz !== void 0 ? _options$inlineMaxSiz : options.maxSize
|
|
115
|
+
}));
|
|
103
116
|
}
|
|
104
117
|
}
|
|
105
118
|
|
package/lib/rules/utils.js
CHANGED
|
@@ -360,28 +360,18 @@ exports.TestCaseProperty = TestCaseProperty;
|
|
|
360
360
|
TestCaseProperty["todo"] = "todo";
|
|
361
361
|
})(TestCaseProperty || (exports.TestCaseProperty = TestCaseProperty = {}));
|
|
362
362
|
|
|
363
|
+
const joinNames = (a, b) => a && b ? `${a}.${b}` : null;
|
|
364
|
+
|
|
363
365
|
function getNodeName(node) {
|
|
364
|
-
|
|
365
|
-
return
|
|
366
|
+
if (isSupportedAccessor(node)) {
|
|
367
|
+
return getAccessorValue(node);
|
|
366
368
|
}
|
|
367
369
|
|
|
368
370
|
switch (node.type) {
|
|
369
|
-
case _experimentalUtils.AST_NODE_TYPES.Identifier:
|
|
370
|
-
return node.name;
|
|
371
|
-
|
|
372
|
-
case _experimentalUtils.AST_NODE_TYPES.Literal:
|
|
373
|
-
return `${node.value}`;
|
|
374
|
-
|
|
375
|
-
case _experimentalUtils.AST_NODE_TYPES.TemplateLiteral:
|
|
376
|
-
if (node.expressions.length === 0) return node.quasis[0].value.cooked;
|
|
377
|
-
break;
|
|
378
|
-
|
|
379
371
|
case _experimentalUtils.AST_NODE_TYPES.MemberExpression:
|
|
380
372
|
return joinNames(getNodeName(node.object), getNodeName(node.property));
|
|
381
373
|
|
|
382
374
|
case _experimentalUtils.AST_NODE_TYPES.NewExpression:
|
|
383
|
-
return getNodeName(node.callee);
|
|
384
|
-
|
|
385
375
|
case _experimentalUtils.AST_NODE_TYPES.CallExpression:
|
|
386
376
|
return getNodeName(node.callee);
|
|
387
377
|
}
|
|
@@ -397,8 +387,8 @@ const isHook = node => node.callee.type === _experimentalUtils.AST_NODE_TYPES.Id
|
|
|
397
387
|
|
|
398
388
|
exports.isHook = isHook;
|
|
399
389
|
|
|
400
|
-
const getTestCallExpressionsFromDeclaredVariables =
|
|
401
|
-
return
|
|
390
|
+
const getTestCallExpressionsFromDeclaredVariables = declaredVariables => {
|
|
391
|
+
return declaredVariables.reduce((acc, {
|
|
402
392
|
references
|
|
403
393
|
}) => acc.concat(references.map(({
|
|
404
394
|
identifier
|
|
@@ -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,20 +61,27 @@ 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
|
-
if (!(
|
|
75
|
+
if (!(0, _utils.isDescribe)(node) && !(0, _utils.isTestCase)(node)) {
|
|
63
76
|
return;
|
|
64
77
|
}
|
|
65
78
|
|
|
66
79
|
const [argument] = (0, _utils.getJestFunctionArguments)(node);
|
|
67
80
|
|
|
81
|
+
if (!argument) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
68
85
|
if (!(0, _utils.isStringNode)(argument)) {
|
|
69
86
|
if (argument.type === _experimentalUtils.AST_NODE_TYPES.BinaryExpression && doesBinaryExpressionContainStringNode(argument)) {
|
|
70
87
|
return;
|
|
@@ -93,16 +110,26 @@ var _default = (0, _utils.createRule)({
|
|
|
93
110
|
return;
|
|
94
111
|
}
|
|
95
112
|
|
|
113
|
+
if (disallowedWords.length > 0) {
|
|
114
|
+
const disallowedMatch = disallowedWordsRegexp.exec(title);
|
|
115
|
+
|
|
116
|
+
if (disallowedMatch) {
|
|
117
|
+
context.report({
|
|
118
|
+
data: {
|
|
119
|
+
word: disallowedMatch[1]
|
|
120
|
+
},
|
|
121
|
+
messageId: 'disallowedWord',
|
|
122
|
+
node: argument
|
|
123
|
+
});
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
96
128
|
if (title.trim().length !== title.length) {
|
|
97
129
|
context.report({
|
|
98
130
|
messageId: 'accidentalSpace',
|
|
99
131
|
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
|
-
|
|
132
|
+
fix: fixer => [fixer.replaceTextRange(argument.range, quoteStringValue(argument).replace(/^([`'"]) +?/u, '$1').replace(/ +?([`'"])$/u, '$1'))]
|
|
106
133
|
});
|
|
107
134
|
}
|
|
108
135
|
|
|
@@ -113,12 +140,7 @@ var _default = (0, _utils.createRule)({
|
|
|
113
140
|
context.report({
|
|
114
141
|
messageId: 'duplicatePrefix',
|
|
115
142
|
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
|
-
|
|
143
|
+
fix: fixer => [fixer.replaceTextRange(argument.range, quoteStringValue(argument).replace(/^([`'"]).+? /u, '$1'))]
|
|
122
144
|
});
|
|
123
145
|
}
|
|
124
146
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-jest",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.8.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",
|