eslint-plugin-jest 24.4.2 → 26.1.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.
Files changed (77) hide show
  1. package/README.md +75 -50
  2. package/docs/rules/expect-expect.md +42 -1
  3. package/docs/rules/max-nested-describe.md +4 -5
  4. package/docs/rules/no-conditional-expect.md +57 -3
  5. package/docs/rules/no-conditional-in-test.md +79 -0
  6. package/docs/rules/no-deprecated-functions.md +5 -0
  7. package/docs/rules/no-done-callback.md +3 -3
  8. package/docs/rules/no-if.md +5 -0
  9. package/docs/rules/no-standalone-expect.md +3 -3
  10. package/docs/rules/no-test-return-statement.md +1 -2
  11. package/docs/rules/prefer-comparison-matcher.md +55 -0
  12. package/docs/rules/prefer-equality-matcher.md +29 -0
  13. package/docs/rules/prefer-expect-assertions.md +126 -0
  14. package/docs/rules/prefer-expect-resolves.md +53 -0
  15. package/docs/rules/prefer-hooks-on-top.md +72 -48
  16. package/docs/rules/{lowercase-name.md → prefer-lowercase-title.md} +7 -7
  17. package/docs/rules/prefer-snapshot-hint.md +188 -0
  18. package/docs/rules/prefer-to-be.md +53 -0
  19. package/docs/rules/require-hook.md +187 -0
  20. package/docs/rules/require-top-level-describe.md +28 -0
  21. package/docs/rules/{valid-describe.md → valid-describe-callback.md} +1 -1
  22. package/docs/rules/valid-expect-in-promise.md +55 -14
  23. package/docs/rules/valid-expect.md +13 -0
  24. package/docs/rules/valid-title.md +30 -2
  25. package/lib/index.js +2 -3
  26. package/lib/processors/snapshot-processor.js +1 -1
  27. package/lib/rules/consistent-test-it.js +20 -20
  28. package/lib/rules/detectJestVersion.js +29 -0
  29. package/lib/rules/expect-expect.js +25 -11
  30. package/lib/rules/max-nested-describe.js +5 -5
  31. package/lib/rules/no-conditional-expect.js +9 -9
  32. package/lib/rules/no-conditional-in-test.js +60 -0
  33. package/lib/rules/no-deprecated-functions.js +14 -32
  34. package/lib/rules/no-done-callback.js +10 -10
  35. package/lib/rules/no-export.js +6 -6
  36. package/lib/rules/no-focused-tests.js +11 -11
  37. package/lib/rules/no-identical-title.js +3 -3
  38. package/lib/rules/no-if.js +13 -11
  39. package/lib/rules/no-interpolation-in-snapshots.js +6 -6
  40. package/lib/rules/no-jasmine-globals.js +10 -10
  41. package/lib/rules/no-large-snapshots.js +11 -11
  42. package/lib/rules/no-standalone-expect.js +14 -14
  43. package/lib/rules/no-test-prefixes.js +6 -6
  44. package/lib/rules/no-test-return-statement.js +8 -8
  45. package/lib/rules/prefer-comparison-matcher.js +139 -0
  46. package/lib/rules/prefer-equality-matcher.js +98 -0
  47. package/lib/rules/prefer-expect-assertions.js +93 -11
  48. package/lib/rules/prefer-expect-resolves.js +48 -0
  49. package/lib/rules/prefer-hooks-on-top.js +1 -1
  50. package/lib/rules/{lowercase-name.js → prefer-lowercase-title.js} +20 -1
  51. package/lib/rules/prefer-snapshot-hint.js +112 -0
  52. package/lib/rules/prefer-spy-on.js +9 -9
  53. package/lib/rules/prefer-to-be.js +136 -0
  54. package/lib/rules/prefer-to-contain.js +19 -67
  55. package/lib/rules/prefer-to-have-length.js +9 -14
  56. package/lib/rules/prefer-todo.js +9 -9
  57. package/lib/rules/require-hook.js +121 -0
  58. package/lib/rules/require-top-level-describe.js +40 -6
  59. package/lib/rules/utils.js +34 -30
  60. package/lib/rules/{valid-describe.js → valid-describe-callback.js} +9 -9
  61. package/lib/rules/valid-expect-in-promise.js +336 -67
  62. package/lib/rules/valid-expect.js +36 -19
  63. package/lib/rules/valid-title.js +61 -61
  64. package/package.json +40 -27
  65. package/CHANGELOG.md +0 -513
  66. package/docs/rules/no-expect-resolves.md +0 -47
  67. package/docs/rules/no-truthy-falsy.md +0 -53
  68. package/docs/rules/no-try-expect.md +0 -63
  69. package/docs/rules/prefer-inline-snapshots.md +0 -51
  70. package/docs/rules/prefer-to-be-null.md +0 -33
  71. package/docs/rules/prefer-to-be-undefined.md +0 -33
  72. package/lib/rules/no-expect-resolves.js +0 -40
  73. package/lib/rules/no-truthy-falsy.js +0 -58
  74. package/lib/rules/no-try-expect.js +0 -89
  75. package/lib/rules/prefer-inline-snapshots.js +0 -69
  76. package/lib/rules/prefer-to-be-null.js +0 -67
  77. package/lib/rules/prefer-to-be-undefined.js +0 -67
@@ -0,0 +1,187 @@
1
+ # Require setup and teardown code to be within a hook (`require-hook`)
2
+
3
+ Often while writing tests you have some setup work that needs to happen before
4
+ tests run, and you have some finishing work that needs to happen after tests
5
+ run. Jest provides helper functions to handle this.
6
+
7
+ It's common when writing tests to need to perform setup work that needs to
8
+ happen before tests run, and finishing work after tests run.
9
+
10
+ Because Jest executes all `describe` handlers in a test file _before_ it
11
+ executes any of the actual tests, it's important to ensure setup and teardown
12
+ work is done inside `before*` and `after*` handlers respectively, rather than
13
+ inside the `describe` blocks.
14
+
15
+ ## Rule details
16
+
17
+ This rule flags any expression that is either at the toplevel of a test file or
18
+ directly within the body of a `describe`, _except_ for the following:
19
+
20
+ - `import` statements
21
+ - `const` variables
22
+ - `let` _declarations_, and initializations to `null` or `undefined`
23
+ - Classes
24
+ - Types
25
+ - Calls to the standard Jest globals
26
+
27
+ This rule flags any function calls within test files that are directly within
28
+ the body of a `describe`, and suggests wrapping them in one of the four
29
+ lifecycle hooks.
30
+
31
+ Here is a slightly contrived test file showcasing some common cases that would
32
+ be flagged:
33
+
34
+ ```js
35
+ import { database, isCity } from '../database';
36
+ import { Logger } from '../../../src/Logger';
37
+ import { loadCities } from '../api';
38
+
39
+ jest.mock('../api');
40
+
41
+ const initializeCityDatabase = () => {
42
+ database.addCity('Vienna');
43
+ database.addCity('San Juan');
44
+ database.addCity('Wellington');
45
+ };
46
+
47
+ const clearCityDatabase = () => {
48
+ database.clear();
49
+ };
50
+
51
+ initializeCityDatabase();
52
+
53
+ test('that persists cities', () => {
54
+ expect(database.cities.length).toHaveLength(3);
55
+ });
56
+
57
+ test('city database has Vienna', () => {
58
+ expect(isCity('Vienna')).toBeTruthy();
59
+ });
60
+
61
+ test('city database has San Juan', () => {
62
+ expect(isCity('San Juan')).toBeTruthy();
63
+ });
64
+
65
+ describe('when loading cities from the api', () => {
66
+ let consoleWarnSpy = jest.spyOn(console, 'warn');
67
+
68
+ loadCities.mockResolvedValue(['Wellington', 'London']);
69
+
70
+ it('does not duplicate cities', async () => {
71
+ await database.loadCities();
72
+
73
+ expect(database.cities).toHaveLength(4);
74
+ });
75
+
76
+ it('logs any duplicates', async () => {
77
+ await database.loadCities();
78
+
79
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
80
+ 'Ignored duplicate cities: Wellington',
81
+ );
82
+ });
83
+ });
84
+
85
+ clearCityDatabase();
86
+ ```
87
+
88
+ Here is the same slightly contrived test file showcasing the same common cases
89
+ but in ways that would be **not** flagged:
90
+
91
+ ```js
92
+ import { database, isCity } from '../database';
93
+ import { Logger } from '../../../src/Logger';
94
+ import { loadCities } from '../api';
95
+
96
+ jest.mock('../api');
97
+
98
+ const initializeCityDatabase = () => {
99
+ database.addCity('Vienna');
100
+ database.addCity('San Juan');
101
+ database.addCity('Wellington');
102
+ };
103
+
104
+ const clearCityDatabase = () => {
105
+ database.clear();
106
+ };
107
+
108
+ beforeEach(() => {
109
+ initializeCityDatabase();
110
+ });
111
+
112
+ test('that persists cities', () => {
113
+ expect(database.cities.length).toHaveLength(3);
114
+ });
115
+
116
+ test('city database has Vienna', () => {
117
+ expect(isCity('Vienna')).toBeTruthy();
118
+ });
119
+
120
+ test('city database has San Juan', () => {
121
+ expect(isCity('San Juan')).toBeTruthy();
122
+ });
123
+
124
+ describe('when loading cities from the api', () => {
125
+ let consoleWarnSpy;
126
+
127
+ beforeEach(() => {
128
+ consoleWarnSpy = jest.spyOn(console, 'warn');
129
+ loadCities.mockResolvedValue(['Wellington', 'London']);
130
+ });
131
+
132
+ it('does not duplicate cities', async () => {
133
+ await database.loadCities();
134
+
135
+ expect(database.cities).toHaveLength(4);
136
+ });
137
+
138
+ it('logs any duplicates', async () => {
139
+ await database.loadCities();
140
+
141
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
142
+ 'Ignored duplicate cities: Wellington',
143
+ );
144
+ });
145
+ });
146
+
147
+ afterEach(() => {
148
+ clearCityDatabase();
149
+ });
150
+ ```
151
+
152
+ ## Options
153
+
154
+ If there are methods that you want to call outside of hooks and tests, you can
155
+ mark them as allowed using the `allowedFunctionCalls` option.
156
+
157
+ ```json
158
+ {
159
+ "jest/require-hook": [
160
+ "error",
161
+ {
162
+ "allowedFunctionCalls": ["enableAutoDestroy"]
163
+ }
164
+ ]
165
+ }
166
+ ```
167
+
168
+ Examples of **correct** code when using
169
+ `{ "allowedFunctionCalls": ["enableAutoDestroy"] }` option:
170
+
171
+ ```js
172
+ /* eslint jest/require-hook: ["error", { "allowedFunctionCalls": ["enableAutoDestroy"] }] */
173
+
174
+ import { enableAutoDestroy, mount } from '@vue/test-utils';
175
+ import { initDatabase, tearDownDatabase } from './databaseUtils';
176
+
177
+ enableAutoDestroy(afterEach);
178
+
179
+ beforeEach(initDatabase);
180
+ afterEach(tearDownDatabase);
181
+
182
+ describe('Foo', () => {
183
+ test('always returns 42', () => {
184
+ expect(global.getAnswer()).toBe(42);
185
+ });
186
+ });
187
+ ```
@@ -47,6 +47,34 @@ describe('test suite', () => {
47
47
  });
48
48
  ```
49
49
 
50
+ You can also enforce a limit on the number of describes allowed at the top-level
51
+ using the `maxNumberOfTopLevelDescribes` option:
52
+
53
+ ```json
54
+ {
55
+ "jest/require-top-level-describe": [
56
+ "error",
57
+ {
58
+ "maxNumberOfTopLevelDescribes": 2
59
+ }
60
+ ]
61
+ }
62
+ ```
63
+
64
+ Examples of **incorrect** code with the above config:
65
+
66
+ ```js
67
+ describe('test suite', () => {
68
+ it('test', () => {});
69
+ });
70
+
71
+ describe('test suite', () => {});
72
+
73
+ describe('test suite', () => {});
74
+ ```
75
+
76
+ This option defaults to `Infinity`, allowing any number of top-level describes.
77
+
50
78
  ## When Not To Use It
51
79
 
52
80
  Don't use this rule on non-jest test files.
@@ -1,4 +1,4 @@
1
- # Enforce valid `describe()` callback (`valid-describe`)
1
+ # Enforce valid `describe()` callback (`valid-describe-callback`)
2
2
 
3
3
  Using an improper `describe()` callback function can lead to unexpected test
4
4
  errors.
@@ -1,31 +1,72 @@
1
- # Enforce having return statement when testing with promises (`valid-expect-in-promise`)
1
+ # Ensure promises that have expectations in their chain are valid (`valid-expect-in-promise`)
2
2
 
3
- Ensure to return promise when having assertions in `then` or `catch` block of
4
- promise
3
+ Ensure promises that include expectations are returned or awaited.
5
4
 
6
5
  ## Rule details
7
6
 
8
- This rule looks for tests that have assertions in `then` and `catch` methods on
9
- promises that are not returned by the test.
7
+ This rule flags any promises within the body of a test that include expectations
8
+ that have either not been returned or awaited.
10
9
 
11
- ### Default configuration
12
-
13
- The following pattern is considered warning:
10
+ The following patterns is considered warning:
14
11
 
15
12
  ```js
16
- it('promise test', () => {
17
- somePromise.then(data => {
18
- expect(data).toEqual('foo');
13
+ it('promises a person', () => {
14
+ api.getPersonByName('bob').then(person => {
15
+ expect(person).toHaveProperty('name', 'Bob');
16
+ });
17
+ });
18
+
19
+ it('promises a counted person', () => {
20
+ const promise = api.getPersonByName('bob').then(person => {
21
+ expect(person).toHaveProperty('name', 'Bob');
22
+ });
23
+
24
+ promise.then(() => {
25
+ expect(analytics.gottenPeopleCount).toBe(1);
19
26
  });
20
27
  });
28
+
29
+ it('promises multiple people', () => {
30
+ const firstPromise = api.getPersonByName('bob').then(person => {
31
+ expect(person).toHaveProperty('name', 'Bob');
32
+ });
33
+ const secondPromise = api.getPersonByName('alice').then(person => {
34
+ expect(person).toHaveProperty('name', 'Alice');
35
+ });
36
+
37
+ return Promise.any([firstPromise, secondPromise]);
38
+ });
21
39
  ```
22
40
 
23
41
  The following pattern is not warning:
24
42
 
25
43
  ```js
26
- it('promise test', () => {
27
- return somePromise.then(data => {
28
- expect(data).toEqual('foo');
44
+ it('promises a person', async () => {
45
+ await api.getPersonByName('bob').then(person => {
46
+ expect(person).toHaveProperty('name', 'Bob');
29
47
  });
30
48
  });
49
+
50
+ it('promises a counted person', () => {
51
+ let promise = api.getPersonByName('bob').then(person => {
52
+ expect(person).toHaveProperty('name', 'Bob');
53
+ });
54
+
55
+ promise = promise.then(() => {
56
+ expect(analytics.gottenPeopleCount).toBe(1);
57
+ });
58
+
59
+ return promise;
60
+ });
61
+
62
+ it('promises multiple people', () => {
63
+ const firstPromise = api.getPersonByName('bob').then(person => {
64
+ expect(person).toHaveProperty('name', 'Bob');
65
+ });
66
+ const secondPromise = api.getPersonByName('alice').then(person => {
67
+ expect(person).toHaveProperty('name', 'Alice');
68
+ });
69
+
70
+ return Promise.allSettled([firstPromise, secondPromise]);
71
+ });
31
72
  ```
@@ -38,6 +38,11 @@ This rule is enabled by default.
38
38
  type: 'boolean',
39
39
  default: false,
40
40
  },
41
+ asyncMatchers: {
42
+ type: 'array',
43
+ items: { type: 'string' },
44
+ default: ['toResolve', 'toReject'],
45
+ },
41
46
  minArgs: {
42
47
  type: 'number',
43
48
  minimum: 1,
@@ -78,6 +83,14 @@ test('test1', async () => {
78
83
  test('test2', () => expect(Promise.resolve(2)).resolves.toBe(2));
79
84
  ```
80
85
 
86
+ ### `asyncMatchers`
87
+
88
+ Allows specifying which matchers return promises, and so should be considered
89
+ async when checking if an `expect` should be returned or awaited.
90
+
91
+ By default, this has a list of all the async matchers provided by
92
+ `jest-extended` (namely, `toResolve` and `toReject`).
93
+
81
94
  ### `minArgs` & `maxArgs`
82
95
 
83
96
  Enforces the minimum and maximum number of arguments that `expect` can take, and
@@ -198,8 +198,9 @@ describe('the proper way to handle things', () => {});
198
198
  Defaults: `{}`
199
199
 
200
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`).
201
+ Expression, with an optional message. An object can be provided to apply
202
+ different Regular Expressions (with optional messages) to specific Jest test
203
+ function groups (`describe`, `test`, and `it`).
203
204
 
204
205
  Examples of **incorrect** code when using `mustMatch`:
205
206
 
@@ -226,3 +227,30 @@ describe('the tests that will be run', () => {});
226
227
  test('that the stuff works', () => {});
227
228
  xtest('that errors that thrown have messages', () => {});
228
229
  ```
230
+
231
+ Optionally you can provide a custom message to show for a particular matcher by
232
+ using a tuple at any level where you can provide a matcher:
233
+
234
+ ```js
235
+ const prefixes = ['when', 'with', 'without', 'if', 'unless', 'for'];
236
+ const prefixesList = prefixes.join(' - \n');
237
+
238
+ module.exports = {
239
+ rules: {
240
+ 'jest/valid-title': [
241
+ 'error',
242
+ {
243
+ mustNotMatch: ['\\.$', 'Titles should not end with a full-stop'],
244
+ mustMatch: {
245
+ describe: [
246
+ new RegExp(`^(?:[A-Z]|\\b(${prefixes.join('|')})\\b`, 'u').source,
247
+ `Describe titles should either start with a capital letter or one of the following prefixes: ${prefixesList}`,
248
+ ],
249
+ test: [/[^A-Z]/u.source],
250
+ it: /[^A-Z]/u.source,
251
+ },
252
+ },
253
+ ],
254
+ },
255
+ };
256
+ ```
package/lib/index.js CHANGED
@@ -25,7 +25,7 @@ const importDefault = moduleName => // eslint-disable-next-line @typescript-esli
25
25
  interopRequireDefault(require(moduleName)).default;
26
26
 
27
27
  const rulesDir = (0, _path.join)(__dirname, 'rules');
28
- const excludedFiles = ['__tests__', 'utils'];
28
+ const excludedFiles = ['__tests__', 'detectJestVersion', 'utils'];
29
29
  const rules = (0, _fs.readdirSync)(rulesDir).map(rule => (0, _path.parse)(rule).name).filter(rule => !excludedFiles.includes(rule)).reduce((acc, curr) => ({ ...acc,
30
30
  [curr]: importDefault((0, _path.join)(rulesDir, curr))
31
31
  }), {});
@@ -52,8 +52,7 @@ module.exports = {
52
52
  plugins: ['jest'],
53
53
  rules: {
54
54
  'jest/no-alias-methods': 'warn',
55
- 'jest/prefer-to-be-null': 'error',
56
- 'jest/prefer-to-be-undefined': 'error',
55
+ 'jest/prefer-to-be': 'error',
57
56
  'jest/prefer-to-contain': 'error',
58
57
  'jest/prefer-to-have-length': 'error'
59
58
  }
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.postprocess = exports.preprocess = void 0;
6
+ exports.preprocess = exports.postprocess = void 0;
7
7
 
8
8
  // https://eslint.org/docs/developer-guide/working-with-plugins#processors-in-plugins
9
9
  // https://github.com/typescript-eslint/typescript-eslint/issues/808
@@ -5,13 +5,13 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _experimentalUtils = require("@typescript-eslint/experimental-utils");
8
+ var _utils = require("@typescript-eslint/utils");
9
9
 
10
- var _utils = require("./utils");
10
+ var _utils2 = 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))];
12
+ const buildFixer = (callee, nodeName, preferredTestKeyword) => fixer => [fixer.replaceText(callee.type === _utils.AST_NODE_TYPES.MemberExpression ? callee.object : callee, getPreferredNodeName(nodeName, preferredTestKeyword))];
13
13
 
14
- var _default = (0, _utils.createRule)({
14
+ var _default = (0, _utils2.createRule)({
15
15
  name: __filename,
16
16
  meta: {
17
17
  docs: {
@@ -28,10 +28,10 @@ var _default = (0, _utils.createRule)({
28
28
  type: 'object',
29
29
  properties: {
30
30
  fn: {
31
- enum: [_utils.TestCaseName.it, _utils.TestCaseName.test]
31
+ enum: [_utils2.TestCaseName.it, _utils2.TestCaseName.test]
32
32
  },
33
33
  withinDescribe: {
34
- enum: [_utils.TestCaseName.it, _utils.TestCaseName.test]
34
+ enum: [_utils2.TestCaseName.it, _utils2.TestCaseName.test]
35
35
  }
36
36
  },
37
37
  additionalProperties: false
@@ -39,30 +39,30 @@ var _default = (0, _utils.createRule)({
39
39
  type: 'suggestion'
40
40
  },
41
41
  defaultOptions: [{
42
- fn: _utils.TestCaseName.test,
43
- withinDescribe: _utils.TestCaseName.it
42
+ fn: _utils2.TestCaseName.test,
43
+ withinDescribe: _utils2.TestCaseName.it
44
44
  }],
45
45
 
46
46
  create(context) {
47
47
  const configObj = context.options[0] || {};
48
- const testKeyword = configObj.fn || _utils.TestCaseName.test;
49
- const testKeywordWithinDescribe = configObj.withinDescribe || configObj.fn || _utils.TestCaseName.it;
48
+ const testKeyword = configObj.fn || _utils2.TestCaseName.test;
49
+ const testKeywordWithinDescribe = configObj.withinDescribe || configObj.fn || _utils2.TestCaseName.it;
50
50
  let describeNestingLevel = 0;
51
51
  return {
52
52
  CallExpression(node) {
53
- const nodeName = (0, _utils.getNodeName)(node.callee);
53
+ const nodeName = (0, _utils2.getNodeName)(node.callee);
54
54
 
55
55
  if (!nodeName) {
56
56
  return;
57
57
  }
58
58
 
59
- if ((0, _utils.isDescribeCall)(node)) {
59
+ if ((0, _utils2.isDescribeCall)(node)) {
60
60
  describeNestingLevel++;
61
61
  }
62
62
 
63
- const funcNode = node.callee.type === _experimentalUtils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
63
+ const funcNode = node.callee.type === _utils.AST_NODE_TYPES.TaggedTemplateExpression ? node.callee.tag : node.callee.type === _utils.AST_NODE_TYPES.CallExpression ? node.callee.callee : node.callee;
64
64
 
65
- if ((0, _utils.isTestCaseCall)(node) && describeNestingLevel === 0 && !nodeName.includes(testKeyword)) {
65
+ if ((0, _utils2.isTestCaseCall)(node) && describeNestingLevel === 0 && !nodeName.includes(testKeyword)) {
66
66
  const oppositeTestKeyword = getOppositeTestKeyword(testKeyword);
67
67
  context.report({
68
68
  messageId: 'consistentMethod',
@@ -75,7 +75,7 @@ var _default = (0, _utils.createRule)({
75
75
  });
76
76
  }
77
77
 
78
- if ((0, _utils.isTestCaseCall)(node) && describeNestingLevel > 0 && !nodeName.includes(testKeywordWithinDescribe)) {
78
+ if ((0, _utils2.isTestCaseCall)(node) && describeNestingLevel > 0 && !nodeName.includes(testKeywordWithinDescribe)) {
79
79
  const oppositeTestKeyword = getOppositeTestKeyword(testKeywordWithinDescribe);
80
80
  context.report({
81
81
  messageId: 'consistentMethodWithinDescribe',
@@ -90,7 +90,7 @@ var _default = (0, _utils.createRule)({
90
90
  },
91
91
 
92
92
  'CallExpression:exit'(node) {
93
- if ((0, _utils.isDescribeCall)(node)) {
93
+ if ((0, _utils2.isDescribeCall)(node)) {
94
94
  describeNestingLevel--;
95
95
  }
96
96
  }
@@ -103,7 +103,7 @@ var _default = (0, _utils.createRule)({
103
103
  exports.default = _default;
104
104
 
105
105
  function getPreferredNodeName(nodeName, preferredTestKeyword) {
106
- if (nodeName === _utils.TestCaseName.fit) {
106
+ if (nodeName === _utils2.TestCaseName.fit) {
107
107
  return 'test.only';
108
108
  }
109
109
 
@@ -111,9 +111,9 @@ function getPreferredNodeName(nodeName, preferredTestKeyword) {
111
111
  }
112
112
 
113
113
  function getOppositeTestKeyword(test) {
114
- if (test === _utils.TestCaseName.test) {
115
- return _utils.TestCaseName.it;
114
+ if (test === _utils2.TestCaseName.test) {
115
+ return _utils2.TestCaseName.it;
116
116
  }
117
117
 
118
- return _utils.TestCaseName.test;
118
+ return _utils2.TestCaseName.test;
119
119
  }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.detectJestVersion = void 0;
7
+ let cachedJestVersion = null;
8
+
9
+ const detectJestVersion = () => {
10
+ if (cachedJestVersion) {
11
+ return cachedJestVersion;
12
+ }
13
+
14
+ try {
15
+ const jestPath = require.resolve('jest/package.json');
16
+
17
+ const jestPackageJson = // eslint-disable-next-line @typescript-eslint/no-require-imports
18
+ require(jestPath);
19
+
20
+ if (jestPackageJson.version) {
21
+ const [majorVersion] = jestPackageJson.version.split('.');
22
+ return cachedJestVersion = parseInt(majorVersion, 10);
23
+ }
24
+ } catch {}
25
+
26
+ throw new Error('Unable to detect Jest version - please ensure jest package is installed, or otherwise set version explicitly');
27
+ };
28
+
29
+ exports.detectJestVersion = detectJestVersion;
@@ -5,9 +5,9 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _experimentalUtils = require("@typescript-eslint/experimental-utils");
8
+ var _utils = require("@typescript-eslint/utils");
9
9
 
10
- var _utils = require("./utils");
10
+ var _utils2 = require("./utils");
11
11
 
12
12
  /*
13
13
  * This implementation is adapted from eslint-plugin-jasmine.
@@ -28,7 +28,7 @@ function matchesAssertFunctionName(nodeName, patterns) {
28
28
  }).join('\\.')}(\\.|$)`, 'ui').test(nodeName));
29
29
  }
30
30
 
31
- var _default = (0, _utils.createRule)({
31
+ var _default = (0, _utils2.createRule)({
32
32
  name: __filename,
33
33
  meta: {
34
34
  docs: {
@@ -47,6 +47,12 @@ var _default = (0, _utils.createRule)({
47
47
  items: [{
48
48
  type: 'string'
49
49
  }]
50
+ },
51
+ additionalTestBlockFunctions: {
52
+ type: 'array',
53
+ items: {
54
+ type: 'string'
55
+ }
50
56
  }
51
57
  },
52
58
  additionalProperties: false
@@ -54,21 +60,23 @@ var _default = (0, _utils.createRule)({
54
60
  type: 'suggestion'
55
61
  },
56
62
  defaultOptions: [{
57
- assertFunctionNames: ['expect']
63
+ assertFunctionNames: ['expect'],
64
+ additionalTestBlockFunctions: []
58
65
  }],
59
66
 
60
67
  create(context, [{
61
- assertFunctionNames = ['expect']
68
+ assertFunctionNames = ['expect'],
69
+ additionalTestBlockFunctions = []
62
70
  }]) {
63
71
  const unchecked = [];
64
72
 
65
73
  function checkCallExpressionUsed(nodes) {
66
74
  for (const node of nodes) {
67
- const index = node.type === _experimentalUtils.AST_NODE_TYPES.CallExpression ? unchecked.indexOf(node) : -1;
75
+ const index = node.type === _utils.AST_NODE_TYPES.CallExpression ? unchecked.indexOf(node) : -1;
68
76
 
69
- if (node.type === _experimentalUtils.AST_NODE_TYPES.FunctionDeclaration) {
77
+ if (node.type === _utils.AST_NODE_TYPES.FunctionDeclaration) {
70
78
  const declaredVariables = context.getDeclaredVariables(node);
71
- const testCallExpressions = (0, _utils.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
79
+ const testCallExpressions = (0, _utils2.getTestCallExpressionsFromDeclaredVariables)(declaredVariables);
72
80
  checkCallExpressionUsed(testCallExpressions);
73
81
  }
74
82
 
@@ -81,11 +89,17 @@ var _default = (0, _utils.createRule)({
81
89
 
82
90
  return {
83
91
  CallExpression(node) {
84
- const name = (0, _utils.getNodeName)(node.callee);
92
+ var _getNodeName;
93
+
94
+ const name = (_getNodeName = (0, _utils2.getNodeName)(node.callee)) !== null && _getNodeName !== void 0 ? _getNodeName : '';
95
+
96
+ if ((0, _utils2.isTestCaseCall)(node) || additionalTestBlockFunctions.includes(name)) {
97
+ if (node.callee.type === _utils.AST_NODE_TYPES.MemberExpression && (0, _utils2.isSupportedAccessor)(node.callee.property, 'todo')) {
98
+ return;
99
+ }
85
100
 
86
- if (name === _utils.TestCaseName.it || name === _utils.TestCaseName.test) {
87
101
  unchecked.push(node);
88
- } else if (name && matchesAssertFunctionName(name, assertFunctionNames)) {
102
+ } else if (matchesAssertFunctionName(name, assertFunctionNames)) {
89
103
  // Return early in case of nested `it` statements.
90
104
  checkCallExpressionUsed(context.getAncestors());
91
105
  }
@@ -5,11 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _experimentalUtils = require("@typescript-eslint/experimental-utils");
8
+ var _utils = require("@typescript-eslint/utils");
9
9
 
10
- var _utils = require("./utils");
10
+ var _utils2 = require("./utils");
11
11
 
12
- var _default = (0, _utils.createRule)({
12
+ var _default = (0, _utils2.createRule)({
13
13
  name: __filename,
14
14
  meta: {
15
15
  docs: {
@@ -46,7 +46,7 @@ var _default = (0, _utils.createRule)({
46
46
  parent
47
47
  } = node;
48
48
 
49
- if ((parent === null || parent === void 0 ? void 0 : parent.type) !== _experimentalUtils.AST_NODE_TYPES.CallExpression || !(0, _utils.isDescribeCall)(parent)) {
49
+ if ((parent === null || parent === void 0 ? void 0 : parent.type) !== _utils.AST_NODE_TYPES.CallExpression || !(0, _utils2.isDescribeCall)(parent)) {
50
50
  return;
51
51
  }
52
52
 
@@ -69,7 +69,7 @@ var _default = (0, _utils.createRule)({
69
69
  parent
70
70
  } = node;
71
71
 
72
- if ((parent === null || parent === void 0 ? void 0 : parent.type) === _experimentalUtils.AST_NODE_TYPES.CallExpression && (0, _utils.isDescribeCall)(parent)) {
72
+ if ((parent === null || parent === void 0 ? void 0 : parent.type) === _utils.AST_NODE_TYPES.CallExpression && (0, _utils2.isDescribeCall)(parent)) {
73
73
  describeCallbackStack.pop();
74
74
  }
75
75
  }