mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
fix(linter): jest/vitest rule compat (#4797)
This pr is for jest/vitest compat and add another jest rule condition --------- Co-authored-by: Don Isaac <donald.isaac@gmail.com> Co-authored-by: Wang Wenzhe <mysteryven@gmail.com>
This commit is contained in:
parent
2bc36ccbb6
commit
fdef8aec72
9 changed files with 1360 additions and 12 deletions
|
|
@ -61,6 +61,11 @@ impl FrameworkFlags {
|
|||
pub const fn is_vitest(self) -> bool {
|
||||
self.contains(Self::Vitest)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn is_jest(self) -> bool {
|
||||
self.contains(Self::Jest)
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://jestjs.io/docs/configuration#testmatch-arraystring>
|
||||
|
|
@ -83,3 +88,7 @@ pub(crate) fn is_jestlike_file(path: &Path) -> bool {
|
|||
pub(crate) fn has_vitest_imports(module_record: &ModuleRecord) -> bool {
|
||||
module_record.import_entries.iter().any(|entry| entry.module_request.name() == "vitest")
|
||||
}
|
||||
|
||||
pub(crate) fn has_jest_imports(module_record: &ModuleRecord) -> bool {
|
||||
module_record.import_entries.iter().any(|entry| entry.module_request.name() == "@jest/globals")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,11 +160,12 @@ impl Linter {
|
|||
if self.options.plugins.jest || self.options.plugins.vitest {
|
||||
let mut test_flags = FrameworkFlags::empty();
|
||||
|
||||
if frameworks::is_jestlike_file(path) {
|
||||
test_flags.set(FrameworkFlags::Jest, self.options.plugins.jest);
|
||||
test_flags.set(FrameworkFlags::Vitest, self.options.plugins.vitest);
|
||||
} else if frameworks::has_vitest_imports(ctx.module_record()) {
|
||||
if frameworks::has_vitest_imports(ctx.module_record()) {
|
||||
test_flags.set(FrameworkFlags::Vitest, true);
|
||||
} else if frameworks::is_jestlike_file(path)
|
||||
|| frameworks::has_jest_imports(ctx.module_record())
|
||||
{
|
||||
test_flags.set(FrameworkFlags::Jest, true);
|
||||
}
|
||||
|
||||
ctx = ctx.and_frameworks(test_flags);
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ fn test() {
|
|||
),
|
||||
("window.location = 'valid'", None, None, None),
|
||||
("module.somethingElse = 'foo';", None, None, None),
|
||||
("export const myThing = 'valid'", None, None, None),
|
||||
("export default function () {}", None, None, None),
|
||||
("export const myThing = 'valid'", None, None, Some(PathBuf::from("foo.js"))),
|
||||
("export default function () {}", None, None, Some(PathBuf::from("foo.js"))),
|
||||
("module.exports = function(){}", None, None, None),
|
||||
("module.exports.myThing = 'valid';", None, None, None),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -622,5 +622,5 @@ fn tests() {
|
|||
),
|
||||
];
|
||||
|
||||
Tester::new(RequireHook::NAME, pass, fail).test_and_snapshot();
|
||||
Tester::new(RequireHook::NAME, pass, fail).with_jest_plugin(true).test_and_snapshot();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,12 +95,26 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>)
|
|||
return;
|
||||
}
|
||||
|
||||
if call_expr.arguments.len() == 0 {
|
||||
let arg_len = call_expr.arguments.len();
|
||||
|
||||
// Handle describe.todo("runPrettierFormat")
|
||||
if ctx.frameworks().is_vitest() && arg_len == 1 {
|
||||
if let Some(member_expr) = call_expr.callee.as_member_expression() {
|
||||
let Some(property_name) = member_expr.static_property_name() else {
|
||||
return;
|
||||
};
|
||||
if property_name == "todo" {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if arg_len == 0 {
|
||||
diagnostic(ctx, call_expr.span, Message::NameAndCallback);
|
||||
return;
|
||||
}
|
||||
|
||||
if call_expr.arguments.len() == 1 {
|
||||
if arg_len == 1 {
|
||||
// For better error notice, we locate it to arguments[0]
|
||||
diagnostic(ctx, call_expr.arguments[0].span(), Message::NameAndCallback);
|
||||
return;
|
||||
|
|
@ -353,7 +367,13 @@ fn test() {
|
|||
("fdescribe(\"foo\", () => {})", None),
|
||||
("describe.only(\"foo\", () => {})", None),
|
||||
("describe.skip(\"foo\", () => {})", None),
|
||||
("describe.todo(\"runPrettierFormat\");", None),
|
||||
(
|
||||
"
|
||||
import { describe } from 'vitest';
|
||||
describe.todo(\"runPrettierFormat\");
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
describe('foo', () => {
|
||||
|
|
|
|||
|
|
@ -364,6 +364,8 @@ impl Tester {
|
|||
self.current_working_directory.join(&self.rule_path)
|
||||
} else if let Some(path) = path {
|
||||
self.current_working_directory.join(path)
|
||||
} else if self.plugins.jest {
|
||||
self.rule_path.with_extension("test.tsx")
|
||||
} else {
|
||||
self.rule_path.clone()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,10 @@ use oxc_span::Span;
|
|||
|
||||
use crate::{
|
||||
context::LintContext,
|
||||
utils::jest::{is_pure_string, JestFnKind, JestGeneralFnKind, PossibleJestNode},
|
||||
utils::{
|
||||
jest::{is_pure_string, JestFnKind, JestGeneralFnKind, PossibleJestNode},
|
||||
vitest::VALID_VITEST_FN_CALL_CHAINS,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn parse_jest_fn_call<'a>(
|
||||
|
|
@ -100,7 +103,12 @@ pub fn parse_jest_fn_call<'a>(
|
|||
|
||||
let mut call_chains = Vec::from([Cow::Borrowed(name)]);
|
||||
call_chains.extend(members.iter().filter_map(KnownMemberExpressionProperty::name));
|
||||
if !is_valid_jest_call(&call_chains) {
|
||||
|
||||
if ctx.frameworks().is_jest() && !is_valid_jest_call(&call_chains) {
|
||||
return None;
|
||||
}
|
||||
|
||||
if ctx.frameworks().is_vitest() && !is_valid_vitest_call(&call_chains) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -298,6 +306,10 @@ fn is_valid_jest_call(members: &[Cow<str>]) -> bool {
|
|||
.is_ok()
|
||||
}
|
||||
|
||||
fn is_valid_vitest_call(members: &[Cow<str>]) -> bool {
|
||||
VALID_VITEST_FN_CALL_CHAINS.contains(&members.join("."))
|
||||
}
|
||||
|
||||
fn resolve_to_jest_fn<'a>(
|
||||
call_expr: &'a CallExpression<'a>,
|
||||
original: Option<&'a str>,
|
||||
|
|
@ -333,6 +345,7 @@ impl<'a> ParsedJestFnCall<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParsedGeneralJestFnCall<'a> {
|
||||
pub kind: JestFnKind,
|
||||
pub members: Vec<KnownMemberExpressionProperty<'a>>,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ use super::{
|
|||
PossibleJestNode,
|
||||
};
|
||||
|
||||
mod valid_vitest_fn;
|
||||
pub use crate::utils::vitest::valid_vitest_fn::VALID_VITEST_FN_CALL_CHAINS;
|
||||
|
||||
pub fn parse_expect_and_typeof_vitest_fn_call<'a>(
|
||||
call_expr: &'a CallExpression<'a>,
|
||||
possible_jest_node: &PossibleJestNode<'a, '_>,
|
||||
|
|
|
|||
1300
crates/oxc_linter/src/utils/vitest/valid_vitest_fn.rs
Normal file
1300
crates/oxc_linter/src/utils/vitest/valid_vitest_fn.rs
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue