oxc-project/oxc · warning

Matchers must be called to assert.

Error message

Matchers must be called to assert.

What it means

Diagnostic from the shared jest/vitest `valid-expect` rule in oxlint (via ExpectError::MatcherNotCalled). It fires when a matcher is referenced at the end of an expect chain but never invoked, e.g. `expect(x).toBeDefined` without parentheses. Such a statement performs no assertion at all, so the test passes vacuously.

Source

Thrown at crates/oxc_linter/src/rules/shared/jest_vitest/valid_expect.rs:23

use oxc_semantic::ScopeId;
use oxc_span::{GetSpan, Span};
use rustc_hash::FxHashSet;
use schemars::JsonSchema;

use crate::{
    AstNode,
    context::LintContext,
    utils::{
        ExpectError, PossibleJestNode, collect_possible_jest_call_node, parse_expect_jest_fn_call,
    },
};

fn valid_expect_diagnostic<S: Into<Cow<'static, str>>>(
    x1: S,
    x2: &'static str,
    span3: Span,
) -> OxcDiagnostic {
    OxcDiagnostic::warn(x1).with_help(x2).with_label(span3)
}

pub const DOCUMENTATION: &str = r"### What it does

Checks that `expect()` is called correctly.

### Why is this bad?

`expect()` is a function that is used to assert values in tests.
It should be called with a single argument, which is the value to be tested.
If you call `expect()` with no arguments, or with more than one argument, it will not work as expected.

### Examples

Examples of **incorrect** code for this rule:
```javascript
expect();
expect('something');

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Add parentheses and any required argument: `expect(true).toBe(true)`, `expect(fn).toHaveBeenCalled()`.
  2. If the matcher genuinely takes no arguments, still call it — `expect(x).toBeDefined()` — never reference it bare.
  3. Delete the dead statement if the assertion was abandoned mid-edit.
  4. If the pattern is intentional in your codebase, disable the rule inline with `// oxlint-disable valid-expect` or turn it off in .oxlintrc.json.

Example fix

// before
expect(result).toBeDefined;

// after
expect(result).toBeDefined();
Defensive patterns

Strategy: validation

Validate before calling

// cheap pre-commit scan for referenced-but-uncalled matchers
// rg "expect\([^)]*\)\.[a-zA-Z]+\s*[;,)" src/ --type ts
const fs = require('fs');
for (const f of process.argv.slice(2)) {
  const src = fs.readFileSync(f, 'utf8');
  if (/expect\([^)]*\)\.[a-zA-Z]\w*\s*[;,)]/.test(src)) {
    console.error(`${f}: matcher referenced without being called`);
    process.exitCode = 1;
  }
}

Prevention

When it happens

Trigger: `parse_expect_jest_fn_call` marks the chain with ExpectError::MatcherNotCalled when the final member of the expect chain (the matcher) is not a CallExpression. Concretely: `expect(value).toBe;`, `expect(fn).toHaveBeenCalled;`, or assigning/passing the matcher as a value instead of calling it.

Common situations: Refactors that drop the `()`, copy-paste edits, or code that uses a matcher as a function reference (e.g. `.map(expect)`-style intent). Also seen when converting assertions between libraries and the call shape gets mangled.

Related errors


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