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

  1. Move all hooks in the scope above the first test case.
  2. Group setup/teardown pairs in one place (top of the describe) so ordering stays obvious.
  3. 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

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


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/54b858009236085f. Report an issue: GitHub.