eslint-plugin-jest 23.17.1 → 23.18.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 +7 -0
- package/docs/rules/valid-title.md +38 -2
- package/lib/index.js +15 -32
- package/lib/rules/expect-expect.js +1 -1
- package/lib/rules/no-alias-methods.js +1 -1
- package/lib/rules/no-commented-out-tests.js +1 -1
- package/lib/rules/no-disabled-tests.js +1 -1
- package/lib/rules/no-export.js +1 -1
- package/lib/rules/no-focused-tests.js +1 -1
- package/lib/rules/no-jasmine-globals.js +1 -1
- package/lib/rules/no-standalone-expect.js +1 -1
- package/lib/rules/no-test-callback.js +1 -1
- package/lib/rules/no-try-expect.js +1 -1
- package/lib/rules/valid-describe.js +1 -1
- package/lib/rules/valid-title.js +96 -2
- package/package.json +3 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [23.18.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.17.1...v23.18.0) (2020-07-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **valid-title:** support `mustMatch` & `mustNotMatch` options ([#608](https://github.com/jest-community/eslint-plugin-jest/issues/608)) ([4c7207e](https://github.com/jest-community/eslint-plugin-jest/commit/4c7207ebbb274f7b584225ad65ffb96a4328240e)), closes [#233](https://github.com/jest-community/eslint-plugin-jest/issues/233)
|
|
7
|
+
|
|
1
8
|
## [23.17.1](https://github.com/jest-community/eslint-plugin-jest/compare/v23.17.0...v23.17.1) (2020-06-23)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -152,9 +152,11 @@ describe('foo', () => {
|
|
|
152
152
|
## Options
|
|
153
153
|
|
|
154
154
|
```ts
|
|
155
|
-
interface {
|
|
155
|
+
interface Options {
|
|
156
156
|
ignoreTypeOfDescribeName?: boolean;
|
|
157
157
|
disallowedWords?: string[];
|
|
158
|
+
mustNotMatch?: Partial<Record<'describe' | 'test' | 'it', string>> | string;
|
|
159
|
+
mustMatch?: Partial<Record<'describe' | 'test' | 'it', string>> | string;
|
|
158
160
|
}
|
|
159
161
|
```
|
|
160
162
|
|
|
@@ -172,7 +174,7 @@ Default: `[]`
|
|
|
172
174
|
A string array of words that are not allowed to be used in test titles. Matching
|
|
173
175
|
is not case-sensitive, and looks for complete words:
|
|
174
176
|
|
|
175
|
-
Examples of **incorrect** code using `disallowedWords`:
|
|
177
|
+
Examples of **incorrect** code when using `disallowedWords`:
|
|
176
178
|
|
|
177
179
|
```js
|
|
178
180
|
// with disallowedWords: ['correct', 'all', 'every', 'properly']
|
|
@@ -190,3 +192,37 @@ it('correctly sets the value', () => {});
|
|
|
190
192
|
test('that everything is as it should be', () => {});
|
|
191
193
|
describe('the proper way to handle things', () => {});
|
|
192
194
|
```
|
|
195
|
+
|
|
196
|
+
#### `mustMatch` & `mustNotMatch`
|
|
197
|
+
|
|
198
|
+
Defaults: `{}`
|
|
199
|
+
|
|
200
|
+
Allows enforcing that titles must match or must not match a given Regular
|
|
201
|
+
Expression. An object can be provided to apply different Regular Expressions to
|
|
202
|
+
specific Jest test function groups (`describe`, `test`, and `it`).
|
|
203
|
+
|
|
204
|
+
Examples of **incorrect** code when using `mustMatch`:
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
// with mustMatch: '$that'
|
|
208
|
+
describe('the correct way to do things', () => {});
|
|
209
|
+
fit('this there!', () => {});
|
|
210
|
+
|
|
211
|
+
// with mustMatch: { test: '$that' }
|
|
212
|
+
describe('the tests that will be run', () => {});
|
|
213
|
+
test('the stuff works', () => {});
|
|
214
|
+
xtest('errors that are thrown have messages', () => {});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Examples of **correct** code when using `mustMatch`:
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
// with mustMatch: '$that'
|
|
221
|
+
describe('that thing that needs to be done', () => {});
|
|
222
|
+
fit('that this there!', () => {});
|
|
223
|
+
|
|
224
|
+
// with mustMatch: { test: '$that' }
|
|
225
|
+
describe('the tests that will be run', () => {});
|
|
226
|
+
test('that the stuff works', () => {});
|
|
227
|
+
xtest('that errors that thrown have messages', () => {});
|
|
228
|
+
```
|
package/lib/index.js
CHANGED
|
@@ -32,45 +32,28 @@ interopRequireDefault(require(moduleName)).default;
|
|
|
32
32
|
|
|
33
33
|
const rulesDir = (0, _path.join)(__dirname, 'rules');
|
|
34
34
|
const excludedFiles = ['__tests__', 'utils'];
|
|
35
|
-
const rules = (0, _fs.readdirSync)(rulesDir).map(rule => (0, _path.parse)(rule).name).filter(rule => !excludedFiles.includes(rule)).reduce((acc, curr) =>
|
|
35
|
+
const rules = (0, _fs.readdirSync)(rulesDir).map(rule => (0, _path.parse)(rule).name).filter(rule => !excludedFiles.includes(rule)).reduce((acc, curr) => _objectSpread(_objectSpread({}, acc), {}, {
|
|
36
36
|
[curr]: importDefault((0, _path.join)(rulesDir, curr))
|
|
37
37
|
}), {});
|
|
38
|
+
const recommendedRules = Object.entries(rules).filter(([, rule]) => rule.meta.docs.recommended).reduce((acc, [name, rule]) => _objectSpread(_objectSpread({}, acc), {}, {
|
|
39
|
+
[`jest/${name}`]: rule.meta.docs.recommended
|
|
40
|
+
}), {});
|
|
38
41
|
const allRules = Object.keys(rules).reduce((rules, key) => _objectSpread(_objectSpread({}, rules), {}, {
|
|
39
42
|
[`jest/${key}`]: 'error'
|
|
40
43
|
}), {});
|
|
44
|
+
|
|
45
|
+
const createConfig = rules => ({
|
|
46
|
+
plugins: ['jest'],
|
|
47
|
+
env: {
|
|
48
|
+
'jest/globals': true
|
|
49
|
+
},
|
|
50
|
+
rules
|
|
51
|
+
});
|
|
52
|
+
|
|
41
53
|
module.exports = {
|
|
42
54
|
configs: {
|
|
43
|
-
all:
|
|
44
|
-
|
|
45
|
-
env: {
|
|
46
|
-
'jest/globals': true
|
|
47
|
-
},
|
|
48
|
-
rules: allRules
|
|
49
|
-
},
|
|
50
|
-
recommended: {
|
|
51
|
-
plugins: ['jest'],
|
|
52
|
-
env: {
|
|
53
|
-
'jest/globals': true
|
|
54
|
-
},
|
|
55
|
-
rules: {
|
|
56
|
-
'jest/expect-expect': 'warn',
|
|
57
|
-
'jest/no-commented-out-tests': 'warn',
|
|
58
|
-
'jest/no-disabled-tests': 'warn',
|
|
59
|
-
'jest/no-export': 'error',
|
|
60
|
-
'jest/no-focused-tests': 'error',
|
|
61
|
-
'jest/no-identical-title': 'error',
|
|
62
|
-
'jest/no-jest-import': 'error',
|
|
63
|
-
'jest/no-mocks-import': 'error',
|
|
64
|
-
'jest/no-jasmine-globals': 'warn',
|
|
65
|
-
'jest/no-standalone-expect': 'error',
|
|
66
|
-
'jest/no-test-callback': 'error',
|
|
67
|
-
'jest/no-test-prefixes': 'error',
|
|
68
|
-
'jest/no-try-expect': 'error',
|
|
69
|
-
'jest/valid-describe': 'error',
|
|
70
|
-
'jest/valid-expect': 'error',
|
|
71
|
-
'jest/valid-expect-in-promise': 'error'
|
|
72
|
-
}
|
|
73
|
-
},
|
|
55
|
+
all: createConfig(allRules),
|
|
56
|
+
recommended: createConfig(recommendedRules),
|
|
74
57
|
style: {
|
|
75
58
|
plugins: ['jest'],
|
|
76
59
|
rules: {
|
|
@@ -13,7 +13,7 @@ var _default = (0, _utils.createRule)({
|
|
|
13
13
|
docs: {
|
|
14
14
|
category: 'Best Practices',
|
|
15
15
|
description: 'Disallow alias methods',
|
|
16
|
-
recommended:
|
|
16
|
+
recommended: false
|
|
17
17
|
},
|
|
18
18
|
messages: {
|
|
19
19
|
replaceAlias: `Replace {{ alias }}() with its canonical name of {{ canonical }}()`
|
package/lib/rules/no-export.js
CHANGED
|
@@ -15,7 +15,7 @@ var _default = (0, _utils.createRule)({
|
|
|
15
15
|
docs: {
|
|
16
16
|
category: 'Best Practices',
|
|
17
17
|
description: 'Disallow Jasmine globals',
|
|
18
|
-
recommended: '
|
|
18
|
+
recommended: 'warn'
|
|
19
19
|
},
|
|
20
20
|
messages: {
|
|
21
21
|
illegalGlobal: 'Illegal usage of global `{{ global }}`, prefer `{{ replacement }}`',
|
|
@@ -46,7 +46,7 @@ var _default = (0, _utils.createRule)({
|
|
|
46
46
|
docs: {
|
|
47
47
|
category: 'Best Practices',
|
|
48
48
|
description: 'Prevents expects that are outside of an it or test block.',
|
|
49
|
-
recommended:
|
|
49
|
+
recommended: 'error'
|
|
50
50
|
},
|
|
51
51
|
messages: {
|
|
52
52
|
unexpectedExpect: 'Expect must be inside of a test block.'
|
|
@@ -25,7 +25,7 @@ var _default = (0, _utils.createRule)({
|
|
|
25
25
|
docs: {
|
|
26
26
|
category: 'Possible Errors',
|
|
27
27
|
description: 'Enforce valid `describe()` callback',
|
|
28
|
-
recommended: '
|
|
28
|
+
recommended: 'error'
|
|
29
29
|
},
|
|
30
30
|
messages: {
|
|
31
31
|
nameAndCallback: 'Describe requires name and callback arguments',
|
package/lib/rules/valid-title.js
CHANGED
|
@@ -25,6 +25,23 @@ const doesBinaryExpressionContainStringNode = binaryExp => {
|
|
|
25
25
|
|
|
26
26
|
const quoteStringValue = node => node.type === _experimentalUtils.AST_NODE_TYPES.TemplateLiteral ? `\`${node.quasis[0].value.raw}\`` : node.raw;
|
|
27
27
|
|
|
28
|
+
const compileMatcherPatterns = matchers => {
|
|
29
|
+
if (typeof matchers === 'string') {
|
|
30
|
+
const matcher = new RegExp(matchers, 'u');
|
|
31
|
+
return {
|
|
32
|
+
describe: matcher,
|
|
33
|
+
test: matcher,
|
|
34
|
+
it: matcher
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
describe: matchers.describe ? new RegExp(matchers.describe, 'u') : null,
|
|
40
|
+
test: matchers.test ? new RegExp(matchers.test, 'u') : null,
|
|
41
|
+
it: matchers.it ? new RegExp(matchers.it, 'u') : null
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
28
45
|
var _default = (0, _utils.createRule)({
|
|
29
46
|
name: __filename,
|
|
30
47
|
meta: {
|
|
@@ -38,7 +55,9 @@ var _default = (0, _utils.createRule)({
|
|
|
38
55
|
emptyTitle: '{{ jestFunctionName }} should not have an empty title',
|
|
39
56
|
duplicatePrefix: 'should not have duplicate prefix',
|
|
40
57
|
accidentalSpace: 'should not have leading or trailing spaces',
|
|
41
|
-
disallowedWord: '"{{ word }}" is not allowed in test titles.'
|
|
58
|
+
disallowedWord: '"{{ word }}" is not allowed in test titles.',
|
|
59
|
+
mustNotMatch: '{{ jestFunctionName }} should not match {{ pattern }}',
|
|
60
|
+
mustMatch: '{{ jestFunctionName }} should match {{ pattern }}'
|
|
42
61
|
},
|
|
43
62
|
type: 'suggestion',
|
|
44
63
|
schema: [{
|
|
@@ -53,6 +72,44 @@ var _default = (0, _utils.createRule)({
|
|
|
53
72
|
items: {
|
|
54
73
|
type: 'string'
|
|
55
74
|
}
|
|
75
|
+
},
|
|
76
|
+
mustNotMatch: {
|
|
77
|
+
oneOf: [{
|
|
78
|
+
type: 'string'
|
|
79
|
+
}, {
|
|
80
|
+
type: 'object',
|
|
81
|
+
properties: {
|
|
82
|
+
describe: {
|
|
83
|
+
type: 'string'
|
|
84
|
+
},
|
|
85
|
+
test: {
|
|
86
|
+
type: 'string'
|
|
87
|
+
},
|
|
88
|
+
it: {
|
|
89
|
+
type: 'string'
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
additionalProperties: false
|
|
93
|
+
}]
|
|
94
|
+
},
|
|
95
|
+
mustMatch: {
|
|
96
|
+
oneOf: [{
|
|
97
|
+
type: 'string'
|
|
98
|
+
}, {
|
|
99
|
+
type: 'object',
|
|
100
|
+
properties: {
|
|
101
|
+
describe: {
|
|
102
|
+
type: 'string'
|
|
103
|
+
},
|
|
104
|
+
test: {
|
|
105
|
+
type: 'string'
|
|
106
|
+
},
|
|
107
|
+
it: {
|
|
108
|
+
type: 'string'
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
additionalProperties: false
|
|
112
|
+
}]
|
|
56
113
|
}
|
|
57
114
|
},
|
|
58
115
|
additionalProperties: false
|
|
@@ -66,9 +123,13 @@ var _default = (0, _utils.createRule)({
|
|
|
66
123
|
|
|
67
124
|
create(context, [{
|
|
68
125
|
ignoreTypeOfDescribeName,
|
|
69
|
-
disallowedWords = []
|
|
126
|
+
disallowedWords = [],
|
|
127
|
+
mustNotMatch,
|
|
128
|
+
mustMatch
|
|
70
129
|
}]) {
|
|
71
130
|
const disallowedWordsRegexp = new RegExp(`\\b(${disallowedWords.join('|')})\\b`, 'iu');
|
|
131
|
+
const mustNotMatchPatterns = compileMatcherPatterns(mustNotMatch !== null && mustNotMatch !== void 0 ? mustNotMatch : {});
|
|
132
|
+
const mustMatchPatterns = compileMatcherPatterns(mustMatch !== null && mustMatch !== void 0 ? mustMatch : {});
|
|
72
133
|
return {
|
|
73
134
|
CallExpression(node) {
|
|
74
135
|
if (!(0, _utils.isDescribe)(node) && !(0, _utils.isTestCase)(node)) {
|
|
@@ -142,6 +203,39 @@ var _default = (0, _utils.createRule)({
|
|
|
142
203
|
fix: fixer => [fixer.replaceTextRange(argument.range, quoteStringValue(argument).replace(/^([`'"]).+? /u, '$1'))]
|
|
143
204
|
});
|
|
144
205
|
}
|
|
206
|
+
|
|
207
|
+
const [jestFunctionName] = nodeName.split('.');
|
|
208
|
+
const mustNotMatchPattern = mustNotMatchPatterns[jestFunctionName];
|
|
209
|
+
|
|
210
|
+
if (mustNotMatchPattern) {
|
|
211
|
+
if (mustNotMatchPattern.test(title)) {
|
|
212
|
+
context.report({
|
|
213
|
+
messageId: 'mustNotMatch',
|
|
214
|
+
node: argument,
|
|
215
|
+
data: {
|
|
216
|
+
jestFunctionName,
|
|
217
|
+
pattern: mustNotMatchPattern
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const mustMatchPattern = mustMatchPatterns[jestFunctionName];
|
|
225
|
+
|
|
226
|
+
if (mustMatchPattern) {
|
|
227
|
+
if (!mustMatchPattern.test(title)) {
|
|
228
|
+
context.report({
|
|
229
|
+
messageId: 'mustMatch',
|
|
230
|
+
node: argument,
|
|
231
|
+
data: {
|
|
232
|
+
jestFunctionName,
|
|
233
|
+
pattern: mustMatchPattern
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
145
239
|
}
|
|
146
240
|
|
|
147
241
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-jest",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.18.0",
|
|
4
4
|
"description": "Eslint rules for Jest",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"eslint",
|
|
@@ -23,10 +23,8 @@
|
|
|
23
23
|
"build": "babel --extensions .js,.ts src --out-dir lib --copy-files",
|
|
24
24
|
"postbuild": "rimraf lib/__tests__ lib/**/__tests__",
|
|
25
25
|
"lint": "eslint . --ignore-pattern '!.eslintrc.js' --ext js,ts",
|
|
26
|
-
"
|
|
27
|
-
"prepublishOnly": "yarn build",
|
|
26
|
+
"prepack": "yarn build",
|
|
28
27
|
"prettylint": "prettylint docs/**/*.md README.md package.json",
|
|
29
|
-
"pretest": "yarn build",
|
|
30
28
|
"test": "jest",
|
|
31
29
|
"tools:generate-rules-table": "ts-node -T tools/generate-rules-table",
|
|
32
30
|
"typecheck": "tsc -p ."
|
|
@@ -120,7 +118,7 @@
|
|
|
120
118
|
"eslint-plugin-prettier": "^3.0.0",
|
|
121
119
|
"husky": "^3.0.9",
|
|
122
120
|
"jest": "^25.2.0",
|
|
123
|
-
"jest-runner-eslint": "^0.
|
|
121
|
+
"jest-runner-eslint": "^0.10.0",
|
|
124
122
|
"lint-staged": "^9.4.2",
|
|
125
123
|
"prettier": "^1.19.1",
|
|
126
124
|
"prettylint": "^1.0.0",
|