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.
What version of Oxlint are you using?
Reproduced on:
oxlint1.69.0, macOS arm64oxlint1.60.0, macOS arm64npm view oxlint versioncurrently reports1.69.0.I also checked
oxcmainatf57b55db11b4bfb50179ab2ca6bce2d394032720: the source still contains the same rule logic described in "Root cause" below. I could not run a source-builtoxlintbinary in this local environment because the repo pins Rust1.96.0, no Rust toolchains are installed, and bothrustupandmise x rust@1.96.0fail to download fromstatic.rust-lang.orgwithunsuccessful tunnel.What command did you run?
What does your config look like?
No config file is needed. The repro enables the Jest plugin with
--jest-pluginand enables only this rule with-D jest/no-confusing-set-timeout.What happened?
jest/no-confusing-set-timeoutreports "jest.setTimeoutshould be placed before any other jest methods" onjest.fn()andjest.clearAllMocks()even though the file contains nojest.setTimeoutcall 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:Output from
oxlint1.69.0:Output from
oxlint1.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:It should not report arbitrary
jest.*calls as if they werejest.setTimeout.Root cause
In
crates/oxc_linter/src/rules/jest/no_confusing_set_timeout.rsonmaincommitf57b55db11b4bfb50179ab2ca6bce2d394032720:collect_jest_reference_idcollects everyjest.*member expression span intojest_reference_list. It only checks that the reference name isjestand that the parent is a member expression. It does not check that the member property issetTimeout.jestreference that is parsed as a Jest function call, it reports every later collectedjest.*member span with the unordered-setTimeoutdiagnostic.That makes the rule treat later
jest.fn(),jest.clearAllMocks(), etc. as if they were latejest.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.snapalready contains repeated diagnostics for the same latejest.setTimeoutspan, which matches the duplicate-reporting part of this bug.Fix sketch
Filter the collected reference list to actual
jest.setTimeoutstatic member expressions, and de-duplicate unordered diagnostics by theReferenceIdof the offendingjest.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:
collect_jest_reference_idto collect onlyStaticMemberExpressionnodes whose property name issetTimeout.ReferenceIds in anFxHashSetso one latejest.setTimeoutproduces one unordered diagnostic even if multiple earlier Jest methods exist.Existing issue/PR search
I did not find a direct duplicate.
Related but not this bug:
--vitest-pluginenabling Jest rules and is closed.jest/no-confusing-set-timeout#938) plus later docs/perf changes (docs(linter): Improve the diagnostics for jest/no-confusing-set-timeout rule. #16815, perf(linter): jest/no-confusing-set-timeout: do not lowercase import name #17324), not a fix for this false positive.Disclosure
This was prepared with AI assistance and has been reviewed by a human.