{"record":{"id":"af3a3248c2f90952","repo":"oxc-project/oxc","slug":"test-hooks-are-not-in-a-consistent-order","errorCode":null,"errorMessage":"Test hooks are not in a consistent order.","messagePattern":"Test hooks are not in a consistent order\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/shared/jest_vitest/prefer_hooks_in_order.rs","lineNumber":15,"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, ParsedJestFnCallNew, PossibleJestNode, parse_jest_fn_call,\n    },\n};\n\nfn reorder_hooks(hook: (&str, Span), previous_hook: (&str, Span)) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Test hooks are not in a consistent order.\")\n        .with_help(format!(\"{:?} hooks should be before any {:?} hooks\", hook.0, previous_hook.0))\n        .with_label(\n            hook.1.label(format!(\"this should be moved to before the {:?} hook\", previous_hook.0)),\n        )\n        .and_label(previous_hook.1.label(format!(\"{:?} hook should be called before this\", hook.0)))\n}\n\npub const DOCUMENTATION: &str = r\"### What it does\n\nEnsures that hooks are in the order that they are called in.\n\n### Why is this bad?\n\nWhile hooks can be setup in any order, they're always called by `jest` in this\nspecific order:\n1. `beforeAll`\n2. `beforeEach`\n3. `afterEach`","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/shared/jest_vitest/prefer_hooks_in_order.rs#L1-L33","documentation":"This is the oxlint `prefer-hooks-in-order` rule (jest/vitest plugin). Within a given scope, hooks have a fixed execution order — `beforeAll` → `beforeEach` → `afterEach` → `afterAll` — regardless of where they are written; declaring them out of that order makes the file lie about what runs when. The rule reports the later-out-of-order hook with labels on both the offending hook and the one it should precede.","triggerScenarios":"Inside one describe/test-file scope, a hook of an earlier phase appears after a hook of a later phase — e.g. a `beforeEach` declared after an `afterEach`, or a `beforeAll` after a `beforeEach`. Parsed via `parse_jest_fn_call` hook kinds (beforeAll/beforeEach/afterEach/afterAll).","commonSituations":"Appending a new beforeEach at the bottom of a long describe that already has afterEach blocks; splitting setup between contributors working at different ends of the file; copy-pasted hook groups in the wrong sequence.","solutions":["Reorder the hook declarations to beforeAll → beforeEach → afterEach → afterAll within each scope.","Delete duplicated hooks that restate the same phase.","If the out-of-order position is intentional for readability, group hooks in a helper and call it once at the top of the describe."],"exampleFix":"// before\ndescribe('db', () => {\n  afterEach(() => cleanup());\n  beforeEach(() => seed());\n  it('reads', () => { /* ... */ });\n});\n\n// after\ndescribe('db', () => {\n  beforeEach(() => seed());\n  afterEach(() => cleanup());\n  it('reads', () => { /* ... */ });\n});","handlingStrategy":"validation","validationCode":"// .oxlintrc.json\n{ \"rules\": { \"jest/prefer-hooks-in-order\": \"error\" } }\n\nnpx oxlint tests/","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Adopt a fixed layout per describe: beforeAll, beforeEach, tests, afterEach, afterAll.","When adding a hook, insert it in phase order rather than appending at the end.","Use editor snippets/templates for new describe blocks that pre-order the hooks."],"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"}