Skip to content

Commit 6708bb8

Browse files
committed
Merge branch 'main' into next
2 parents 24b6c5d + e277f79 commit 6708bb8

22 files changed

+2496
-720
lines changed

CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,36 @@
6060

6161
* Drop support for Node 10 and 15
6262

63+
# [24.7.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.6.0...v24.7.0) (2021-10-10)
64+
65+
66+
### Features
67+
68+
* create `require-hook` rule ([#929](https://github.com/jest-community/eslint-plugin-jest/issues/929)) ([6204b31](https://github.com/jest-community/eslint-plugin-jest/commit/6204b311e849b51a0e4705015575139f590ae7a4))
69+
* deprecate `prefer-to-be-null` rule ([4db9161](https://github.com/jest-community/eslint-plugin-jest/commit/4db91612e988e84ac2facbfe466331b22eeccec9))
70+
* deprecate `prefer-to-be-undefined` rule ([fa08f09](https://github.com/jest-community/eslint-plugin-jest/commit/fa08f0944e89915fb215bbeff970f12459121cb8))
71+
72+
# [24.6.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.5.2...v24.6.0) (2021-10-09)
73+
74+
75+
### Features
76+
77+
* **valid-expect-in-promise:** re-implement rule ([#916](https://github.com/jest-community/eslint-plugin-jest/issues/916)) ([7a49c58](https://github.com/jest-community/eslint-plugin-jest/commit/7a49c5831e3d85a60c11e385203b8f83d98ad580))
78+
79+
## [24.5.2](https://github.com/jest-community/eslint-plugin-jest/compare/v24.5.1...v24.5.2) (2021-10-04)
80+
81+
82+
### Bug Fixes
83+
84+
* **lowercase-name:** consider skip and only prefixes for ignores ([#923](https://github.com/jest-community/eslint-plugin-jest/issues/923)) ([8716c24](https://github.com/jest-community/eslint-plugin-jest/commit/8716c24678ea7dc7c9f692b573d1ea19a67efd84))
85+
86+
## [24.5.1](https://github.com/jest-community/eslint-plugin-jest/compare/v24.5.0...v24.5.1) (2021-10-04)
87+
88+
89+
### Bug Fixes
90+
91+
* **prefer-to-be:** don't consider RegExp literals as `toBe`-able ([#922](https://github.com/jest-community/eslint-plugin-jest/issues/922)) ([99b6d42](https://github.com/jest-community/eslint-plugin-jest/commit/99b6d429e697d60645b4bc64ee4ae34d7016118c))
92+
6393
# [24.5.0](https://github.com/jest-community/eslint-plugin-jest/compare/v24.4.3...v24.5.0) (2021-09-29)
6494

6595

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,16 +184,15 @@ installations requiring long-term consistency.
184184
| [prefer-spy-on](docs/rules/prefer-spy-on.md) | Suggest using `jest.spyOn()` | | ![fixable][] |
185185
| [prefer-strict-equal](docs/rules/prefer-strict-equal.md) | Suggest using `toStrictEqual()` | | ![suggest][] |
186186
| [prefer-to-be](docs/rules/prefer-to-be.md) | Suggest using `toBe()` for primitive literals | | ![fixable][] |
187-
| [prefer-to-be-null](docs/rules/prefer-to-be-null.md) | Suggest using `toBeNull()` | ![style][] | ![fixable][] |
188-
| [prefer-to-be-undefined](docs/rules/prefer-to-be-undefined.md) | Suggest using `toBeUndefined()` | ![style][] | ![fixable][] |
189187
| [prefer-to-contain](docs/rules/prefer-to-contain.md) | Suggest using `toContain()` | ![style][] | ![fixable][] |
190188
| [prefer-to-have-length](docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` | ![style][] | ![fixable][] |
191189
| [prefer-todo](docs/rules/prefer-todo.md) | Suggest using `test.todo` | | ![fixable][] |
190+
| [require-hook](docs/rules/require-hook.md) | Require setup and teardown code to be within a hook | | |
192191
| [require-to-throw-message](docs/rules/require-to-throw-message.md) | Require a message for `toThrow()` | | |
193192
| [require-top-level-describe](docs/rules/require-top-level-describe.md) | Require test cases and hooks to be inside a `describe` block | | |
194193
| [valid-describe](docs/rules/valid-describe.md) | Enforce valid `describe()` callback | ![recommended][] | |
195194
| [valid-expect](docs/rules/valid-expect.md) | Enforce valid `expect()` usage | ![recommended][] | |
196-
| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Enforce having return statement when testing with promises | ![recommended][] | |
195+
| [valid-expect-in-promise](docs/rules/valid-expect-in-promise.md) | Ensure promises that have expectations in their chain are valid | ![recommended][] | |
197196
| [valid-title](docs/rules/valid-title.md) | Enforce valid titles | ![recommended][] | ![fixable][] |
198197

199198
<!-- end base rules list -->

docs/rules/prefer-to-be-null.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Suggest using `toBeNull()` (`prefer-to-be-null`)
22

3+
## Deprecated
4+
5+
This rule has been deprecated in favor of [`prefer-to-be`](prefer-to-be.md).
6+
37
In order to have a better failure message, `toBeNull()` should be used upon
48
asserting expectations on null value.
59

docs/rules/prefer-to-be-undefined.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Suggest using `toBeUndefined()` (`prefer-to-be-undefined`)
22

3+
## Deprecated
4+
5+
This rule has been deprecated in favor of [`prefer-to-be`](prefer-to-be.md).
6+
37
In order to have a better failure message, `toBeUndefined()` should be used upon
48
asserting expectations on undefined value.
59

docs/rules/require-hook.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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_
23+
- Types
24+
- Calls to the standard Jest globals
25+
26+
This rule flags any function calls within test files that are directly within
27+
the body of a `describe`, and suggests wrapping them in one of the four
28+
lifecycle hooks.
29+
30+
Here is a slightly contrived test file showcasing some common cases that would
31+
be flagged:
32+
33+
```js
34+
import { database, isCity } from '../database';
35+
import { Logger } from '../../../src/Logger';
36+
import { loadCities } from '../api';
37+
38+
jest.mock('../api');
39+
40+
const initializeCityDatabase = () => {
41+
database.addCity('Vienna');
42+
database.addCity('San Juan');
43+
database.addCity('Wellington');
44+
};
45+
46+
const clearCityDatabase = () => {
47+
database.clear();
48+
};
49+
50+
initializeCityDatabase();
51+
52+
test('that persists cities', () => {
53+
expect(database.cities.length).toHaveLength(3);
54+
});
55+
56+
test('city database has Vienna', () => {
57+
expect(isCity('Vienna')).toBeTruthy();
58+
});
59+
60+
test('city database has San Juan', () => {
61+
expect(isCity('San Juan')).toBeTruthy();
62+
});
63+
64+
describe('when loading cities from the api', () => {
65+
let consoleWarnSpy = jest.spyOn(console, 'warn');
66+
67+
loadCities.mockResolvedValue(['Wellington', 'London']);
68+
69+
it('does not duplicate cities', async () => {
70+
await database.loadCities();
71+
72+
expect(database.cities).toHaveLength(4);
73+
});
74+
75+
it('logs any duplicates', async () => {
76+
await database.loadCities();
77+
78+
expect(consoleWarnSpy).toHaveBeenCalledWith(
79+
'Ignored duplicate cities: Wellington',
80+
);
81+
});
82+
});
83+
84+
clearCityDatabase();
85+
```
86+
87+
Here is the same slightly contrived test file showcasing the same common cases
88+
but in ways that would be **not** flagged:
89+
90+
```js
91+
import { database, isCity } from '../database';
92+
import { Logger } from '../../../src/Logger';
93+
import { loadCities } from '../api';
94+
95+
jest.mock('../api');
96+
97+
const initializeCityDatabase = () => {
98+
database.addCity('Vienna');
99+
database.addCity('San Juan');
100+
database.addCity('Wellington');
101+
};
102+
103+
const clearCityDatabase = () => {
104+
database.clear();
105+
};
106+
107+
beforeEach(() => {
108+
initializeCityDatabase();
109+
});
110+
111+
test('that persists cities', () => {
112+
expect(database.cities.length).toHaveLength(3);
113+
});
114+
115+
test('city database has Vienna', () => {
116+
expect(isCity('Vienna')).toBeTruthy();
117+
});
118+
119+
test('city database has San Juan', () => {
120+
expect(isCity('San Juan')).toBeTruthy();
121+
});
122+
123+
describe('when loading cities from the api', () => {
124+
let consoleWarnSpy;
125+
126+
beforeEach(() => {
127+
consoleWarnSpy = jest.spyOn(console, 'warn');
128+
loadCities.mockResolvedValue(['Wellington', 'London']);
129+
});
130+
131+
it('does not duplicate cities', async () => {
132+
await database.loadCities();
133+
134+
expect(database.cities).toHaveLength(4);
135+
});
136+
137+
it('logs any duplicates', async () => {
138+
await database.loadCities();
139+
140+
expect(consoleWarnSpy).toHaveBeenCalledWith(
141+
'Ignored duplicate cities: Wellington',
142+
);
143+
});
144+
});
145+
146+
afterEach(() => {
147+
clearCityDatabase();
148+
});
149+
```

docs/rules/valid-expect-in-promise.md

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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`)
22

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.
54

65
## Rule details
76

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.
109

11-
### Default configuration
12-
13-
The following pattern is considered warning:
10+
The following patterns is considered warning:
1411

1512
```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);
1926
});
2027
});
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+
});
2139
```
2240

2341
The following pattern is not warning:
2442

2543
```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');
2947
});
3048
});
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+
});
3172
```

src/__tests__/__snapshots__/rules.test.ts.snap

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,10 @@ Object {
4242
"jest/prefer-spy-on": "error",
4343
"jest/prefer-strict-equal": "error",
4444
"jest/prefer-to-be": "error",
45-
"jest/prefer-to-be-null": "error",
46-
"jest/prefer-to-be-undefined": "error",
4745
"jest/prefer-to-contain": "error",
4846
"jest/prefer-to-have-length": "error",
4947
"jest/prefer-todo": "error",
48+
"jest/require-hook": "error",
5049
"jest/require-to-throw-message": "error",
5150
"jest/require-top-level-describe": "error",
5251
"jest/unbound-method": "error",

src/__tests__/rules.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { existsSync } from 'fs';
22
import { resolve } from 'path';
33
import plugin from '../';
44

5-
const numberOfRules = 44;
5+
const numberOfRules = 45;
66
const ruleNames = Object.keys(plugin.rules);
77
const deprecatedRules = Object.entries(plugin.rules)
88
.filter(([, rule]) => rule.meta.deprecated)

0 commit comments

Comments
 (0)