oxc-project/oxc · warning
Suggest having hooks before any test cases.
Error message
Suggest having hooks before any test cases.
What it means
This is the oxlint `prefer-hooks-on-top` rule (jest/vitest plugin). Jest runs hooks in phase order regardless of position, so a hook written after test cases still executes before them — but readers assume top-to-bottom flow and may miss late setup. The rule reports any hook (beforeAll/beforeEach/afterEach/afterAll) declared after at least one test case in the same scope, asking you to move hooks above the tests.
Source
Thrown at crates/oxc_linter/src/rules/shared/jest_vitest/prefer_hooks_on_top.rs:16
use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_semantic::ScopeId;
use oxc_span::Span;
use rustc_hash::FxHashMap;
use crate::{
context::LintContext,
utils::{
JestFnKind, JestGeneralFnKind, PossibleJestNode, collect_possible_jest_call_node,
is_type_of_jest_fn_call,
},
};
fn no_hook_on_top(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Suggest having hooks before any test cases.")
.with_help("Hooks should come before test cases")
.with_label(span)
}
pub const DOCUMENTATION: &str = r"### What it does
While hooks can be setup anywhere in a test file, they are always called in a
specific order, which means it can be confusing if they're intermixed with test
cases.
### Why is this bad?
When hooks are mixed with test cases, it becomes harder to understand
the test setup and execution order. This can lead to confusion about
which hooks apply to which tests and when they run. Grouping hooks at
the top of each `describe` block makes the test structure clearer and
more maintainable.
View on GitHub (pinned to e1e7af627c)
Solutions
- Move all hooks in the scope above the first test case.
- Group setup/teardown pairs in one place (top of the describe) so ordering stays obvious.
- If a hook only concerns later tests, extract those tests into their own describe with hooks on top.
Example fix
// before
describe('api', () => {
it('lists', () => { /* ... */ });
it('creates', () => { /* ... */ });
beforeEach(() => mockNetwork());
});
// after
describe('api', () => {
beforeEach(() => mockNetwork());
it('lists', () => { /* ... */ });
it('creates', () => { /* ... */ });
}); Defensive patterns
Strategy: validation
Validate before calling
// .oxlintrc.json
{ "rules": { "jest/prefer-hooks-on-top": "error" } }
npx oxlint tests/ Prevention
- Declare all hooks before the first test case in every scope.
- If a subset of tests needs extra setup, split them into their own describe with hooks on top.
- Let CI catch late-appended hooks in growing test files.
When it happens
Trigger: Within a describe block (or top level), a hook call is collected via `collect_possible_jest_call_node` and appears after the first `it`/`test` call in that scope — e.g. an afterEach near the bottom of the block for cleanup readability.
Common situations: Cleanup hooks appended at the end of a block next to the tests that need them; incremental growth of test files where new hooks get added after existing cases; generated scaffolds that emit tests before hooks.
Related errors
- Test hooks are not in a consistent order.
- `expect` must be inside of a test block.
- Jest tests should not return a value
- Unnecessary async function wrapper
- Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()`
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/54b858009236085f.
Report an issue: GitHub.