eslint-plugin-jest 27.0.0-next.1 → 27.0.1

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/README.md CHANGED
@@ -203,7 +203,7 @@ installations requiring long-term consistency.
203
203
  | [expect-expect](docs/rules/expect-expect.md) | Enforce assertion to be made in a test body | ![recommended][] | |
204
204
  | [max-expects](docs/rules/max-expects.md) | Enforces a maximum number assertion calls in a test body | | |
205
205
  | [max-nested-describe](docs/rules/max-nested-describe.md) | Enforces a maximum depth to nested describe calls | | |
206
- | [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods | ![style][] | ![fixable][] |
206
+ | [no-alias-methods](docs/rules/no-alias-methods.md) | Disallow alias methods | ![recommended][] | ![fixable][] |
207
207
  | [no-commented-out-tests](docs/rules/no-commented-out-tests.md) | Disallow commented out tests | ![recommended][] | |
208
208
  | [no-conditional-expect](docs/rules/no-conditional-expect.md) | Prevent calling `expect` conditionally | ![recommended][] | |
209
209
  | [no-conditional-in-test](docs/rules/no-conditional-in-test.md) | Disallow conditional logic in tests | | |
@@ -217,7 +217,6 @@ installations requiring long-term consistency.
217
217
  | [no-identical-title](docs/rules/no-identical-title.md) | Disallow identical titles | ![recommended][] | |
218
218
  | [no-interpolation-in-snapshots](docs/rules/no-interpolation-in-snapshots.md) | Disallow string interpolation inside snapshots | ![recommended][] | |
219
219
  | [no-jasmine-globals](docs/rules/no-jasmine-globals.md) | Disallow Jasmine globals | ![recommended][] | ![fixable][] |
220
- | [no-jest-import](docs/rules/no-jest-import.md) | Disallow importing Jest | ![recommended][] | |
221
220
  | [no-large-snapshots](docs/rules/no-large-snapshots.md) | disallow large snapshots | | |
222
221
  | [no-mocks-import](docs/rules/no-mocks-import.md) | Disallow manually importing from `__mocks__` | ![recommended][] | |
223
222
  | [no-restricted-matchers](docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers | | |
@@ -226,6 +225,7 @@ installations requiring long-term consistency.
226
225
  | [no-test-return-statement](docs/rules/no-test-return-statement.md) | Disallow explicitly returning from tests | | |
227
226
  | [prefer-called-with](docs/rules/prefer-called-with.md) | Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()` | | |
228
227
  | [prefer-comparison-matcher](docs/rules/prefer-comparison-matcher.md) | Suggest using the built-in comparison matchers | | ![fixable][] |
228
+ | [prefer-each](docs/rules/prefer-each.md) | Prefer using `.each` rather than manual loops | | |
229
229
  | [prefer-equality-matcher](docs/rules/prefer-equality-matcher.md) | Suggest using the built-in equality matchers | | ![suggest][] |
230
230
  | [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | ![suggest][] |
231
231
  | [prefer-expect-resolves](docs/rules/prefer-expect-resolves.md) | Prefer `await expect(...).resolves` over `expect(await ...)` syntax | | ![fixable][] |
@@ -1,5 +1,8 @@
1
1
  # Disallow alias methods (`no-alias-methods`)
2
2
 
3
+ > These aliases are going to be removed in the next major version of Jest - see
4
+ > https://github.com/facebook/jest/issues/13164 for more
5
+
3
6
  Several Jest methods have alias names, such as `toThrow` having the alias of
4
7
  `toThrowError`. This rule ensures that only the canonical name as used in the
5
8
  Jest documentation is used in the code. This makes it easier to search for all
@@ -8,8 +8,9 @@ alternatives.
8
8
  Bans are expressed in the form of a map, with the value being either a string
9
9
  message to be shown, or `null` if the default rule message should be used.
10
10
 
11
- Both matchers, modifiers, and chains of the two are checked, allowing for
12
- specific variations of a matcher to be banned if desired.
11
+ Bans are checked against the start of the `expect` chain - this means that to
12
+ ban a specific matcher entirely you must specify all six permutations, but
13
+ allows you to ban modifiers as well.
13
14
 
14
15
  By default, this map is empty, meaning no matchers or modifiers are banned.
15
16
 
@@ -22,7 +23,12 @@ For example:
22
23
  {
23
24
  "toBeFalsy": null,
24
25
  "resolves": "Use `expect(await promise)` instead.",
25
- "not.toHaveBeenCalledWith": null
26
+ "toHaveBeenCalledWith": null,
27
+ "not.toHaveBeenCalledWith": null,
28
+ "resolves.toHaveBeenCalledWith": null,
29
+ "rejects.toHaveBeenCalledWith": null,
30
+ "resolves.not.toHaveBeenCalledWith": null,
31
+ "rejects.not.toHaveBeenCalledWith": null
26
32
  }
27
33
  ]
28
34
  }
@@ -32,15 +38,18 @@ Examples of **incorrect** code for this rule with the above configuration
32
38
 
33
39
  ```js
34
40
  it('is false', () => {
41
+ // if this has a modifer (i.e. `not.toBeFalsy`), it would be considered fine
35
42
  expect(a).toBeFalsy();
36
43
  });
37
44
 
38
45
  it('resolves', async () => {
46
+ // all uses of this modifier are disallowed, regardless of matcher
39
47
  await expect(myPromise()).resolves.toBe(true);
40
48
  });
41
49
 
42
50
  describe('when an error happens', () => {
43
51
  it('does not upload the file', async () => {
52
+ // all uses of this matcher are disallowed
44
53
  expect(uploadFileMock).not.toHaveBeenCalledWith('file.name');
45
54
  });
46
55
  });
@@ -0,0 +1,54 @@
1
+ # Prefer using `.each` rather than manual loops (`prefer-each`)
2
+
3
+ Reports where you might be able to use `.each` instead of native loops.
4
+
5
+ ## Rule details
6
+
7
+ This rule triggers a warning if you use test case functions like `describe`,
8
+ `test`, and `it`, in a native loop - generally you should be able to use `.each`
9
+ instead which gives better output and makes it easier to run specific cases.
10
+
11
+ Examples of **incorrect** code for this rule:
12
+
13
+ ```js
14
+ for (const number of getNumbers()) {
15
+ it('is greater than five', function () {
16
+ expect(number).toBeGreaterThan(5);
17
+ });
18
+ }
19
+
20
+ for (const [input, expected] of data) {
21
+ beforeEach(() => setupSomething(input));
22
+
23
+ test(`results in ${expected}`, () => {
24
+ expect(doSomething()).toBe(expected);
25
+ });
26
+ }
27
+ ```
28
+
29
+ Examples of **correct** code for this rule:
30
+
31
+ ```js
32
+ it.each(getNumbers())(
33
+ 'only returns numbers that are greater than seven',
34
+ number => {
35
+ expect(number).toBeGreaterThan(7);
36
+ },
37
+ );
38
+
39
+ describe.each(data)('when input is %s', ([input, expected]) => {
40
+ beforeEach(() => setupSomething(input));
41
+
42
+ test(`results in ${expected}`, () => {
43
+ expect(doSomething()).toBe(expected);
44
+ });
45
+ });
46
+
47
+ // we don't warn on loops _in_ test functions because those typically involve
48
+ // complex setup that is better done in the test function itself
49
+ it('returns numbers that are greater than five', () => {
50
+ for (const number of getNumbers()) {
51
+ expect(number).toBeGreaterThan(5);
52
+ }
53
+ });
54
+ ```
@@ -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: false
16
+ recommended: 'error'
17
17
  },
18
18
  messages: {
19
19
  replaceAlias: `Replace {{ alias }}() with its canonical name of {{ canonical }}()`
@@ -33,8 +33,7 @@ var _default = (0, _utils2.createRule)({
33
33
  docs: {
34
34
  category: 'Best Practices',
35
35
  description: 'Avoid using a callback in asynchronous tests and hooks',
36
- recommended: 'error',
37
- suggestion: true
36
+ recommended: 'error'
38
37
  },
39
38
  messages: {
40
39
  noDoneCallback: 'Return a Promise instead of relying on callback parameter',
@@ -15,8 +15,7 @@ var _default = (0, _utils2.createRule)({
15
15
  docs: {
16
16
  category: 'Best Practices',
17
17
  description: 'Disallow focused tests',
18
- recommended: 'error',
19
- suggestion: true
18
+ recommended: 'error'
20
19
  },
21
20
  messages: {
22
21
  focusedTest: 'Unexpected focused test.',
@@ -23,7 +23,7 @@ var _default = (0, _utils.createRule)({
23
23
  }
24
24
  }],
25
25
  messages: {
26
- restrictedChain: 'Use of `{{ chain }}` is disallowed',
26
+ restrictedChain: 'Use of `{{ restriction }}` is disallowed',
27
27
  restrictedChainWithMessage: '{{ message }}'
28
28
  }
29
29
  },
@@ -38,31 +38,19 @@ var _default = (0, _utils.createRule)({
38
38
  return;
39
39
  }
40
40
 
41
- const permutations = [jestFnCall.members];
41
+ const chain = jestFnCall.members.map(nod => (0, _utils.getAccessorValue)(nod)).join('.');
42
42
 
43
- if (jestFnCall.members.length > 2) {
44
- permutations.push([jestFnCall.members[0], jestFnCall.members[1]]);
45
- permutations.push([jestFnCall.members[1], jestFnCall.members[2]]);
46
- }
47
-
48
- if (jestFnCall.members.length > 1) {
49
- permutations.push(...jestFnCall.members.map(nod => [nod]));
50
- }
51
-
52
- for (const permutation of permutations) {
53
- const chain = permutation.map(nod => (0, _utils.getAccessorValue)(nod)).join('.');
54
-
55
- if (chain in restrictedChains) {
56
- const message = restrictedChains[chain];
43
+ for (const [restriction, message] of Object.entries(restrictedChains)) {
44
+ if (chain.startsWith(restriction)) {
57
45
  context.report({
58
46
  messageId: message ? 'restrictedChainWithMessage' : 'restrictedChain',
59
47
  data: {
60
48
  message,
61
- chain
49
+ restriction
62
50
  },
63
51
  loc: {
64
- start: permutation[0].loc.start,
65
- end: permutation[permutation.length - 1].loc.end
52
+ start: jestFnCall.members[0].loc.start,
53
+ end: jestFnCall.members[jestFnCall.members.length - 1].loc.end
66
54
  }
67
55
  });
68
56
  break;
@@ -0,0 +1,98 @@
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
+ category: 'Best Practices',
15
+ description: 'Prefer using `.each` rather than manual loops',
16
+ recommended: false
17
+ },
18
+ messages: {
19
+ preferEach: 'prefer using `{{ fn }}.each` rather than a manual loop'
20
+ },
21
+ type: 'suggestion',
22
+ schema: []
23
+ },
24
+ defaultOptions: [],
25
+
26
+ create(context) {
27
+ const jestFnCalls = [];
28
+ let inTestCaseCall = false;
29
+
30
+ const recommendFn = () => {
31
+ if (jestFnCalls.length === 1 && jestFnCalls[0] === 'test') {
32
+ return 'it';
33
+ }
34
+
35
+ return 'describe';
36
+ };
37
+
38
+ const enterForLoop = () => {
39
+ if (jestFnCalls.length === 0 || inTestCaseCall) {
40
+ return;
41
+ }
42
+
43
+ jestFnCalls.length = 0;
44
+ };
45
+
46
+ const exitForLoop = node => {
47
+ if (jestFnCalls.length === 0 || inTestCaseCall) {
48
+ return;
49
+ }
50
+
51
+ context.report({
52
+ node,
53
+ messageId: 'preferEach',
54
+ data: {
55
+ fn: recommendFn()
56
+ }
57
+ });
58
+ jestFnCalls.length = 0;
59
+ };
60
+
61
+ return {
62
+ ForStatement: enterForLoop,
63
+ 'ForStatement:exit': exitForLoop,
64
+ ForInStatement: enterForLoop,
65
+ 'ForInStatement:exit': exitForLoop,
66
+ ForOfStatement: enterForLoop,
67
+ 'ForOfStatement:exit': exitForLoop,
68
+
69
+ CallExpression(node) {
70
+ const {
71
+ type: jestFnCallType
72
+ } = (0, _utils.parseJestFnCall)(node, context) ?? {};
73
+
74
+ if (jestFnCallType === 'hook' || jestFnCallType === 'describe' || jestFnCallType === 'test') {
75
+ jestFnCalls.push(jestFnCallType);
76
+ }
77
+
78
+ if (jestFnCallType === 'test') {
79
+ inTestCaseCall = true;
80
+ }
81
+ },
82
+
83
+ 'CallExpression:exit'(node) {
84
+ const {
85
+ type: jestFnCallType
86
+ } = (0, _utils.parseJestFnCall)(node, context) ?? {};
87
+
88
+ if (jestFnCallType === 'test') {
89
+ inTestCaseCall = false;
90
+ }
91
+ }
92
+
93
+ };
94
+ }
95
+
96
+ });
97
+
98
+ exports.default = _default;
@@ -15,8 +15,7 @@ var _default = (0, _utils2.createRule)({
15
15
  docs: {
16
16
  category: 'Best Practices',
17
17
  description: 'Suggest using the built-in equality matchers',
18
- recommended: false,
19
- suggestion: true
18
+ recommended: false
20
19
  },
21
20
  messages: {
22
21
  useEqualityMatcher: 'Prefer using one of the equality matchers instead',
@@ -13,10 +13,16 @@ const isFirstStatement = node => {
13
13
  let parent = node;
14
14
 
15
15
  while (parent) {
16
- var _parent$parent;
16
+ var _parent$parent, _parent$parent2;
17
17
 
18
18
  if (((_parent$parent = parent.parent) === null || _parent$parent === void 0 ? void 0 : _parent$parent.type) === _utils.AST_NODE_TYPES.BlockStatement) {
19
19
  return parent.parent.body[0] === parent;
20
+ } // if we've hit an arrow function, then it must have a single expression
21
+ // as its body, as otherwise we would have hit the block statement already
22
+
23
+
24
+ if (((_parent$parent2 = parent.parent) === null || _parent$parent2 === void 0 ? void 0 : _parent$parent2.type) === _utils.AST_NODE_TYPES.ArrowFunctionExpression) {
25
+ return true;
20
26
  }
21
27
 
22
28
  parent = parent.parent;
@@ -32,18 +38,13 @@ const suggestRemovingExtraArguments = (args, extraArgsStartAt) => ({
32
38
  fix: fixer => fixer.removeRange([args[extraArgsStartAt].range[0] - Math.sign(extraArgsStartAt), args[args.length - 1].range[1]])
33
39
  });
34
40
 
35
- // const suggestions: Array<[MessageIds, string]> = [
36
- // ['suggestAddingHasAssertions', 'expect.hasAssertions();'],
37
- // ['suggestAddingAssertions', 'expect.assertions();'],
38
- // ];
39
41
  var _default = (0, _utils2.createRule)({
40
42
  name: __filename,
41
43
  meta: {
42
44
  docs: {
43
45
  category: 'Best Practices',
44
46
  description: 'Suggest using `expect.assertions()` OR `expect.hasAssertions()`',
45
- recommended: false,
46
- suggestion: true
47
+ recommended: false
47
48
  },
48
49
  messages: {
49
50
  hasAssertionsTakesNoArguments: '`expect.hasAssertions` expects no arguments',
@@ -13,8 +13,7 @@ var _default = (0, _utils.createRule)({
13
13
  docs: {
14
14
  category: 'Best Practices',
15
15
  description: 'Suggest using `toStrictEqual()`',
16
- recommended: false,
17
- suggestion: true
16
+ recommended: false
18
17
  },
19
18
  messages: {
20
19
  useToStrictEqual: 'Use `toStrictEqual()` instead',
@@ -28,14 +28,6 @@ const baseRule = (() => {
28
28
  }
29
29
  })();
30
30
 
31
- const tryCreateBaseRule = context => {
32
- try {
33
- return baseRule === null || baseRule === void 0 ? void 0 : baseRule.create(context);
34
- } catch {
35
- return null;
36
- }
37
- };
38
-
39
31
  const DEFAULT_MESSAGE = 'This rule requires `@typescript-eslint/eslint-plugin`';
40
32
 
41
33
  var _default = (0, _utils2.createRule)({
@@ -62,7 +54,7 @@ var _default = (0, _utils2.createRule)({
62
54
  },
63
55
 
64
56
  create(context) {
65
- const baseSelectors = tryCreateBaseRule(context);
57
+ const baseSelectors = baseRule === null || baseRule === void 0 ? void 0 : baseRule.create(context);
66
58
 
67
59
  if (!baseSelectors) {
68
60
  return {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-jest",
3
- "version": "27.0.0-next.1",
3
+ "version": "27.0.1",
4
4
  "description": "ESLint rules for Jest",
5
5
  "keywords": [
6
6
  "eslint",
@@ -103,34 +103,34 @@
103
103
  "@babel/core": "^7.4.4",
104
104
  "@babel/preset-env": "^7.4.4",
105
105
  "@babel/preset-typescript": "^7.3.3",
106
- "@commitlint/cli": "^16.0.0",
107
- "@commitlint/config-conventional": "^16.0.0",
106
+ "@commitlint/cli": "^17.0.3",
107
+ "@commitlint/config-conventional": "^17.0.3",
108
108
  "@schemastore/package": "^0.0.6",
109
109
  "@semantic-release/changelog": "^6.0.0",
110
110
  "@semantic-release/git": "^10.0.0",
111
111
  "@types/dedent": "^0.7.0",
112
112
  "@types/jest": "^28.0.0",
113
- "@types/node": "^16.0.0",
113
+ "@types/node": "^14.18.26",
114
114
  "@types/prettier": "^2.0.0",
115
115
  "@typescript-eslint/eslint-plugin": "^5.0.0",
116
116
  "@typescript-eslint/parser": "^5.0.0",
117
- "babel-jest": "^28.0.0",
117
+ "babel-jest": "^29.0.0",
118
118
  "babel-plugin-replace-ts-export-assignment": "^0.0.2",
119
119
  "dedent": "^0.7.0",
120
120
  "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0",
121
121
  "eslint-config-prettier": "^8.3.0",
122
122
  "eslint-plugin-eslint-comments": "^3.1.2",
123
- "eslint-plugin-eslint-plugin": "^4.0.0",
123
+ "eslint-plugin-eslint-plugin": "^5.0.6",
124
124
  "eslint-plugin-import": "^2.25.1",
125
125
  "eslint-plugin-node": "^11.0.0",
126
- "eslint-plugin-prettier": "^3.4.1",
126
+ "eslint-plugin-prettier": "^4.2.1",
127
127
  "eslint-remote-tester": "^3.0.0",
128
128
  "eslint-remote-tester-repositories": "~0.0.5",
129
- "husky": "^7.0.2",
129
+ "husky": "^8.0.1",
130
130
  "is-ci": "^3.0.0",
131
- "jest": "^28.0.0",
132
- "jest-runner-eslint": "^1.0.0",
133
- "lint-staged": "^12.0.0",
131
+ "jest": "^29.0.0",
132
+ "jest-runner-eslint": "^1.1.0",
133
+ "lint-staged": "^13.0.3",
134
134
  "pinst": "^3.0.0",
135
135
  "prettier": "^2.0.5",
136
136
  "rimraf": "^3.0.0",
@@ -151,7 +151,7 @@
151
151
  "optional": true
152
152
  }
153
153
  },
154
- "packageManager": "yarn@3.2.2",
154
+ "packageManager": "yarn@3.2.3",
155
155
  "engines": {
156
156
  "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
157
157
  }
@@ -1,20 +0,0 @@
1
- # Disallow importing Jest (`no-jest-import`)
2
-
3
- The `jest` object is automatically in scope within every test file. The methods
4
- in the `jest` object help create mocks and let you control Jest's overall
5
- behavior. It is therefore completely unnecessary to import in `jest`, as Jest
6
- doesn't export anything in the first place.
7
-
8
- ### Rule details
9
-
10
- This rule reports on any importing of Jest.
11
-
12
- To name a few: `var jest = require('jest');` `const jest = require('jest');`
13
- `import jest from 'jest';` `import {jest as test} from 'jest';`
14
-
15
- There is no correct usage of this code, other than to not import `jest` in the
16
- first place.
17
-
18
- ## Further Reading
19
-
20
- - [The Jest Object](https://facebook.github.io/jest/docs/en/jest-object.html)
@@ -1,48 +0,0 @@
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
- type: 'problem',
14
- docs: {
15
- description: 'Disallow importing Jest',
16
- category: 'Best Practices',
17
- recommended: 'error'
18
- },
19
- messages: {
20
- unexpectedImport: `Jest is automatically in scope. Do not import "jest", as Jest doesn't export anything.`
21
- },
22
- schema: []
23
- },
24
- defaultOptions: [],
25
-
26
- create(context) {
27
- return {
28
- 'ImportDeclaration[source.value="jest"]'(node) {
29
- context.report({
30
- node,
31
- messageId: 'unexpectedImport'
32
- });
33
- },
34
-
35
- 'CallExpression[callee.name="require"][arguments.0.value="jest"]'(node) {
36
- context.report({
37
- loc: node.arguments[0].loc,
38
- messageId: 'unexpectedImport',
39
- node
40
- });
41
- }
42
-
43
- };
44
- }
45
-
46
- });
47
-
48
- exports.default = _default;