Skip to content

Commit

Permalink
feat: create prefer-hooks-in-order rule (#1098)
Browse files Browse the repository at this point in the history
* feat: create `prefer-hooks-in-order` rule

* wip

* Implement prefer-hooks-in-order logic

* Fix all rules tests

* ci: run prettier and docs generation, fix test description

* test: Add examples to the tests

* test: Add some more complicated tests

* ci: change isHook to isHookCall

* feat: use early returns consistently

Co-authored-by: Gareth Jones <jones258@gmail.com>
  • Loading branch information
aaron012 and G-Rath committed May 28, 2022
1 parent 7c28c6b commit 384654c
Show file tree
Hide file tree
Showing 6 changed files with 904 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -209,6 +209,7 @@ installations requiring long-term consistency.
| [prefer-equality-matcher](docs/rules/prefer-equality-matcher.md) | Suggest using the built-in equality matchers | | ![suggest][] |
| [prefer-expect-assertions](docs/rules/prefer-expect-assertions.md) | Suggest using `expect.assertions()` OR `expect.hasAssertions()` | | ![suggest][] |
| [prefer-expect-resolves](docs/rules/prefer-expect-resolves.md) | Prefer `await expect(...).resolves` over `expect(await ...)` syntax | | ![fixable][] |
| [prefer-hooks-in-order](docs/rules/prefer-hooks-in-order.md) | Prefer having hooks in a consistent order | | |
| [prefer-hooks-on-top](docs/rules/prefer-hooks-on-top.md) | Suggest having hooks before any test cases | | |
| [prefer-lowercase-title](docs/rules/prefer-lowercase-title.md) | Enforce lowercase test names | | ![fixable][] |
| [prefer-snapshot-hint](docs/rules/prefer-snapshot-hint.md) | Prefer including a hint with external snapshots | | |
Expand Down
133 changes: 133 additions & 0 deletions docs/rules/prefer-hooks-in-order.md
@@ -0,0 +1,133 @@
# Prefer having hooks in a consistent order (`prefer-hooks-in-order`)

While hooks can be setup in any order, they're always called by `jest` in this
specific order:

1. `beforeAll`
1. `beforeEach`
1. `afterEach`
1. `afterAll`

This rule aims to make that more obvious by enforcing grouped hooks be setup in
that order within tests.

## Rule Details

Examples of **incorrect** code for this rule

```js
/* eslint jest/prefer-hooks-in-order: "error" */

describe('foo', () => {
beforeEach(() => {
seedMyDatabase();
});

beforeAll(() => {
createMyDatabase();
});

it('accepts this input', () => {
// ...
});

it('returns that value', () => {
// ...
});

describe('when the database has specific values', () => {
const specificValue = '...';

beforeEach(() => {
seedMyDatabase(specificValue);
});

it('accepts that input', () => {
// ...
});

it('throws an error', () => {
// ...
});

afterEach(() => {
clearLogger();
});
beforeEach(() => {
mockLogger();
});

it('logs a message', () => {
// ...
});
});

afterAll(() => {
removeMyDatabase();
});
});
```

Examples of **correct** code for this rule

```js
/* eslint jest/prefer-hooks-in-order: "error" */

describe('foo', () => {
beforeAll(() => {
createMyDatabase();
});

beforeEach(() => {
seedMyDatabase();
});

it('accepts this input', () => {
// ...
});

it('returns that value', () => {
// ...
});

describe('when the database has specific values', () => {
const specificValue = '...';

beforeEach(() => {
seedMyDatabase(specificValue);
});

it('accepts that input', () => {
// ...
});

it('throws an error', () => {
// ...
});

beforeEach(() => {
mockLogger();
});

afterEach(() => {
clearLogger();
});

it('logs a message', () => {
// ...
});
});

afterAll(() => {
removeMyDatabase();
});
});
```

## Also See

- [`prefer-hooks-on-top`](prefer-hooks-on-top.md)

## Further Reading

- [Order of execution of describe and test blocks](https://jestjs.io/docs/setup-teardown#order-of-execution-of-describe-and-test-blocks)
1 change: 1 addition & 0 deletions src/__tests__/__snapshots__/rules.test.ts.snap
Expand Up @@ -39,6 +39,7 @@ Object {
"jest/prefer-equality-matcher": "error",
"jest/prefer-expect-assertions": "error",
"jest/prefer-expect-resolves": "error",
"jest/prefer-hooks-in-order": "error",
"jest/prefer-hooks-on-top": "error",
"jest/prefer-lowercase-title": "error",
"jest/prefer-snapshot-hint": "error",
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/rules.test.ts
Expand Up @@ -2,7 +2,7 @@ import { existsSync } from 'fs';
import { resolve } from 'path';
import plugin from '../';

const numberOfRules = 47;
const numberOfRules = 48;
const ruleNames = Object.keys(plugin.rules);
const deprecatedRules = Object.entries(plugin.rules)
.filter(([, rule]) => rule.meta.deprecated)
Expand Down

0 comments on commit 384654c

Please sign in to comment.