mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(linter): support vitest/no-disabled-tests (#3717)
This commit is contained in:
parent
ef82c78a72
commit
328445b4ca
15 changed files with 323 additions and 21 deletions
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"rules": {
|
||||||
|
"vitest/no-disabled-tests": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
3
apps/oxlint/fixtures/eslintrc_vitest_replace/foo.js
Normal file
3
apps/oxlint/fixtures/eslintrc_vitest_replace/foo.js
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
test.skip('foo', () => {
|
||||||
|
// ...
|
||||||
|
})
|
||||||
|
|
@ -208,6 +208,10 @@ pub struct EnablePlugins {
|
||||||
#[bpaf(switch, hide_usage)]
|
#[bpaf(switch, hide_usage)]
|
||||||
pub jest_plugin: bool,
|
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
|
/// Enable the JSX-a11y plugin and detect accessibility problems
|
||||||
#[bpaf(switch, hide_usage)]
|
#[bpaf(switch, hide_usage)]
|
||||||
pub jsx_a11y_plugin: bool,
|
pub jsx_a11y_plugin: bool,
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ impl Runner for LintRunner {
|
||||||
.with_import_plugin(enable_plugins.import_plugin)
|
.with_import_plugin(enable_plugins.import_plugin)
|
||||||
.with_jsdoc_plugin(enable_plugins.jsdoc_plugin)
|
.with_jsdoc_plugin(enable_plugins.jsdoc_plugin)
|
||||||
.with_jest_plugin(enable_plugins.jest_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_jsx_a11y_plugin(enable_plugins.jsx_a11y_plugin)
|
||||||
.with_nextjs_plugin(enable_plugins.nextjs_plugin)
|
.with_nextjs_plugin(enable_plugins.nextjs_plugin)
|
||||||
.with_react_perf_plugin(enable_plugins.react_perf_plugin);
|
.with_react_perf_plugin(enable_plugins.react_perf_plugin);
|
||||||
|
|
@ -488,4 +489,26 @@ mod test {
|
||||||
assert!(test_invalid_options(&["--tsconfig", "oxc/tsconfig.json"])
|
assert!(test_invalid_options(&["--tsconfig", "oxc/tsconfig.json"])
|
||||||
.contains("oxc/tsconfig.json\" does not exist, Please provide a valid tsconfig file."));
|
.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"rules": {
|
||||||
|
"vitest/no-disabled-tests": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,9 @@ pub use self::{
|
||||||
rules::OxlintRules,
|
rules::OxlintRules,
|
||||||
settings::{jsdoc::JSDocPluginSettings, OxlintSettings},
|
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
|
/// Oxlint Configuration File
|
||||||
///
|
///
|
||||||
|
|
@ -113,8 +115,10 @@ impl OxlintConfig {
|
||||||
0 => unreachable!(),
|
0 => unreachable!(),
|
||||||
1 => {
|
1 => {
|
||||||
let rule_config = &rule_configs[0];
|
let rule_config = &rule_configs[0];
|
||||||
let rule_name = &rule_config.rule_name;
|
let (rule_name, plugin_name) = transform_rule_and_plugin_name(
|
||||||
let plugin_name = &rule_config.plugin_name;
|
&rule_config.rule_name,
|
||||||
|
&rule_config.plugin_name,
|
||||||
|
);
|
||||||
let severity = rule_config.severity;
|
let severity = rule_config.severity;
|
||||||
match severity {
|
match severity {
|
||||||
AllowWarnDeny::Warn | AllowWarnDeny::Deny => {
|
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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
use rustc_hash::FxHashSet;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use crate::rules::RULES;
|
||||||
|
|
||||||
use super::OxlintConfig;
|
use super::OxlintConfig;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -221,4 +239,17 @@ mod test {
|
||||||
assert_eq!(env.iter().count(), 1);
|
assert_eq!(env.iter().count(), 1);
|
||||||
assert!(globals.is_enabled("foo"));
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use oxc_span::{SourceType, Span};
|
||||||
use oxc_syntax::module_record::ModuleRecord;
|
use oxc_syntax::module_record::ModuleRecord;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
config::OxlintRules,
|
||||||
disable_directives::{DisableDirectives, DisableDirectivesBuilder},
|
disable_directives::{DisableDirectives, DisableDirectivesBuilder},
|
||||||
fixer::{Fix, Message, RuleFixer},
|
fixer::{Fix, Message, RuleFixer},
|
||||||
javascript_globals::GLOBALS,
|
javascript_globals::GLOBALS,
|
||||||
|
|
@ -131,6 +132,10 @@ impl<'a> LintContext<'a> {
|
||||||
&self.eslint_config.env
|
&self.eslint_config.env
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rules(&self) -> &OxlintRules {
|
||||||
|
&self.eslint_config.rules
|
||||||
|
}
|
||||||
|
|
||||||
pub fn env_contains_var(&self, var: &str) -> bool {
|
pub fn env_contains_var(&self, var: &str) -> bool {
|
||||||
for env in self.env().iter() {
|
for env in self.env().iter() {
|
||||||
let env = GLOBALS.get(env).unwrap_or(&GLOBALS["builtin"]);
|
let env = GLOBALS.get(env).unwrap_or(&GLOBALS["builtin"]);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ use oxc_diagnostics::{Error, OxcDiagnostic, Severity};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use serde_json::{Number, Value};
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct LintOptions {
|
pub struct LintOptions {
|
||||||
|
|
@ -21,6 +24,7 @@ pub struct LintOptions {
|
||||||
pub import_plugin: bool,
|
pub import_plugin: bool,
|
||||||
pub jsdoc_plugin: bool,
|
pub jsdoc_plugin: bool,
|
||||||
pub jest_plugin: bool,
|
pub jest_plugin: bool,
|
||||||
|
pub vitest_plugin: bool,
|
||||||
pub jsx_a11y_plugin: bool,
|
pub jsx_a11y_plugin: bool,
|
||||||
pub nextjs_plugin: bool,
|
pub nextjs_plugin: bool,
|
||||||
pub react_perf_plugin: bool,
|
pub react_perf_plugin: bool,
|
||||||
|
|
@ -39,6 +43,7 @@ impl Default for LintOptions {
|
||||||
import_plugin: false,
|
import_plugin: false,
|
||||||
jsdoc_plugin: false,
|
jsdoc_plugin: false,
|
||||||
jest_plugin: false,
|
jest_plugin: false,
|
||||||
|
vitest_plugin: false,
|
||||||
jsx_a11y_plugin: false,
|
jsx_a11y_plugin: false,
|
||||||
nextjs_plugin: false,
|
nextjs_plugin: false,
|
||||||
react_perf_plugin: false,
|
react_perf_plugin: false,
|
||||||
|
|
@ -109,6 +114,12 @@ impl LintOptions {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_vitest_plugin(mut self, yes: bool) -> Self {
|
||||||
|
self.vitest_plugin = yes;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_jsx_a11y_plugin(mut self, yes: bool) -> Self {
|
pub fn with_jsx_a11y_plugin(mut self, yes: bool) -> Self {
|
||||||
self.jsx_a11y_plugin = yes;
|
self.jsx_a11y_plugin = yes;
|
||||||
|
|
@ -277,7 +288,15 @@ impl LintOptions {
|
||||||
"typescript" => self.typescript_plugin,
|
"typescript" => self.typescript_plugin,
|
||||||
"import" => self.import_plugin,
|
"import" => self.import_plugin,
|
||||||
"jsdoc" => self.jsdoc_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,
|
"jsx_a11y" => self.jsx_a11y_plugin,
|
||||||
"nextjs" => self.nextjs_plugin,
|
"nextjs" => self.nextjs_plugin,
|
||||||
"react_perf" => self.react_perf_plugin,
|
"react_perf" => self.react_perf_plugin,
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ use crate::{
|
||||||
context::LintContext,
|
context::LintContext,
|
||||||
rule::Rule,
|
rule::Rule,
|
||||||
utils::{
|
utils::{
|
||||||
collect_possible_jest_call_node, parse_general_jest_fn_call, JestFnKind, JestGeneralFnKind,
|
collect_possible_jest_call_node, get_test_plugin_name, parse_general_jest_fn_call,
|
||||||
ParsedGeneralJestFnCall, PossibleJestNode,
|
JestFnKind, JestGeneralFnKind, ParsedGeneralJestFnCall, PossibleJestNode,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -48,14 +48,25 @@ declare_oxc_lint!(
|
||||||
/// pending();
|
/// 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,
|
NoDisabledTests,
|
||||||
correctness
|
correctness
|
||||||
);
|
);
|
||||||
|
|
||||||
fn no_disabled_tests_diagnostic(x0: &str, x1: &str, span2: Span) -> OxcDiagnostic {
|
fn no_disabled_tests_diagnostic(x0: &str, x1: &str, x2: &str, span3: Span) -> OxcDiagnostic {
|
||||||
OxcDiagnostic::warn(format!("eslint-plugin-jest(no-disabled-tests): {x0:?}"))
|
OxcDiagnostic::warn(format!("{x0}(no-disabled-tests): {x1:?}"))
|
||||||
.with_help(format!("{x1:?}"))
|
.with_help(format!("{x2:?}"))
|
||||||
.with_labels([span2.into()])
|
.with_labels([span3.into()])
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Message {
|
enum Message {
|
||||||
|
|
@ -82,13 +93,19 @@ impl Message {
|
||||||
|
|
||||||
impl Rule for NoDisabledTests {
|
impl Rule for NoDisabledTests {
|
||||||
fn run_once(&self, ctx: &LintContext) {
|
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) {
|
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;
|
let node = possible_jest_node.node;
|
||||||
if let AstKind::CallExpression(call_expr) = node.kind() {
|
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) {
|
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"))
|
&& members.iter().all(|member| member.is_name_unequal("todo"))
|
||||||
{
|
{
|
||||||
let (error, help) = Message::MissingFunction.details();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +137,12 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>)
|
||||||
} else {
|
} else {
|
||||||
Message::DisabledTestWithX.details()
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +154,12 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>)
|
||||||
} else {
|
} else {
|
||||||
Message::DisabledTestWithSkip.details()
|
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 {
|
} else if let Expression::Identifier(ident) = &call_expr.callee {
|
||||||
if ident.name.as_str() == "pending"
|
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() })`
|
// `describe('foo', function () { pending() })`
|
||||||
let (error, help) = Message::Pending.details();
|
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() {
|
fn test() {
|
||||||
use crate::tester::Tester;
|
use crate::tester::Tester;
|
||||||
|
|
||||||
let pass = vec![
|
let mut pass = vec![
|
||||||
("describe('foo', function () {})", None),
|
("describe('foo', function () {})", None),
|
||||||
("it('foo', function () {})", None),
|
("it('foo', function () {})", None),
|
||||||
("describe.only('foo', function () {})", None),
|
("describe.only('foo', function () {})", None),
|
||||||
|
|
@ -184,7 +221,7 @@ fn test() {
|
||||||
("import { test } from './test-utils'; test('something');", None),
|
("import { test } from './test-utils'; test('something');", None),
|
||||||
];
|
];
|
||||||
|
|
||||||
let fail = vec![
|
let mut fail = vec![
|
||||||
("describe.skip('foo', function () {})", None),
|
("describe.skip('foo', function () {})", None),
|
||||||
("describe.skip.each([1, 2, 3])('%s', (a, b) => {});", None),
|
("describe.skip.each([1, 2, 3])('%s', (a, b) => {});", None),
|
||||||
("xdescribe.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),
|
("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#"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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,3 +182,75 @@ source: crates/oxc_linter/src/tester.rs
|
||||||
· ─────────────────
|
· ─────────────────
|
||||||
╰────
|
╰────
|
||||||
help: "Add function argument"
|
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`"
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ pub struct Tester {
|
||||||
current_working_directory: Box<Path>,
|
current_working_directory: Box<Path>,
|
||||||
import_plugin: bool,
|
import_plugin: bool,
|
||||||
jest_plugin: bool,
|
jest_plugin: bool,
|
||||||
|
vitest_plugin: bool,
|
||||||
jsx_a11y_plugin: bool,
|
jsx_a11y_plugin: bool,
|
||||||
nextjs_plugin: bool,
|
nextjs_plugin: bool,
|
||||||
react_perf_plugin: bool,
|
react_perf_plugin: bool,
|
||||||
|
|
@ -125,6 +126,7 @@ impl Tester {
|
||||||
jsx_a11y_plugin: false,
|
jsx_a11y_plugin: false,
|
||||||
nextjs_plugin: false,
|
nextjs_plugin: false,
|
||||||
react_perf_plugin: false,
|
react_perf_plugin: false,
|
||||||
|
vitest_plugin: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,6 +152,11 @@ impl Tester {
|
||||||
self
|
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 {
|
pub fn with_jsx_a11y_plugin(mut self, yes: bool) -> Self {
|
||||||
self.jsx_a11y_plugin = yes;
|
self.jsx_a11y_plugin = yes;
|
||||||
self
|
self
|
||||||
|
|
@ -255,6 +262,7 @@ impl Tester {
|
||||||
.with_fix(is_fix)
|
.with_fix(is_fix)
|
||||||
.with_import_plugin(self.import_plugin)
|
.with_import_plugin(self.import_plugin)
|
||||||
.with_jest_plugin(self.jest_plugin)
|
.with_jest_plugin(self.jest_plugin)
|
||||||
|
.with_vitest_plugin(self.vitest_plugin)
|
||||||
.with_jsx_a11y_plugin(self.jsx_a11y_plugin)
|
.with_jsx_a11y_plugin(self.jsx_a11y_plugin)
|
||||||
.with_nextjs_plugin(self.nextjs_plugin)
|
.with_nextjs_plugin(self.nextjs_plugin)
|
||||||
.with_react_perf_plugin(self.react_perf_plugin);
|
.with_react_perf_plugin(self.react_perf_plugin);
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ fn collect_ids_referenced_to_import<'a>(
|
||||||
};
|
};
|
||||||
let name = ctx.symbols().get_name(symbol_id);
|
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 original = find_original_name(import_decl, name);
|
||||||
let mut ret = vec![];
|
let mut ret = vec![];
|
||||||
for reference_id in reference_ids {
|
for reference_id in reference_ids {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,39 @@ mod react_perf;
|
||||||
mod tree_shaking;
|
mod tree_shaking;
|
||||||
mod unicorn;
|
mod unicorn;
|
||||||
|
|
||||||
|
use crate::LintContext;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
jest::*, jsdoc::*, nextjs::*, react::*, react_perf::*, tree_shaking::*, unicorn::*,
|
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")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,8 @@ Arguments:
|
||||||
Enable the experimental jsdoc plugin and detect JSDoc problems
|
Enable the experimental jsdoc plugin and detect JSDoc problems
|
||||||
- **` --jest-plugin`** —
|
- **` --jest-plugin`** —
|
||||||
Enable the Jest plugin and detect test problems
|
Enable the Jest plugin and detect test problems
|
||||||
|
- **` --vitest-plugin`** —
|
||||||
|
Enable the Vitest plugin and detect test problems
|
||||||
- **` --jsx-a11y-plugin`** —
|
- **` --jsx-a11y-plugin`** —
|
||||||
Enable the JSX-a11y plugin and detect accessibility problems
|
Enable the JSX-a11y plugin and detect accessibility problems
|
||||||
- **` --nextjs-plugin`** —
|
- **` --nextjs-plugin`** —
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ Enable Plugins
|
||||||
recommended to use along side with the `--tsconfig` option.
|
recommended to use along side with the `--tsconfig` option.
|
||||||
--jsdoc-plugin Enable the experimental jsdoc plugin and detect JSDoc problems
|
--jsdoc-plugin Enable the experimental jsdoc plugin and detect JSDoc problems
|
||||||
--jest-plugin Enable the Jest plugin and detect test 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
|
--jsx-a11y-plugin Enable the JSX-a11y plugin and detect accessibility problems
|
||||||
--nextjs-plugin Enable the Next.js plugin and detect Next.js 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
|
--react-perf-plugin Enable the React performance plugin and detect rendering performance
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue