{"record":{"id":"c28e98dc620bf207","repo":"oxc-project/oxc","slug":"expect-in-a-promise-chain-must-be-awaited-or-retur","errorCode":null,"errorMessage":"Expect in a promise chain must be awaited or returned","messagePattern":"Expect in a promise chain must be awaited or returned","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/shared/jest_vitest/valid_expect_in_promise.rs","lineNumber":21,"sourceCode":"    AstKind,\n    ast::{\n        Argument, CallExpression, Expression, FunctionBody, MemberExpression,\n        SimpleAssignmentTarget, Statement,\n    },\n};\nuse oxc_ast_visit::{VisitJs, walk_js};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_span::{GetSpan, Span};\nuse oxc_str::CompactStr;\nuse rustc_hash::{FxHashMap, FxHashSet};\n\nuse crate::{\n    context::LintContext,\n    utils::{JestGeneralFnKind, PossibleJestNode, get_node_name_vec, parse_general_jest_fn_call},\n};\n\nfn expect_in_unhandled_promise(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Expect in a promise chain must be awaited or returned\")\n        .with_help(\"Either `await` the promise, `return` it, or use `expect().resolves`/`expect().rejects`.\")\n        .with_label(span)\n}\n\nfn expect_in_promise_after_return(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Expect in a promise chain is unreachable after a `return` statement\")\n        .with_help(\"Move the promise before the `return` and ensure it is awaited or returned.\")\n        .with_label(span)\n}\n\npub const DOCUMENTATION: &str = r\"### What it does\n\nEnsures that `expect` calls inside promise chains (`.then()`, `.catch()`,\n`.finally()`) are properly awaited or returned from the test.\n\n### Why is this bad?\n\nWhen `expect` is called inside a promise callback that is not awaited or","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/shared/jest_vitest/valid_expect_in_promise.rs#L3-L39","documentation":"Diagnostic from the shared jest/vitest `valid-expect-in-promise` rule (expect_in_unhandled_promise). It fires when an `expect()` call lives inside a `.then()`/`.catch()`/`.finally()` callback of a promise that is neither awaited nor returned from the test. The test function returns before the callback runs, so failures vanish and the test is a false pass.","triggerScenarios":"The rule parses general jest function calls (test/it handlers) and inspects promise-chain member expressions; when an expect sits in the callback and the chain is floating, this diagnostic is emitted. Examples: `it('x', () => { fetchData().then((d) => expect(d).toBe(1)); });` or `.catch(() => expect(err).toBeDefined());` without await/return.","commonSituations":"Legacy promise-chain tests written before async/await, tests where a refactor removed `return` from `return promise.then(...)`, and fire-and-forget `.catch` handlers that swallow assertion errors.","solutions":["Make the test async and `await` the chain: `it('x', async () => { await fetchData().then((d) => expect(d).toBe(1)); });`.","Or `return` the chain from the test: `return fetchData().then(...)`.","Or drop the chain: `const d = await fetchData(); expect(d).toBe(1);`.","For promise assertions use `await expect(p).resolves.toBe(1)` / `.rejects` instead of .then/.catch wrappers."],"exampleFix":"// before\nit('loads', () => {\n  fetchData().then((data) => expect(data.length).toBe(1));\n});\n\n// after\nit('loads', async () => {\n  const data = await fetchData();\n  expect(data.length).toBe(1);\n});","handlingStrategy":"validation","validationCode":"// detect expect inside then/catch/finally callbacks\nconst floating = /\\.(then|catch|finally)\\s*\\(\\s*\\(?[^)]*\\)?\\s*=>\\s*(\\{[^}]*|)expect\\s*\\(/;\nif (floating.test(src)) console.warn('expect() inside a promise chain callback — await or return it');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Write new tests as `async/await` only; never `.then()` inside test bodies.","If you must keep a chain, `return` it from the test so the runner awaits it.","Enable oxlint's valid-expect-in-promise plus @typescript-eslint no-floating-promises in CI."],"tags":["jest","vitest","oxlint","testing","promise-chain","floating-promise","async","valid-expect-in-promise"],"backgroundTag":"unawaited-assertion-in-promise-chain","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}