{"record":{"id":"54b858009236085f","repo":"oxc-project/oxc","slug":"suggest-having-hooks-before-any-test-cases","errorCode":null,"errorMessage":"Suggest having hooks before any test cases.","messagePattern":"Suggest having hooks before any test cases\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/shared/jest_vitest/prefer_hooks_on_top.rs","lineNumber":16,"sourceCode":"use oxc_ast::AstKind;\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_semantic::ScopeId;\nuse oxc_span::Span;\nuse rustc_hash::FxHashMap;\n\nuse crate::{\n    context::LintContext,\n    utils::{\n        JestFnKind, JestGeneralFnKind, PossibleJestNode, collect_possible_jest_call_node,\n        is_type_of_jest_fn_call,\n    },\n};\n\nfn no_hook_on_top(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Suggest having hooks before any test cases.\")\n        .with_help(\"Hooks should come before test cases\")\n        .with_label(span)\n}\n\npub const DOCUMENTATION: &str = r\"### What it does\n\nWhile hooks can be setup anywhere in a test file, they are always called in a\nspecific order, which means it can be confusing if they're intermixed with test\ncases.\n\n### Why is this bad?\n\nWhen hooks are mixed with test cases, it becomes harder to understand\nthe test setup and execution order. This can lead to confusion about\nwhich hooks apply to which tests and when they run. Grouping hooks at\nthe top of each `describe` block makes the test structure clearer and\nmore maintainable.\n","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/shared/jest_vitest/prefer_hooks_on_top.rs#L1-L34","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ndescribe('api', () => {\n  it('lists', () => { /* ... */ });\n  it('creates', () => { /* ... */ });\n  beforeEach(() => mockNetwork());\n});\n\n// after\ndescribe('api', () => {\n  beforeEach(() => mockNetwork());\n  it('lists', () => { /* ... */ });\n  it('creates', () => { /* ... */ });\n});","handlingStrategy":"validation","validationCode":"// .oxlintrc.json\n{ \"rules\": { \"jest/prefer-hooks-on-top\": \"error\" } }\n\nnpx oxlint tests/","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["jest","vitest","oxlint","testing","lifecycle-hooks","static-analysis"],"backgroundTag":"lifecycle-hook-order","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}