Skip to content

linter: jest/no-confusing-set-timeout reports on arbitrary jest.* calls when no jest.setTimeout exists #23360

Description

@therockstorm

What version of Oxlint are you using?

Reproduced on:

  • oxlint 1.69.0, macOS arm64
  • oxlint 1.60.0, macOS arm64

npm view oxlint version currently reports 1.69.0.

I also checked oxc main at f57b55db11b4bfb50179ab2ca6bce2d394032720: the source still contains the same rule logic described in "Root cause" below. I could not run a source-built oxlint binary in this local environment because the repo pins Rust 1.96.0, no Rust toolchains are installed, and both rustup and mise x rust@1.96.0 fail to download from static.rust-lang.org with unsuccessful tunnel.

What command did you run?

npx -y oxlint@1.69.0 --jest-plugin -D jest/no-confusing-set-timeout example.spec.ts

What does your config look like?

No config file is needed. The repro enables the Jest plugin with --jest-plugin and enables only this rule with -D jest/no-confusing-set-timeout.

What happened?

jest/no-confusing-set-timeout reports "jest.setTimeout should be placed before any other jest methods" on jest.fn() and jest.clearAllMocks() even though the file contains no jest.setTimeout call at all.

It also reports the same span multiple times. In a larger repo this produced 265,800 diagnostics across 764 files, none of which call jest.setTimeout.

Minimal repro

example.spec.ts:

describe("example", () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it("works", () => {
    const fn = jest.fn();
    fn();
    expect(fn).toHaveBeenCalled();
  });
});

Output from oxlint 1.69.0:

example.spec.ts:7:16: error jest(no-confusing-set-timeout): `jest.setTimeout` should be placed before any other jest methods.
example.spec.ts:3:5: error jest(no-confusing-set-timeout): `jest.setTimeout` should be placed before any other jest methods.
example.spec.ts:7:16: error jest(no-confusing-set-timeout): `jest.setTimeout` should be placed before any other jest methods.
example.spec.ts:3:5: error jest(no-confusing-set-timeout): `jest.setTimeout` should be placed before any other jest methods.
example.spec.ts:7:16: error jest(no-confusing-set-timeout): `jest.setTimeout` should be placed before any other jest methods.

Output from oxlint 1.60.0 shows the same five diagnostics, just with the older formatted reporter.

What did you expect to happen?

Zero diagnostics. The rule should only report actual jest.setTimeout(...) calls that are:

  • outside global scope
  • repeated
  • placed after other Jest methods

It should not report arbitrary jest.* calls as if they were jest.setTimeout.

Root cause

In crates/oxc_linter/src/rules/jest/no_confusing_set_timeout.rs on main commit f57b55db11b4bfb50179ab2ca6bce2d394032720:

  • Lines 127-145: collect_jest_reference_id collects every jest.* member expression span into jest_reference_list. It only checks that the reference name is jest and that the parent is a member expression. It does not check that the member property is setTimeout.
  • Lines 164-168: when the rule sees any earlier non-jest reference that is parsed as a Jest function call, it reports every later collected jest.* member span with the unordered-setTimeout diagnostic.

That makes the rule treat later jest.fn(), jest.clearAllMocks(), etc. as if they were late jest.setTimeout() calls.

The duplicate diagnostics come from the same loop: one later jest.* span can be "later than" multiple earlier Jest method references, so the same span is reported once per earlier method.

The checked-in snapshot crates/oxc_linter/src/snapshots/jest_no_confusing_set_timeout.snap already contains repeated diagnostics for the same late jest.setTimeout span, which matches the duplicate-reporting part of this bug.

Fix sketch

Filter the collected reference list to actual jest.setTimeout static member expressions, and de-duplicate unordered diagnostics by the ReferenceId of the offending jest.setTimeout.

I applied this direction locally as a candidate patch shape, but could not run the Rust test suite in this environment because of the toolchain download blocker above:

  • Rename collect_jest_reference_id to collect only StaticMemberExpression nodes whose property name is setTimeout.
  • Pass only those references to the unordered check.
  • Track reported unordered ReferenceIds in an FxHashSet so one late jest.setTimeout produces one unordered diagnostic even if multiple earlier Jest methods exist.
  • Add the minimal repro above as a passing fixture.

Existing issue/PR search

I did not find a direct duplicate.

Related but not this bug:

Disclosure

This was prepared with AI assistance and has been reviewed by a human.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Fields

    Priority

    None yet

    Effort

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions