From 328445b4ca821056ea01c19548f784d8df76a5d2 Mon Sep 17 00:00:00 2001 From: mysteryven <33973865+mysteryven@users.noreply.github.com> Date: Mon, 24 Jun 2024 15:16:31 +0000 Subject: [PATCH] feat(linter): support `vitest/no-disabled-tests` (#3717) --- .../eslintrc_vitest_replace/eslintrc.json | 5 + .../fixtures/eslintrc_vitest_replace/foo.js | 3 + apps/oxlint/src/command/lint.rs | 4 + apps/oxlint/src/lint/mod.rs | 23 ++++ .../eslint_config_vitest_replace.json | 5 + crates/oxc_linter/src/config/mod.rs | 37 +++++- crates/oxc_linter/src/context.rs | 5 + crates/oxc_linter/src/options.rs | 23 +++- .../src/rules/jest/no_disabled_tests.rs | 121 +++++++++++++++--- .../src/snapshots/no_disabled_tests.snap | 72 +++++++++++ crates/oxc_linter/src/tester.rs | 8 ++ crates/oxc_linter/src/utils/jest.rs | 2 +- crates/oxc_linter/src/utils/mod.rs | 33 +++++ tasks/website/src/linter/snapshots/cli.snap | 2 + .../src/linter/snapshots/cli_terminal.snap | 1 + 15 files changed, 323 insertions(+), 21 deletions(-) create mode 100644 apps/oxlint/fixtures/eslintrc_vitest_replace/eslintrc.json create mode 100644 apps/oxlint/fixtures/eslintrc_vitest_replace/foo.js create mode 100644 crates/oxc_linter/fixtures/eslint_config_vitest_replace.json diff --git a/apps/oxlint/fixtures/eslintrc_vitest_replace/eslintrc.json b/apps/oxlint/fixtures/eslintrc_vitest_replace/eslintrc.json new file mode 100644 index 0000000000000..9db9a461312ee --- /dev/null +++ b/apps/oxlint/fixtures/eslintrc_vitest_replace/eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "vitest/no-disabled-tests": "error" + } +} diff --git a/apps/oxlint/fixtures/eslintrc_vitest_replace/foo.js b/apps/oxlint/fixtures/eslintrc_vitest_replace/foo.js new file mode 100644 index 0000000000000..6f0f89fd0b220 --- /dev/null +++ b/apps/oxlint/fixtures/eslintrc_vitest_replace/foo.js @@ -0,0 +1,3 @@ +test.skip('foo', () => { + // ... +}) diff --git a/apps/oxlint/src/command/lint.rs b/apps/oxlint/src/command/lint.rs index 8b3c7a88b6a06..de29b4720481a 100644 --- a/apps/oxlint/src/command/lint.rs +++ b/apps/oxlint/src/command/lint.rs @@ -208,6 +208,10 @@ pub struct EnablePlugins { #[bpaf(switch, hide_usage)] pub jest_plugin: bool, + /// Enable the Vitest plugin and detect test problems + #[bpaf(switch, hide_usage)] + pub vitest_plugin: bool, + /// Enable the JSX-a11y plugin and detect accessibility problems #[bpaf(switch, hide_usage)] pub jsx_a11y_plugin: bool, diff --git a/apps/oxlint/src/lint/mod.rs b/apps/oxlint/src/lint/mod.rs index 3288eb8edef7b..9f6a2a45d42ab 100644 --- a/apps/oxlint/src/lint/mod.rs +++ b/apps/oxlint/src/lint/mod.rs @@ -101,6 +101,7 @@ impl Runner for LintRunner { .with_import_plugin(enable_plugins.import_plugin) .with_jsdoc_plugin(enable_plugins.jsdoc_plugin) .with_jest_plugin(enable_plugins.jest_plugin) + .with_vitest_plugin(enable_plugins.vitest_plugin) .with_jsx_a11y_plugin(enable_plugins.jsx_a11y_plugin) .with_nextjs_plugin(enable_plugins.nextjs_plugin) .with_react_perf_plugin(enable_plugins.react_perf_plugin); @@ -488,4 +489,26 @@ mod test { assert!(test_invalid_options(&["--tsconfig", "oxc/tsconfig.json"]) .contains("oxc/tsconfig.json\" does not exist, Please provide a valid tsconfig file.")); } + + #[test] + fn test_enable_vitest_plugin() { + let args = &[ + "-c", + "fixtures/eslintrc_vitest_replace/eslintrc.json", + "fixtures/eslintrc_vitest_replace/foo.js", + ]; + let result = test(args); + assert_eq!(result.number_of_files, 1); + assert_eq!(result.number_of_errors, 0); + + let args = &[ + "--vitest-plugin", + "-c", + "fixtures/eslintrc_vitest_replace/eslintrc.json", + "fixtures/eslintrc_vitest_replace/foo.js", + ]; + let result = test(args); + assert_eq!(result.number_of_files, 1); + assert_eq!(result.number_of_errors, 1); + } } diff --git a/crates/oxc_linter/fixtures/eslint_config_vitest_replace.json b/crates/oxc_linter/fixtures/eslint_config_vitest_replace.json new file mode 100644 index 0000000000000..9db9a461312ee --- /dev/null +++ b/crates/oxc_linter/fixtures/eslint_config_vitest_replace.json @@ -0,0 +1,5 @@ +{ + "rules": { + "vitest/no-disabled-tests": "error" + } +} diff --git a/crates/oxc_linter/src/config/mod.rs b/crates/oxc_linter/src/config/mod.rs index ca7dfd9825b48..db9580fee54b7 100644 --- a/crates/oxc_linter/src/config/mod.rs +++ b/crates/oxc_linter/src/config/mod.rs @@ -16,7 +16,9 @@ pub use self::{ rules::OxlintRules, settings::{jsdoc::JSDocPluginSettings, OxlintSettings}, }; -use crate::{rules::RuleEnum, AllowWarnDeny, RuleWithSeverity}; +use crate::{ + rules::RuleEnum, utils::is_jest_rule_adapted_to_vitest, AllowWarnDeny, RuleWithSeverity, +}; /// Oxlint Configuration File /// @@ -113,8 +115,10 @@ impl OxlintConfig { 0 => unreachable!(), 1 => { let rule_config = &rule_configs[0]; - let rule_name = &rule_config.rule_name; - let plugin_name = &rule_config.plugin_name; + let (rule_name, plugin_name) = transform_rule_and_plugin_name( + &rule_config.rule_name, + &rule_config.plugin_name, + ); let severity = rule_config.severity; match severity { AllowWarnDeny::Warn | AllowWarnDeny::Deny => { @@ -168,12 +172,26 @@ impl OxlintConfig { } } +fn transform_rule_and_plugin_name<'a>( + rule_name: &'a str, + plugin_name: &'a str, +) -> (&'a str, &'a str) { + if plugin_name == "vitest" && is_jest_rule_adapted_to_vitest(rule_name) { + return (rule_name, "jest"); + } + + (rule_name, plugin_name) +} + #[cfg(test)] mod test { use std::env; + use rustc_hash::FxHashSet; use serde::Deserialize; + use crate::rules::RULES; + use super::OxlintConfig; #[test] @@ -221,4 +239,17 @@ mod test { assert_eq!(env.iter().count(), 1); assert!(globals.is_enabled("foo")); } + + #[test] + fn test_vitest_rule_replace() { + let fixture_path: std::path::PathBuf = + env::current_dir().unwrap().join("fixtures/eslint_config_vitest_replace.json"); + let config = OxlintConfig::from_file(&fixture_path).unwrap(); + let mut set = FxHashSet::default(); + config.override_rules(&mut set, &RULES); + + let rule = set.into_iter().next().unwrap(); + assert_eq!(rule.name(), "no-disabled-tests"); + assert_eq!(rule.plugin_name(), "jest"); + } } diff --git a/crates/oxc_linter/src/context.rs b/crates/oxc_linter/src/context.rs index 668522e885b48..f30b9d6fdde75 100644 --- a/crates/oxc_linter/src/context.rs +++ b/crates/oxc_linter/src/context.rs @@ -7,6 +7,7 @@ use oxc_span::{SourceType, Span}; use oxc_syntax::module_record::ModuleRecord; use crate::{ + config::OxlintRules, disable_directives::{DisableDirectives, DisableDirectivesBuilder}, fixer::{Fix, Message, RuleFixer}, javascript_globals::GLOBALS, @@ -131,6 +132,10 @@ impl<'a> LintContext<'a> { &self.eslint_config.env } + pub fn rules(&self) -> &OxlintRules { + &self.eslint_config.rules + } + pub fn env_contains_var(&self, var: &str) -> bool { for env in self.env().iter() { let env = GLOBALS.get(env).unwrap_or(&GLOBALS["builtin"]); diff --git a/crates/oxc_linter/src/options.rs b/crates/oxc_linter/src/options.rs index 138236cbc0eac..258ec0d2167df 100644 --- a/crates/oxc_linter/src/options.rs +++ b/crates/oxc_linter/src/options.rs @@ -4,7 +4,10 @@ use oxc_diagnostics::{Error, OxcDiagnostic, Severity}; use rustc_hash::FxHashSet; use serde_json::{Number, Value}; -use crate::{config::OxlintConfig, rules::RULES, RuleCategory, RuleEnum, RuleWithSeverity}; +use crate::{ + config::OxlintConfig, rules::RULES, utils::is_jest_rule_adapted_to_vitest, RuleCategory, + RuleEnum, RuleWithSeverity, +}; #[derive(Debug)] pub struct LintOptions { @@ -21,6 +24,7 @@ pub struct LintOptions { pub import_plugin: bool, pub jsdoc_plugin: bool, pub jest_plugin: bool, + pub vitest_plugin: bool, pub jsx_a11y_plugin: bool, pub nextjs_plugin: bool, pub react_perf_plugin: bool, @@ -39,6 +43,7 @@ impl Default for LintOptions { import_plugin: false, jsdoc_plugin: false, jest_plugin: false, + vitest_plugin: false, jsx_a11y_plugin: false, nextjs_plugin: false, react_perf_plugin: false, @@ -109,6 +114,12 @@ impl LintOptions { self } + #[must_use] + pub fn with_vitest_plugin(mut self, yes: bool) -> Self { + self.vitest_plugin = yes; + self + } + #[must_use] pub fn with_jsx_a11y_plugin(mut self, yes: bool) -> Self { self.jsx_a11y_plugin = yes; @@ -277,7 +288,15 @@ impl LintOptions { "typescript" => self.typescript_plugin, "import" => self.import_plugin, "jsdoc" => self.jsdoc_plugin, - "jest" => self.jest_plugin, + "jest" => { + if self.jest_plugin { + return true; + } + if self.vitest_plugin && is_jest_rule_adapted_to_vitest(rule.name()) { + return true; + } + false + } "jsx_a11y" => self.jsx_a11y_plugin, "nextjs" => self.nextjs_plugin, "react_perf" => self.react_perf_plugin, diff --git a/crates/oxc_linter/src/rules/jest/no_disabled_tests.rs b/crates/oxc_linter/src/rules/jest/no_disabled_tests.rs index cc92ce62a6848..0ae05ca4addaa 100644 --- a/crates/oxc_linter/src/rules/jest/no_disabled_tests.rs +++ b/crates/oxc_linter/src/rules/jest/no_disabled_tests.rs @@ -7,8 +7,8 @@ use crate::{ context::LintContext, rule::Rule, utils::{ - collect_possible_jest_call_node, parse_general_jest_fn_call, JestFnKind, JestGeneralFnKind, - ParsedGeneralJestFnCall, PossibleJestNode, + collect_possible_jest_call_node, get_test_plugin_name, parse_general_jest_fn_call, + JestFnKind, JestGeneralFnKind, ParsedGeneralJestFnCall, PossibleJestNode, }, }; @@ -48,14 +48,25 @@ declare_oxc_lint!( /// pending(); /// }); /// ``` + /// + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-disabled-tests.md), + /// to use it, add the following configuration to your `.eslintrc.json`: + /// + /// ```json + /// { + /// "rules": { + /// "vitest/no-disabled-tests": "error" + /// } + /// } + /// ``` NoDisabledTests, correctness ); -fn no_disabled_tests_diagnostic(x0: &str, x1: &str, span2: Span) -> OxcDiagnostic { - OxcDiagnostic::warn(format!("eslint-plugin-jest(no-disabled-tests): {x0:?}")) - .with_help(format!("{x1:?}")) - .with_labels([span2.into()]) +fn no_disabled_tests_diagnostic(x0: &str, x1: &str, x2: &str, span3: Span) -> OxcDiagnostic { + OxcDiagnostic::warn(format!("{x0}(no-disabled-tests): {x1:?}")) + .with_help(format!("{x2:?}")) + .with_labels([span3.into()]) } enum Message { @@ -82,13 +93,19 @@ impl Message { impl Rule for NoDisabledTests { fn run_once(&self, ctx: &LintContext) { + let plugin_name = get_test_plugin_name(ctx); + for possible_jest_node in &collect_possible_jest_call_node(ctx) { - run(possible_jest_node, ctx); + run(possible_jest_node, plugin_name, ctx); } } } -fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) { +fn run<'a>( + possible_jest_node: &PossibleJestNode<'a, '_>, + plugin_name: &str, + ctx: &LintContext<'a>, +) { let node = possible_jest_node.node; if let AstKind::CallExpression(call_expr) = node.kind() { if let Some(jest_fn_call) = parse_general_jest_fn_call(call_expr, possible_jest_node, ctx) { @@ -103,7 +120,12 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) && members.iter().all(|member| member.is_name_unequal("todo")) { let (error, help) = Message::MissingFunction.details(); - ctx.diagnostic(no_disabled_tests_diagnostic(error, help, call_expr.span)); + ctx.diagnostic(no_disabled_tests_diagnostic( + plugin_name, + error, + help, + call_expr.span, + )); return; } @@ -115,7 +137,12 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) } else { Message::DisabledTestWithX.details() }; - ctx.diagnostic(no_disabled_tests_diagnostic(error, help, call_expr.callee.span())); + ctx.diagnostic(no_disabled_tests_diagnostic( + plugin_name, + error, + help, + call_expr.callee.span(), + )); return; } @@ -127,7 +154,12 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) } else { Message::DisabledTestWithSkip.details() }; - ctx.diagnostic(no_disabled_tests_diagnostic(error, help, call_expr.callee.span())); + ctx.diagnostic(no_disabled_tests_diagnostic( + plugin_name, + error, + help, + call_expr.callee.span(), + )); } } else if let Expression::Identifier(ident) = &call_expr.callee { if ident.name.as_str() == "pending" @@ -135,7 +167,12 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) { // `describe('foo', function () { pending() })` let (error, help) = Message::Pending.details(); - ctx.diagnostic(no_disabled_tests_diagnostic(error, help, call_expr.span)); + ctx.diagnostic(no_disabled_tests_diagnostic( + plugin_name, + error, + help, + call_expr.span, + )); } } } @@ -145,7 +182,7 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) fn test() { use crate::tester::Tester; - let pass = vec![ + let mut pass = vec![ ("describe('foo', function () {})", None), ("it('foo', function () {})", None), ("describe.only('foo', function () {})", None), @@ -184,7 +221,7 @@ fn test() { ("import { test } from './test-utils'; test('something');", None), ]; - let fail = vec![ + let mut fail = vec![ ("describe.skip('foo', function () {})", None), ("describe.skip.each([1, 2, 3])('%s', (a, b) => {});", None), ("xdescribe.each([1, 2, 3])('%s', (a, b) => {});", None), @@ -213,5 +250,59 @@ fn test() { ("import { test } from '@jest/globals';test('something');", None), ]; - Tester::new(NoDisabledTests::NAME, pass, fail).with_jest_plugin(true).test_and_snapshot(); + let pass_vitest = vec![ + r#"describe("foo", function () {})"#, + r#"it("foo", function () {})"#, + r#"describe.only("foo", function () {})"#, + r#"it.only("foo", function () {})"#, + r#"it.each("foo", () => {})"#, + r#"it.concurrent("foo", function () {})"#, + r#"test("foo", function () {})"#, + r#"test.only("foo", function () {})"#, + r#"test.concurrent("foo", function () {})"#, + r#"describe[`${"skip"}`]("foo", function () {})"#, + r#"it.todo("fill this later")"#, + "var appliedSkip = describe.skip; appliedSkip.apply(describe)", + "var calledSkip = it.skip; calledSkip.call(it)", + "({ f: function () {} }).f()", + "(a || b).f()", + "itHappensToStartWithIt()", + "testSomething()", + "xitSomethingElse()", + "xitiViewMap()", + r#" + import { pending } from "actions" + test("foo", () => { + expect(pending()).toEqual({}) + }) + "#, + " + import { test } from './test-utils'; + test('something'); + ", + ]; + + let fail_vitest = vec![ + r#"describe.skip("foo", function () {})"#, + r#"xtest("foo", function () {})"#, + r#"xit.each``("foo", function () {})"#, + r#"xtest.each``("foo", function () {})"#, + r#"xit.each([])("foo", function () {})"#, + r#"it("has title but no callback")"#, + r#"test("has title but no callback")"#, + r#"it("contains a call to pending", function () { pending() })"#, + "pending();", + r#" + import { describe } from 'vitest'; + describe.skip("foo", function () {}) + "#, + ]; + + pass.extend(pass_vitest.into_iter().map(|x| (x, None))); + fail.extend(fail_vitest.into_iter().map(|x| (x, None))); + + Tester::new(NoDisabledTests::NAME, pass, fail) + .with_jest_plugin(true) + .with_vitest_plugin(true) + .test_and_snapshot(); } diff --git a/crates/oxc_linter/src/snapshots/no_disabled_tests.snap b/crates/oxc_linter/src/snapshots/no_disabled_tests.snap index bd3e45064893b..c765a72248fc7 100644 --- a/crates/oxc_linter/src/snapshots/no_disabled_tests.snap +++ b/crates/oxc_linter/src/snapshots/no_disabled_tests.snap @@ -182,3 +182,75 @@ source: crates/oxc_linter/src/tester.rs · ───────────────── ╰──── help: "Add function argument" + + ⚠ eslint-plugin-jest(no-disabled-tests): "Disabled test suite" + ╭─[no_disabled_tests.tsx:1:1] + 1 │ describe.skip("foo", function () {}) + · ───────────── + ╰──── + help: "Remove the appending `.skip`" + + ⚠ eslint-plugin-jest(no-disabled-tests): "Disabled test" + ╭─[no_disabled_tests.tsx:1:1] + 1 │ xtest("foo", function () {}) + · ───── + ╰──── + help: "Remove x prefix" + + ⚠ eslint-plugin-jest(no-disabled-tests): "Disabled test" + ╭─[no_disabled_tests.tsx:1:1] + 1 │ xit.each``("foo", function () {}) + · ────────── + ╰──── + help: "Remove x prefix" + + ⚠ eslint-plugin-jest(no-disabled-tests): "Disabled test" + ╭─[no_disabled_tests.tsx:1:1] + 1 │ xtest.each``("foo", function () {}) + · ──────────── + ╰──── + help: "Remove x prefix" + + ⚠ eslint-plugin-jest(no-disabled-tests): "Disabled test" + ╭─[no_disabled_tests.tsx:1:1] + 1 │ xit.each([])("foo", function () {}) + · ──────────── + ╰──── + help: "Remove x prefix" + + ⚠ eslint-plugin-jest(no-disabled-tests): "Test is missing function argument" + ╭─[no_disabled_tests.tsx:1:1] + 1 │ it("has title but no callback") + · ─────────────────────────────── + ╰──── + help: "Add function argument" + + ⚠ eslint-plugin-jest(no-disabled-tests): "Test is missing function argument" + ╭─[no_disabled_tests.tsx:1:1] + 1 │ test("has title but no callback") + · ───────────────────────────────── + ╰──── + help: "Add function argument" + + ⚠ eslint-plugin-jest(no-disabled-tests): "Call to pending()" + ╭─[no_disabled_tests.tsx:1:48] + 1 │ it("contains a call to pending", function () { pending() }) + · ───────── + ╰──── + help: "Remove pending() call" + + ⚠ eslint-plugin-jest(no-disabled-tests): "Call to pending()" + ╭─[no_disabled_tests.tsx:1:1] + 1 │ pending(); + · ───────── + ╰──── + help: "Remove pending() call" + + ⚠ eslint-plugin-vitest(no-disabled-tests): "Disabled test suite" + ╭─[no_disabled_tests.tsx:3:13] + 2 │ import { describe } from 'vitest'; + 3 │ describe.skip("foo", function () {}) + · ───────────── + 4 │ + ╰──── + help: "Remove the appending `.skip`" diff --git a/crates/oxc_linter/src/tester.rs b/crates/oxc_linter/src/tester.rs index d16b2bbb65be7..09742d8fb3957 100644 --- a/crates/oxc_linter/src/tester.rs +++ b/crates/oxc_linter/src/tester.rs @@ -96,6 +96,7 @@ pub struct Tester { current_working_directory: Box, import_plugin: bool, jest_plugin: bool, + vitest_plugin: bool, jsx_a11y_plugin: bool, nextjs_plugin: bool, react_perf_plugin: bool, @@ -125,6 +126,7 @@ impl Tester { jsx_a11y_plugin: false, nextjs_plugin: false, react_perf_plugin: false, + vitest_plugin: false, } } @@ -150,6 +152,11 @@ impl Tester { self } + pub fn with_vitest_plugin(mut self, yes: bool) -> Self { + self.vitest_plugin = yes; + self + } + pub fn with_jsx_a11y_plugin(mut self, yes: bool) -> Self { self.jsx_a11y_plugin = yes; self @@ -255,6 +262,7 @@ impl Tester { .with_fix(is_fix) .with_import_plugin(self.import_plugin) .with_jest_plugin(self.jest_plugin) + .with_vitest_plugin(self.vitest_plugin) .with_jsx_a11y_plugin(self.jsx_a11y_plugin) .with_nextjs_plugin(self.nextjs_plugin) .with_react_perf_plugin(self.react_perf_plugin); diff --git a/crates/oxc_linter/src/utils/jest.rs b/crates/oxc_linter/src/utils/jest.rs index b5fa3fc60c466..aebcf7cc471f8 100644 --- a/crates/oxc_linter/src/utils/jest.rs +++ b/crates/oxc_linter/src/utils/jest.rs @@ -206,7 +206,7 @@ fn collect_ids_referenced_to_import<'a>( }; let name = ctx.symbols().get_name(symbol_id); - if import_decl.source.value == "@jest/globals" { + if matches!(import_decl.source.value.as_str(), "@jest/globals" | "vitest") { let original = find_original_name(import_decl, name); let mut ret = vec![]; for reference_id in reference_ids { diff --git a/crates/oxc_linter/src/utils/mod.rs b/crates/oxc_linter/src/utils/mod.rs index faf7d84307c14..1c0410d65b084 100644 --- a/crates/oxc_linter/src/utils/mod.rs +++ b/crates/oxc_linter/src/utils/mod.rs @@ -6,6 +6,39 @@ mod react_perf; mod tree_shaking; mod unicorn; +use crate::LintContext; + pub use self::{ jest::*, jsdoc::*, nextjs::*, react::*, react_perf::*, tree_shaking::*, unicorn::*, }; + +/// Check if the Jest rule is adapted to Vitest. +/// Many Vitest rule are essentially ports of Jest plugin rules with minor modifications. +/// For these rules, we use the corresponding jest rules with some adjustments for compatibility. +pub fn is_jest_rule_adapted_to_vitest(rule_name: &str) -> bool { + matches!(rule_name, "no-disabled-tests") +} + +pub fn get_test_plugin_name(ctx: &LintContext) -> &'static str { + if is_using_vitest(ctx) { + "eslint-plugin-vitest" + } else { + "eslint-plugin-jest" + } +} + +fn is_using_vitest(ctx: &LintContext) -> bool { + // If import 'vitest' is found, we assume the user is using vitest. + if ctx + .semantic() + .module_record() + .import_entries + .iter() + .any(|entry| entry.module_request.name().as_str() == "vitest") + { + return true; + } + + // Or, find the eslint config file + ctx.rules().iter().any(|rule| rule.plugin_name == "vitest") +} diff --git a/tasks/website/src/linter/snapshots/cli.snap b/tasks/website/src/linter/snapshots/cli.snap index ed6c20c08e058..23397ef38ef75 100644 --- a/tasks/website/src/linter/snapshots/cli.snap +++ b/tasks/website/src/linter/snapshots/cli.snap @@ -58,6 +58,8 @@ Arguments: Enable the experimental jsdoc plugin and detect JSDoc problems - **` --jest-plugin`** — Enable the Jest plugin and detect test problems +- **` --vitest-plugin`** — + Enable the Vitest plugin and detect test problems - **` --jsx-a11y-plugin`** — Enable the JSX-a11y plugin and detect accessibility problems - **` --nextjs-plugin`** — diff --git a/tasks/website/src/linter/snapshots/cli_terminal.snap b/tasks/website/src/linter/snapshots/cli_terminal.snap index 511faceabbb29..42246aa3a568c 100644 --- a/tasks/website/src/linter/snapshots/cli_terminal.snap +++ b/tasks/website/src/linter/snapshots/cli_terminal.snap @@ -35,6 +35,7 @@ Enable Plugins recommended to use along side with the `--tsconfig` option. --jsdoc-plugin Enable the experimental jsdoc plugin and detect JSDoc problems --jest-plugin Enable the Jest plugin and detect test problems + --vitest-plugin Enable the Vitest plugin and detect test problems --jsx-a11y-plugin Enable the JSX-a11y plugin and detect accessibility problems --nextjs-plugin Enable the Next.js plugin and detect Next.js problems --react-perf-plugin Enable the React performance plugin and detect rendering performance