diff --git a/crates/oxc_linter/data/vitest_compatible_jest_rules.json b/crates/oxc_linter/data/vitest_compatible_jest_rules.json index d88d35eed5ca6..04597999a5b4e 100644 --- a/crates/oxc_linter/data/vitest_compatible_jest_rules.json +++ b/crates/oxc_linter/data/vitest_compatible_jest_rules.json @@ -35,6 +35,7 @@ "prefer-strict-equal", "prefer-to-be", "prefer-to-contain", + "prefer-to-have-been-called-times", "prefer-to-have-length", "prefer-todo", "require-hook", diff --git a/crates/oxc_linter/src/rules/jest/prefer_to_have_been_called_times.rs b/crates/oxc_linter/src/rules/jest/prefer_to_have_been_called_times.rs index 15953b7ed6319..780736fd72d3c 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_to_have_been_called_times.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_to_have_been_called_times.rs @@ -54,6 +54,17 @@ declare_oxc_lint!( /// expect(uncalledFunction).not.toBeCalled(); /// expect(method.mock.calls[0][0]).toStrictEqual(value); /// ``` + /// + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/vitest-dev/eslint-plugin-vitest/blob/main/docs/rules/prefer-to-have-been-called-times.md), + /// to use it, add the following configuration to your `.oxlintrc.json`: + /// + /// ```json + /// { + /// "rules": { + /// "vitest/prefer-to-have-been-called-times": "error" + /// } + /// } + /// ``` PreferToHaveBeenCalledTimes, jest, style, @@ -182,7 +193,7 @@ impl PreferToHaveBeenCalledTimes { fn test() { use crate::tester::Tester; - let pass = vec![ + let mut pass = vec![ "expect.assertions(1)", "expect(fn).toHaveBeenCalledTimes", "expect(fn.mock.calls).toHaveLength", @@ -201,14 +212,14 @@ fn test() { "expect(fn.mock.calls).toContain(1, 2, 3);", ]; - let fail = vec![ + let mut fail = vec![ "expect(method.mock.calls).toHaveLength(1);", "expect(method.mock.calls).resolves.toHaveLength(x);", r#"expect(method["mock"].calls).toHaveLength(0);"#, "expect(my.method.mock.calls).not.toHaveLength(0);", ]; - let fix = vec![ + let mut fix = vec![ ( "expect(method.mock.calls).toHaveLength(1);", "expect(method).toHaveBeenCalledTimes(1);", @@ -245,8 +256,65 @@ fn test() { None, ), ]; + + let pass_vitest = vec![ + "expect.assertions(1)", + "expect(fn).toHaveBeenCalledTimes", + "expect(fn.mock.calls).toHaveLength", + "expect(fn.mock.values).toHaveLength(0)", + "expect(fn.values.calls).toHaveLength(0)", + "expect(fn).toHaveBeenCalledTimes(0)", + "expect(fn).resolves.toHaveBeenCalledTimes(10)", + "expect(fn).not.toHaveBeenCalledTimes(10)", + "expect(fn).toHaveBeenCalledTimes(1)", + "expect(fn).toBeCalledTimes(0);", + "expect(fn).toHaveBeenCalledTimes(0);", + "expect(fn);", + "expect(method.mock.calls[0][0]).toStrictEqual(value);", + "expect(fn.mock.length).toEqual(1);", + "expect(fn.mock.calls).toEqual([]);", + "expect(fn.mock.calls).toContain(1, 2, 3);", + ]; + + pass.extend(pass_vitest); + + let fail_vitest = vec![ + "expect(method.mock.calls).toHaveLength(1);", + "expect(method.mock.calls).resolves.toHaveLength(x);", + r#"expect(method["mock"].calls).toHaveLength(0);"#, + "expect(my.method.mock.calls).not.toHaveLength(0);", + ]; + + fail.extend(fail_vitest); + + let fix_vitest = vec![ + ( + "expect(method.mock.calls).toHaveLength(1);", + "expect(method).toHaveBeenCalledTimes(1);", + None, + ), + ( + "expect(method.mock.calls).resolves.toHaveLength(x);", + "expect(method).resolves.toHaveBeenCalledTimes(x);", + None, + ), + ( + r#"expect(method["mock"].calls).toHaveLength(0);"#, + "expect(method).toHaveBeenCalledTimes(0);", + None, + ), + ( + "expect(my.method.mock.calls).not.toHaveLength(0);", + "expect(my.method).not.toHaveBeenCalledTimes(0);", + None, + ), + ]; + + fix.extend(fix_vitest); + Tester::new(PreferToHaveBeenCalledTimes::NAME, PreferToHaveBeenCalledTimes::PLUGIN, pass, fail) .with_jest_plugin(true) + .with_vitest_plugin(true) .expect_fix(fix) .test_and_snapshot(); } diff --git a/crates/oxc_linter/src/snapshots/jest_prefer_to_have_been_called_times.snap b/crates/oxc_linter/src/snapshots/jest_prefer_to_have_been_called_times.snap index f7762c4d86e25..98053b7812456 100644 --- a/crates/oxc_linter/src/snapshots/jest_prefer_to_have_been_called_times.snap +++ b/crates/oxc_linter/src/snapshots/jest_prefer_to_have_been_called_times.snap @@ -29,3 +29,31 @@ source: crates/oxc_linter/src/tester.rs · ──────────────────────────────────────────────── ╰──── help: Use `toHaveBeenCalledTimes()` to assert the number of times a mock function was called + + ⚠ eslint-plugin-jest(prefer-to-have-been-called-times): Prefer `toHaveBeenCalledTimes()` over `toHaveLength()` when asserting mock call counts + ╭─[prefer_to_have_been_called_times.tsx:1:1] + 1 │ expect(method.mock.calls).toHaveLength(1); + · ───────────────────────────────────────── + ╰──── + help: Use `toHaveBeenCalledTimes()` to assert the number of times a mock function was called + + ⚠ eslint-plugin-jest(prefer-to-have-been-called-times): Prefer `toHaveBeenCalledTimes()` over `toHaveLength()` when asserting mock call counts + ╭─[prefer_to_have_been_called_times.tsx:1:1] + 1 │ expect(method.mock.calls).resolves.toHaveLength(x); + · ────────────────────────────────────────────────── + ╰──── + help: Use `toHaveBeenCalledTimes()` to assert the number of times a mock function was called + + ⚠ eslint-plugin-jest(prefer-to-have-been-called-times): Prefer `toHaveBeenCalledTimes()` over `toHaveLength()` when asserting mock call counts + ╭─[prefer_to_have_been_called_times.tsx:1:1] + 1 │ expect(method["mock"].calls).toHaveLength(0); + · ──────────────────────────────────────────── + ╰──── + help: Use `toHaveBeenCalledTimes()` to assert the number of times a mock function was called + + ⚠ eslint-plugin-jest(prefer-to-have-been-called-times): Prefer `toHaveBeenCalledTimes()` over `toHaveLength()` when asserting mock call counts + ╭─[prefer_to_have_been_called_times.tsx:1:1] + 1 │ expect(my.method.mock.calls).not.toHaveLength(0); + · ──────────────────────────────────────────────── + ╰──── + help: Use `toHaveBeenCalledTimes()` to assert the number of times a mock function was called diff --git a/crates/oxc_linter/src/utils/mod.rs b/crates/oxc_linter/src/utils/mod.rs index 31d995ccc9d3a..d4af39c137673 100644 --- a/crates/oxc_linter/src/utils/mod.rs +++ b/crates/oxc_linter/src/utils/mod.rs @@ -37,7 +37,7 @@ pub use self::{ // the crates/oxc_linter/data/vitest_compatible_jest_rules.json // file is also updated. The JSON file is used by the oxlint-migrate // and eslint-plugin-oxlint repos to keep everything synced. -const VITEST_COMPATIBLE_JEST_RULES: [&str; 43] = [ +const VITEST_COMPATIBLE_JEST_RULES: [&str; 44] = [ "consistent-test-it", "expect-expect", "max-expects", @@ -74,6 +74,7 @@ const VITEST_COMPATIBLE_JEST_RULES: [&str; 43] = [ "prefer-strict-equal", "prefer-to-be", "prefer-to-contain", + "prefer-to-have-been-called-times", "prefer-to-have-length", "prefer-todo", "require-hook",