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:
```js

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Pass the call directly and use the resolves matcher: `await expect(someCall()).resolves.toBe(expected)`.
  2. For rejection paths use `await expect(someCall()).rejects.toThrow()`.
  3. 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

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


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