Repository: oxc-project/oxc (2026-04-02T16:18:51Z)

Issue:
linter: `jest` and `vitest` plugins do not work with `vite-plus/test`
### What version of Oxlint are you using?

1.58.0

### What command did you run?

`vp lint`

### What does your `.oxlintrc.json` (or `oxlint.config.ts`) config file look like?

### `vite.config.ts`

```ts
import { defineConfig } from "vite-plus";

export default defineConfig({
  lint: {
    options: { typeAware: true, typeCheck: true },
    plugins: ["jest", "vitest"],
    rules: {
      "jest/expect-expect": "error",
      "vitest/warn-todo": "error",
    },
  },
});
```


### What happened?

When `test` is imported from `vite-plus/test` instead of `vitest`, the Oxlint `jest` and `vitest` plugins do not recognize it as a test function, so the plugin rules silently do nothing.

See a reproduction here: https://github.com/dvanoni/vite-plus-test-lint-issue

```ts
import { test as vpTest } from "vite-plus/test";
import { test as vitestTest } from "vitest";

// ✗ Should error (jest/expect-expect) — but does NOT
vpTest(
  "vite-plus/test does not have expected jest/expect-expect lint error",
  () => {},
);

// ✗ Should error (vitest/warn-todo) — but does NOT
vpTest.todo(
  "vite-plus/test does not have expected vitest/warn-todo lint error",
  () => {},
);

// ✓ Correctly errors (jest/expect-expect)
vitestTest("vitest does have expected jest/expect-expect lint error", () => {});

// ✓ Correctly errors (vitest/warn-todo)
vitestTest.todo(
  "vitest does have expected vitest/warn-todo lint error",
  () => {},
);


Discussion:

Patch:
diff --git a/crates/oxc_linter/src/frameworks.rs b/crates/oxc_linter/src/frameworks.rs
index 2098994212107..2471474a26ec5 100644
--- a/crates/oxc_linter/src/frameworks.rs
+++ b/crates/oxc_linter/src/frameworks.rs
@@ -89,7 +89,9 @@ pub fn is_jestlike_file(path: &Path) -> bool {
 }
 
 pub fn has_vitest_imports(module_record: &ModuleRecord) -> bool {
-    module_record.import_entries.iter().any(|entry| entry.module_request.name() == "vitest")
+    module_record.import_entries.iter().any(|entry| {
+        entry.module_request.name() == "vitest" || entry.module_request.name() == "vite-plus/test"
+    })
 }
 
 pub fn has_jest_imports(module_record: &ModuleRecord) -> bool {
diff --git a/crates/oxc_linter/src/utils/jest.rs b/crates/oxc_linter/src/utils/jest.rs
index 8bc17af4b07b2..306470f01c0f8 100644
--- a/crates/oxc_linter/src/utils/jest.rs
+++ b/crates/oxc_linter/src/utils/jest.rs
@@ -225,7 +225,10 @@ fn collect_ids_referenced_to_import<'a, 'c>(
                 };
                 let name = semantic.scoping().symbol_name(symbol_id);
 
-                if matches!(import_decl.source.value.as_str(), "@jest/globals" | "vitest") {
+                if matches!(
+                    import_decl.source.value.as_str(),
+                    "@jest/globals" | "vitest" | "vite-plus/test"
+                ) {
                     let original = find_original_name(import_decl, name);
                     let ret = reference_ids
                         .iter()


Test patch:
diff --git a/crates/oxc_linter/src/rules/vitest/warn_todo.rs b/crates/oxc_linter/src/rules/vitest/warn_todo.rs
index 026e943847c82..a466e4bea6725 100644
--- a/crates/oxc_linter/src/rules/vitest/warn_todo.rs
+++ b/crates/oxc_linter/src/rules/vitest/warn_todo.rs
@@ -140,6 +140,13 @@ fn test() {
         (vitest_context!(r#"describe.only.todo("foo", function () {})"#)),
         (vitest_context!(r#"it.only.todo("foo", function () {})"#)),
         (vitest_context!(r#"test.only.todo("foo", function () {})"#)),
+        // Issue #20955
+        r#"import { test as vpTest } from "vite-plus/test";
+        vpTest.todo(
+          "vite-plus/test does not have expected vitest/warn-todo lint error",
+          () => {},
+        );
+        "#,
     ];
 
     Tester::new(WarnTodo::NAME, WarnTodo::PLUGIN, pass, fail)
diff --git a/crates/oxc_linter/src/snapshots/vitest_warn_todo.snap b/crates/oxc_linter/src/snapshots/vitest_warn_todo.snap
index 58e03755c4291..8b95df5029149 100644
--- a/crates/oxc_linter/src/snapshots/vitest_warn_todo.snap
+++ b/crates/oxc_linter/src/snapshots/vitest_warn_todo.snap
@@ -73,3 +73,12 @@ source: crates/oxc_linter/src/tester.rs
    ·           ────
    ╰────
   help: Write an actual test and remove the `.todo` modifier before pushing/merging your changes.
+
+  ⚠ eslint-plugin-vitest(warn-todo): The use of `.todo` is not recommended.
+   ╭─[warn_todo.tsx:2:16]
+ 1 │ import { test as vpTest } from "vite-plus/test";
+ 2 │         vpTest.todo(
+   ·                ────
+ 3 │           "vite-plus/test does not have expected vitest/warn-todo lint error",
+   ╰────
+  help: Write an actual test and remove the `.todo` modifier before pushing/merging your changes.