eslint-plugin-jest 23.15.0 → 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 CHANGED
@@ -1,3 +1,32 @@
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
+
8
+ ## [23.17.1](https://github.com/jest-community/eslint-plugin-jest/compare/v23.17.0...v23.17.1) (2020-06-23)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **lowercase-name:** ignore all top level describes when option is true ([#614](https://github.com/jest-community/eslint-plugin-jest/issues/614)) ([624018a](https://github.com/jest-community/eslint-plugin-jest/commit/624018aa181e7c0ce87457a4f9c212c7891987a8)), closes [#613](https://github.com/jest-community/eslint-plugin-jest/issues/613)
14
+
15
+ # [23.17.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.16.0...v23.17.0) (2020-06-23)
16
+
17
+
18
+ ### Features
19
+
20
+ * **lowercase-name:** support `ignoreTopLevelDescribe` option ([#611](https://github.com/jest-community/eslint-plugin-jest/issues/611)) ([36fdcc5](https://github.com/jest-community/eslint-plugin-jest/commit/36fdcc553ca40bc2ca2e9ca7e04f8e9e4a315274)), closes [#247](https://github.com/jest-community/eslint-plugin-jest/issues/247)
21
+
22
+ # [23.16.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.15.0...v23.16.0) (2020-06-21)
23
+
24
+
25
+ ### Features
26
+
27
+ * create `no-conditional-expect` rule ([aba53e4](https://github.com/jest-community/eslint-plugin-jest/commit/aba53e4061f3b636ab0c0270e183c355c6f301e0))
28
+ * deprecate `no-try-expect` in favor of `no-conditional-expect` ([6d07cad](https://github.com/jest-community/eslint-plugin-jest/commit/6d07cadd5f78ed7a64a86792931d49d3cd943d69))
29
+
1
30
  # [23.15.0](https://github.com/jest-community/eslint-plugin-jest/compare/v23.14.0...v23.15.0) (2020-06-21)
2
31
 
3
32
 
package/README.md CHANGED
@@ -134,6 +134,7 @@ installations requiring long-term consistency.
134
134
  | [lowercase-name](docs/rules/lowercase-name.md) | Enforce lowercase test names | | ![fixable][] |
135
135
  | [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods | ![style][] | ![fixable][] |
136
136
  | [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests | ![recommended][] | |
137
+ | [no-conditional-expect](docs/rules/no-conditional-expect.md) | Prevent calling `expect` conditionally | | |
137
138
  | [no-deprecated-functions](docs/rules/no-deprecated-functions.md) | Disallow use of deprecated functions | | ![fixable][] |
138
139
  | [no-disabled-tests](docs/rules/no-disabled-tests.md) | Disallow disabled tests | ![recommended][] | |
139
140
  | [no-duplicate-hooks](docs/rules/no-duplicate-hooks.md) | Disallow duplicate setup and teardown hooks | | |
@@ -151,7 +152,6 @@ installations requiring long-term consistency.
151
152
  | [no-test-callback](docs/rules/no-test-callback.md) | Avoid using a callback in asynchronous tests | ![recommended][] | ![suggest][] |
152
153
  | [no-test-prefixes](docs/rules/no-test-prefixes.md) | Use `.only` and `.skip` over `f` and `x` | ![recommended][] | ![fixable][] |
153
154
  | [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests | | |
154
- | [no-try-expect](docs/rules/no-try-expect.md) | Prefer using toThrow for exception tests | ![recommended][] | |
155
155
  | [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` OR `toHaveBeenCalledWith()` | | |
156
156
  | [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | ![suggest][] |
157
157
  | [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md) | Suggest to have all hooks at top level | | |
@@ -86,3 +86,21 @@ Example of **correct** code for the `{ "allowedPrefixes": ["GET"] }` option:
86
86
 
87
87
  describe('GET /live');
88
88
  ```
89
+
90
+ ### `ignoreTopLevelDescribe`
91
+
92
+ This option can be set to allow only the top-level `describe` blocks to have a
93
+ title starting with an upper-case letter.
94
+
95
+ Example of **correct** code for the `{ "ignoreTopLevelDescribe": true }` option:
96
+
97
+ ```js
98
+ /* eslint jest/lowercase-name: ["error", { "ignoreTopLevelDescribe": true }] */
99
+ describe('MyClass', () => {
100
+ describe('#myMethod', () => {
101
+ it('does things', () => {
102
+ //
103
+ });
104
+ });
105
+ });
106
+ ```
@@ -0,0 +1,70 @@
1
+ # Prevent calling `expect` conditionally (`no-conditional-expect`)
2
+
3
+ This rule prevents the use of `expect` in conditional blocks, such as `if`s &
4
+ `catch`s.
5
+
6
+ ## Rule Details
7
+
8
+ Jest considered a test to have failed if it throws an error, rather than on if
9
+ any particular function is called, meaning conditional calls to `expect` could
10
+ result in tests silently being skipped.
11
+
12
+ Additionally, conditionals tend to make tests more brittle and complex, as they
13
+ increase the amount of mental thinking needed to understand what is actually
14
+ being tested.
15
+
16
+ While `expect.assertions` & `expect.hasAssertions` can help prevent tests from
17
+ silently being skipped, when combined with conditionals they typically result in
18
+ even more complexity being introduced.
19
+
20
+ The following patterns are warnings:
21
+
22
+ ```js
23
+ it('foo', () => {
24
+ doTest && expect(1).toBe(2);
25
+ });
26
+
27
+ it('bar', () => {
28
+ if (!skipTest) {
29
+ expect(1).toEqual(2);
30
+ }
31
+ });
32
+
33
+ it('baz', async () => {
34
+ try {
35
+ await foo();
36
+ } catch (err) {
37
+ expect(err).toMatchObject({ code: 'MODULE_NOT_FOUND' });
38
+ }
39
+ });
40
+ ```
41
+
42
+ The following patterns are not warnings:
43
+
44
+ ```js
45
+ it('foo', () => {
46
+ expect(!value).toBe(false);
47
+ });
48
+
49
+ function getValue() {
50
+ if (process.env.FAIL) {
51
+ return 1;
52
+ }
53
+
54
+ return 2;
55
+ }
56
+
57
+ it('foo', () => {
58
+ expect(getValue()).toBe(2);
59
+ });
60
+
61
+ it('validates the request', () => {
62
+ try {
63
+ processRequest(request);
64
+ } catch {
65
+ // ignore errors
66
+ } finally {
67
+ expect(validRequest).toHaveBeenCalledWith(request);
68
+ }
69
+ });
70
+ ```
@@ -1,5 +1,12 @@
1
1
  # Prevent catch assertions in tests (`no-try-expect`)
2
2
 
3
+ ## Deprecated
4
+
5
+ This rule has been deprecated in favor of
6
+ [`no-conditional-expect`](no-conditional-expect.md).
7
+
8
+ ---
9
+
3
10
  This rule prevents the use of `expect` inside `catch` blocks.
4
11
 
5
12
  ## Rule Details
@@ -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) => Object.assign(acc, {
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
- plugins: ['jest'],
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: {
@@ -34,7 +34,7 @@ var _default = (0, _utils.createRule)({
34
34
  docs: {
35
35
  category: 'Best Practices',
36
36
  description: 'Enforce assertion to be made in a test body',
37
- recommended: false
37
+ recommended: 'warn'
38
38
  },
39
39
  messages: {
40
40
  noAssertions: 'Test has no assertions'
@@ -58,6 +58,10 @@ var _default = (0, _utils.createRule)({
58
58
  type: 'string'
59
59
  },
60
60
  additionalItems: false
61
+ },
62
+ ignoreTopLevelDescribe: {
63
+ type: 'boolean',
64
+ default: false
61
65
  }
62
66
  },
63
67
  additionalProperties: false
@@ -65,19 +69,30 @@ var _default = (0, _utils.createRule)({
65
69
  },
66
70
  defaultOptions: [{
67
71
  ignore: [],
68
- allowedPrefixes: []
72
+ allowedPrefixes: [],
73
+ ignoreTopLevelDescribe: false
69
74
  }],
70
75
 
71
76
  create(context, [{
72
77
  ignore = [],
73
- allowedPrefixes = []
78
+ allowedPrefixes = [],
79
+ ignoreTopLevelDescribe
74
80
  }]) {
81
+ let numberOfDescribeBlocks = 0;
75
82
  return {
76
83
  CallExpression(node) {
77
84
  if (!isJestFunctionWithLiteralArg(node)) {
78
85
  return;
79
86
  }
80
87
 
88
+ if ((0, _utils.isDescribe)(node)) {
89
+ numberOfDescribeBlocks++;
90
+
91
+ if (ignoreTopLevelDescribe && numberOfDescribeBlocks === 1) {
92
+ return;
93
+ }
94
+ }
95
+
81
96
  const erroneousMethod = jestFunctionName(node, allowedPrefixes);
82
97
 
83
98
  if (erroneousMethod && !ignore.includes(node.callee.name)) {
@@ -98,6 +113,12 @@ var _default = (0, _utils.createRule)({
98
113
 
99
114
  });
100
115
  }
116
+ },
117
+
118
+ 'CallExpression:exit'(node) {
119
+ if ((0, _utils.isDescribe)(node)) {
120
+ numberOfDescribeBlocks--;
121
+ }
101
122
  }
102
123
 
103
124
  };
@@ -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: 'warn'
16
+ recommended: false
17
17
  },
18
18
  messages: {
19
19
  replaceAlias: `Replace {{ alias }}() with its canonical name of {{ canonical }}()`
@@ -17,7 +17,7 @@ var _default = (0, _utils.createRule)({
17
17
  docs: {
18
18
  category: 'Best Practices',
19
19
  description: 'Disallow commented out tests',
20
- recommended: false
20
+ recommended: 'warn'
21
21
  },
22
22
  messages: {
23
23
  commentedTests: 'Some tests seem to be commented'
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _utils = require("./utils");
9
+
10
+ var _default = (0, _utils.createRule)({
11
+ name: __filename,
12
+ meta: {
13
+ docs: {
14
+ description: 'Prevent calling `expect` conditionally',
15
+ category: 'Best Practices',
16
+ recommended: false
17
+ },
18
+ messages: {
19
+ conditionalExpect: 'Avoid calling `expect` conditionally`'
20
+ },
21
+ type: 'problem',
22
+ schema: []
23
+ },
24
+ defaultOptions: [],
25
+
26
+ create(context) {
27
+ let conditionalDepth = 0;
28
+ let inTestCase = false;
29
+
30
+ const increaseConditionalDepth = () => inTestCase && conditionalDepth++;
31
+
32
+ const decreaseConditionalDepth = () => inTestCase && conditionalDepth--;
33
+
34
+ return {
35
+ FunctionDeclaration(node) {
36
+ const declaredVariables = context.getDeclaredVariables(node);
37
+ const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
38
+
39
+ if (testCallExpressions.length > 0) {
40
+ inTestCase = true;
41
+ }
42
+ },
43
+
44
+ CallExpression(node) {
45
+ if ((0, _utils.isTestCase)(node)) {
46
+ inTestCase = true;
47
+ }
48
+
49
+ if (inTestCase && (0, _utils.isExpectCall)(node) && conditionalDepth > 0) {
50
+ context.report({
51
+ messageId: 'conditionalExpect',
52
+ node
53
+ });
54
+ }
55
+ },
56
+
57
+ 'CallExpression:exit'(node) {
58
+ if ((0, _utils.isTestCase)(node)) {
59
+ inTestCase = false;
60
+ }
61
+ },
62
+
63
+ CatchClause: increaseConditionalDepth,
64
+ 'CatchClause:exit': decreaseConditionalDepth,
65
+ IfStatement: increaseConditionalDepth,
66
+ 'IfStatement:exit': decreaseConditionalDepth,
67
+ SwitchStatement: increaseConditionalDepth,
68
+ 'SwitchStatement:exit': decreaseConditionalDepth,
69
+ ConditionalExpression: increaseConditionalDepth,
70
+ 'ConditionalExpression:exit': decreaseConditionalDepth,
71
+ LogicalExpression: increaseConditionalDepth,
72
+ 'LogicalExpression:exit': decreaseConditionalDepth
73
+ };
74
+ }
75
+
76
+ });
77
+
78
+ exports.default = _default;
@@ -13,7 +13,7 @@ var _default = (0, _utils.createRule)({
13
13
  docs: {
14
14
  category: 'Best Practices',
15
15
  description: 'Disallow disabled tests',
16
- recommended: false
16
+ recommended: 'warn'
17
17
  },
18
18
  messages: {
19
19
  missingFunction: 'Test is missing function argument',
@@ -15,7 +15,7 @@ var _default = (0, _utils.createRule)({
15
15
  docs: {
16
16
  category: 'Best Practices',
17
17
  description: 'Prevent exporting from test files',
18
- recommended: false
18
+ recommended: 'error'
19
19
  },
20
20
  messages: {
21
21
  unexpectedExport: `Do not export from a test file.`
@@ -26,7 +26,7 @@ var _default = (0, _utils.createRule)({
26
26
  docs: {
27
27
  category: 'Best Practices',
28
28
  description: 'Disallow focused tests',
29
- recommended: false
29
+ recommended: 'error'
30
30
  },
31
31
  messages: {
32
32
  focusedTest: 'Unexpected focused test.'
@@ -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: 'error'
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: false
49
+ recommended: 'error'
50
50
  },
51
51
  messages: {
52
52
  unexpectedExpect: 'Expect must be inside of a test block.'
@@ -15,7 +15,7 @@ var _default = (0, _utils.createRule)({
15
15
  docs: {
16
16
  category: 'Best Practices',
17
17
  description: 'Avoid using a callback in asynchronous tests',
18
- recommended: false,
18
+ recommended: 'error',
19
19
  suggestion: true
20
20
  },
21
21
  messages: {
@@ -13,8 +13,10 @@ var _default = (0, _utils.createRule)({
13
13
  docs: {
14
14
  description: 'Prefer using toThrow for exception tests',
15
15
  category: 'Best Practices',
16
- recommended: false
16
+ recommended: 'error'
17
17
  },
18
+ deprecated: true,
19
+ replacedBy: ['no-conditional-expect'],
18
20
  messages: {
19
21
  noTryExpect: ['Tests should use Jest‘s exception helpers.', 'Use "expect(() => yourFunction()).toThrow()" for synchronous tests,', 'or "await expect(yourFunction()).rejects.toThrow()" for async tests'].join(' ')
20
22
  },
@@ -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: 'warn'
28
+ recommended: 'error'
29
29
  },
30
30
  messages: {
31
31
  nameAndCallback: 'Describe requires name and callback arguments',
@@ -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.15.0",
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
- "prepare": "yarn build && yarn postbuild",
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 ."
@@ -102,9 +100,9 @@
102
100
  "@semantic-release/changelog": "^3.0.5",
103
101
  "@semantic-release/git": "^7.0.17",
104
102
  "@types/dedent": "^0.7.0",
105
- "@types/eslint": "^6.1.3",
106
103
  "@types/jest": "^25.1.0",
107
104
  "@types/node": "^12.6.6",
105
+ "@types/prettier": "^1.19.0",
108
106
  "@typescript-eslint/eslint-plugin": "^2.5.0",
109
107
  "@typescript-eslint/parser": "^2.5.0",
110
108
  "babel-jest": "^25.2.0",
@@ -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.8.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",