Skip to content

Commit

Permalink
feat(linter): eslint-plugin-vitest/no-import-node-test (#4440)
Browse files Browse the repository at this point in the history
  • Loading branch information
eryue0220 authored Jul 29, 2024
1 parent 96602bf commit d8c2a83
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 1 deletion.
1 change: 1 addition & 0 deletions crates/oxc_linter/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ impl LintOptions {
}
false
}
"vitest" => self.vitest_plugin,
"jsx_a11y" => self.jsx_a11y_plugin,
"nextjs" => self.nextjs_plugin,
"react_perf" => self.react_perf_plugin,
Expand Down
5 changes: 5 additions & 0 deletions crates/oxc_linter/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ mod promise {
pub mod param_names;
}

mod vitest {
pub mod no_import_node_test;
}

oxc_macros::declare_all_lint_rules! {
eslint::array_callback_return,
eslint::constructor_super,
Expand Down Expand Up @@ -837,4 +841,5 @@ oxc_macros::declare_all_lint_rules! {
promise::avoid_new,
promise::no_new_statics,
promise::param_names,
vitest::no_import_node_test,
}
79 changes: 79 additions & 0 deletions crates/oxc_linter/src/rules/vitest/no_import_node_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{context::LintContext, rule::Rule};

fn no_import_node_test(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("disallow importing `node:test`".to_string())
.with_help("Import from `vitest` instead of `node:test`")
.with_label(span0)
}

#[derive(Debug, Default, Clone)]
pub struct NoImportNodeTest;

declare_oxc_lint!(
/// ### What it does
///
/// This rule warns when `node:test` is imported (usually accidentally). With `--fix`, it will replace the import with `vitest`.
///
/// ### Examples
///
/// ```javascript
/// // invalid
/// import { test } from 'node:test'
/// import { expect } from 'vitest'
///
/// test('foo', () => {
/// expect(1).toBe(1)
/// })
/// ```
///
/// ```javascript
/// // valid
/// import { test, expect } from 'vitest'
///
/// test('foo', () => {
/// expect(1).toBe(1)
/// })
/// ```
NoImportNodeTest,
style,
);

impl Rule for NoImportNodeTest {
fn run_once(&self, ctx: &LintContext<'_>) {
let module_record = ctx.module_record();

if let Some(node_test_module) = module_record.requested_modules.get("node:test") {
if let Some(requested_module) = node_test_module.first() {
ctx.diagnostic_with_fix(no_import_node_test(requested_module.span()), |fixer| {
fixer.replace(requested_module.span(), "\"vitest\"")
});
}
}
}
}

#[test]
fn test() {
use crate::tester::Tester;

let pass = vec![(r#"import { test } from "vitest""#, None)];

let fail = vec![
(r#"import { test } from "node:test""#, None),
("import * as foo from 'node:test'", None),
];

let fix = vec![
(r#"import { test } from "node:test""#, r#"import { test } from "vitest""#, None),
(r#"import * as foo from "node:test""#, r#"import * as foo from "vitest""#, None),
];

Tester::new(NoImportNodeTest::NAME, pass, fail)
.with_vitest_plugin(true)
.expect_fix(fix)
.test_and_snapshot();
}
17 changes: 17 additions & 0 deletions crates/oxc_linter/src/snapshots/no_import_node_test.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
source: crates/oxc_linter/src/tester.rs
assertion_line: 216
---
eslint-plugin-vitest(no-import-node-test): disallow importing `node:test`
╭─[no_import_node_test.tsx:1:22]
1import { test } from "node:test"
· ───────────
╰────
help: Import from `vitest` instead of `node:test`

eslint-plugin-vitest(no-import-node-test): disallow importing `node:test`
╭─[no_import_node_test.tsx:1:22]
1import * as foo from 'node:test'
· ───────────
╰────
help: Import from `vitest` instead of `node:test`
3 changes: 2 additions & 1 deletion tasks/benchmark/benches/linter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ fn bench_linter(criterion: &mut Criterion) {
.with_jest_plugin(true)
.with_jsx_a11y_plugin(true)
.with_nextjs_plugin(true)
.with_react_perf_plugin(true);
.with_react_perf_plugin(true)
.with_vitest_plugin(true);
let linter = Linter::from_options(lint_options).unwrap();
let semantic = Rc::new(semantic_ret.semantic);
b.iter(|| linter.run(Path::new(std::ffi::OsStr::new("")), Rc::clone(&semantic)));
Expand Down

0 comments on commit d8c2a83

Please sign in to comment.