jest/require-hook Style
What it does
This rule flags any expression that is either at the toplevel of a test file or directly within the body of a describe
, except for the following:
import
statementsconst
variableslet
declarations, and initializations tonull
orundefined
- Classes
- Types
- Calls to the standard Jest globals
Why is this bad?
Having setup and teardown code outside of hooks can lead to unpredictable test behavior. Code that runs at the top level executes when the test file is loaded, not when tests run, which can cause issues with test isolation and make tests dependent on execution order. Using proper hooks like beforeEach
, beforeAll
, afterEach
, and afterAll
ensures that setup and teardown code runs at the correct time and maintains test isolation.
Examples
Examples of incorrect code for this rule:
javascript
import { Logger } from "../../../src/Logger";
import { loadCities } from "../api";
import { database, isCity } from "../database";
jest.mock("../api");
const initializeCityDatabase = () => {
database.addCity("Vienna");
database.addCity("San Juan");
database.addCity("Wellington");
};
const clearCityDatabase = () => {
database.clear();
};
initializeCityDatabase();
test("that persists cities", () => {
expect(database.cities.length).toHaveLength(3);
});
test("city database has Vienna", () => {
expect(isCity("Vienna")).toBeTruthy();
});
test("city database has San Juan", () => {
expect(isCity("San Juan")).toBeTruthy();
});
describe("when loading cities from the api", () => {
let consoleWarnSpy = jest.spyOn(console, "warn");
loadCities.mockResolvedValue(["Wellington", "London"]);
it("does not duplicate cities", async () => {
await database.loadCities();
expect(database.cities).toHaveLength(4);
});
});
clearCityDatabase();
Examples of correct code for this rule:
javascript
import { Logger } from "../../../src/Logger";
import { loadCities } from "../api";
import { database, isCity } from "../database";
jest.mock("../api");
const initializeCityDatabase = () => {
database.addCity("Vienna");
database.addCity("San Juan");
database.addCity("Wellington");
};
const clearCityDatabase = () => {
database.clear();
};
beforeEach(() => {
initializeCityDatabase();
});
test("that persists cities", () => {
expect(database.cities.length).toHaveLength(3);
});
test("city database has Vienna", () => {
expect(isCity("Vienna")).toBeTruthy();
});
test("city database has San Juan", () => {
expect(isCity("San Juan")).toBeTruthy();
});
describe("when loading cities from the api", () => {
let consoleWarnSpy;
beforeEach(() => {
consoleWarnSpy = jest.spyOn(console, "warn");
loadCities.mockResolvedValue(["Wellington", "London"]);
});
it("does not duplicate cities", async () => {
await database.loadCities();
expect(database.cities).toHaveLength(4);
});
});
afterEach(() => {
clearCityDatabase();
});
How to use
To enable this rule in the CLI or using the config file, you can use:
bash
oxlint --deny jest/require-hook --jest-plugin
json
{
"plugins": ["jest"],
"rules": {
"jest/require-hook": "error"
}
}