oxc-project/oxc · warning
Unnecessary async function wrapper
Error message
Unnecessary async function wrapper
What it means
This is the oxlint `no-unneeded-async-expect-function` rule (jest/vitest plugin). Wrapping a call in an `async () => { await fn() }` arrow before passing it to `expect()` defeats the assertion: `expect` receives a function value, not the promise, so `.resolves`/`.rejects` matchers never observe the awaited result. The rule flags expect() calls whose single argument is an async function/arrow whose body is only an awaited call, and tells you to pass the call itself.
Source
Thrown at crates/oxc_linter/src/rules/shared/jest_vitest/no_unneeded_async_expect_function.rs:14
use oxc_ast::{
AstKind,
ast::{Argument, Expression, Statement},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::Span;
use crate::{
context::LintContext,
utils::{ParsedJestFnCallNew, PossibleJestNode, parse_jest_fn_call},
};
fn no_unneeded_async_expect_function_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Unnecessary async function wrapper")
.with_help("Remove the async wrapper and pass the promise directly to expect")
.with_label(span)
}
pub const DOCUMENTATION: &str = r"### What it does
Disallows unnecessary async function wrapper for expected promises.
### Why is this bad?
When the only statement inside an async wrapper is `await someCall()`,
the call should be passed directly to `expect` instead. This makes the
test code more concise and easier to read.
### Examples
Examples of **incorrect** code for this rule:
```jsView on GitHub (pinned to e1e7af627c)
Solutions
- Pass the call directly and use the resolves matcher: `await expect(someCall()).resolves.toBe(expected)`.
- For rejection paths use `await expect(someCall()).rejects.toThrow()`.
- If the wrapper contains more than one statement, unwrap only the awaited call and keep the rest in the test body.
Example fix
// before
it('resolves', () => {
expect(async () => { await Promise.resolve('value'); }).resolves.toBe('value');
});
// after
it('resolves', async () => {
await expect(Promise.resolve('value')).resolves.toBe('value');
}); Defensive patterns
Strategy: validation
Validate before calling
// .oxlintrc.json
{ "rules": { "jest/no-unneeded-async-expect-function": "error" } }
npx oxlint tests/ Prevention
- Remember expect() takes a value or promise — never a function you want executed.
- Use the pattern `await expect(call()).resolves|rejects.matcher` for all promise assertions.
- Add the rule to CI so the silent no-op wrapper never lands.
When it happens
Trigger: `expect(async () => { await someCall(); })` — an Argument that is an async arrow/function expression whose body consists solely of an `await someCall()` expression (or a single `return await someCall()`), typically followed by `.resolves`/`.rejects` matchers.
Common situations: Developers learning promise matchers who 'make sure it is async' by wrapping; refactoring `await` out of a test body into the expect argument; TypeScript users adding the wrapper to satisfy a type expectation about the argument.
Related errors
- Prefer `await expect(...).resolves` over `expect(await ...)`
- Jest tests should not return a value
- `expect` must be inside of a test block.
- Suggest using `toBeCalledWith()` or `toHaveBeenCalledWith()`
- Enforce using `each` rather than manual loops
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/e529c1d76210c58b.
Report an issue: GitHub.