mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(linter/eslint-plugin-vitest): implement no-conditional-tests (#4955)
This commit is contained in:
parent
6800e694e3
commit
7859f58b4e
3 changed files with 179 additions and 0 deletions
|
|
@ -452,6 +452,7 @@ mod promise {
|
|||
}
|
||||
|
||||
mod vitest {
|
||||
pub mod no_conditional_tests;
|
||||
pub mod no_import_node_test;
|
||||
pub mod prefer_to_be_falsy;
|
||||
pub mod prefer_to_be_truthy;
|
||||
|
|
@ -866,4 +867,5 @@ oxc_macros::declare_all_lint_rules! {
|
|||
vitest::no_import_node_test,
|
||||
vitest::prefer_to_be_falsy,
|
||||
vitest::prefer_to_be_truthy,
|
||||
vitest::no_conditional_tests,
|
||||
}
|
||||
|
|
|
|||
139
crates/oxc_linter/src/rules/vitest/no_conditional_tests.rs
Normal file
139
crates/oxc_linter/src/rules/vitest/no_conditional_tests.rs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
use oxc_ast::AstKind;
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
|
||||
use crate::{
|
||||
context::LintContext,
|
||||
rule::Rule,
|
||||
utils::{
|
||||
collect_possible_jest_call_node, is_type_of_jest_fn_call, JestFnKind, JestGeneralFnKind,
|
||||
PossibleJestNode,
|
||||
},
|
||||
};
|
||||
|
||||
fn no_conditional_tests(span0: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn("Avoid having conditionals in tests")
|
||||
.with_help("Remove the surrounding if statement.")
|
||||
.with_label(span0)
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct NoConditionalTests;
|
||||
|
||||
declare_oxc_lint!(
|
||||
/// ### What it does
|
||||
/// The rule disallows the use of conditional statements within test cases to ensure that tests are deterministic and clearly readable.
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// Examples of **incorrect** code for this rule:
|
||||
/// ```js
|
||||
/// describe('my tests', () => {
|
||||
/// if (true) {
|
||||
/// it('is awesome', () => {
|
||||
/// doTheThing()
|
||||
/// })
|
||||
/// }
|
||||
/// })
|
||||
/// ```
|
||||
///
|
||||
/// Examples of **correct** code for this rule:
|
||||
/// ```js
|
||||
/// describe('my tests', () => {
|
||||
/// it('is awesome', () => {
|
||||
/// doTheThing()
|
||||
/// })
|
||||
/// })
|
||||
/// ```
|
||||
NoConditionalTests,
|
||||
correctness,
|
||||
);
|
||||
|
||||
impl Rule for NoConditionalTests {
|
||||
fn run_once(&self, ctx: &LintContext) {
|
||||
for node in &collect_possible_jest_call_node(ctx) {
|
||||
run(node, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) {
|
||||
let node = possible_jest_node.node;
|
||||
if let AstKind::CallExpression(call_expr) = node.kind() {
|
||||
if is_type_of_jest_fn_call(
|
||||
call_expr,
|
||||
possible_jest_node,
|
||||
ctx,
|
||||
&[
|
||||
JestFnKind::General(JestGeneralFnKind::Describe),
|
||||
JestFnKind::General(JestGeneralFnKind::Test),
|
||||
],
|
||||
) {
|
||||
let if_statement_node = ctx
|
||||
.nodes()
|
||||
.iter_parents(node.id())
|
||||
.find(|node| matches!(node.kind(), AstKind::IfStatement(_)));
|
||||
|
||||
let Some(node) = if_statement_node else { return };
|
||||
|
||||
if let AstKind::IfStatement(if_statement) = node.kind() {
|
||||
ctx.diagnostic(no_conditional_tests(if_statement.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
use crate::tester::Tester;
|
||||
|
||||
let pass = vec![
|
||||
r#"test("shows error", () => {});"#,
|
||||
r#"it("foo", function () {})"#,
|
||||
"it('foo', () => {}); function myTest() { if ('bar') {} }",
|
||||
r#"function myFunc(str: string) {
|
||||
return str;
|
||||
}
|
||||
describe("myTest", () => {
|
||||
it("convert shortened equal filter", () => {
|
||||
expect(
|
||||
myFunc("5")
|
||||
).toEqual("5");
|
||||
});
|
||||
});"#,
|
||||
r#"describe("shows error", () => {
|
||||
if (1 === 2) {
|
||||
myFunc();
|
||||
}
|
||||
expect(true).toBe(false);
|
||||
});"#,
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
r#"describe("shows error", () => {
|
||||
if(true) {
|
||||
test("shows error", () => {
|
||||
expect(true).toBe(true);
|
||||
})
|
||||
}
|
||||
})"#,
|
||||
r#"
|
||||
describe("shows error", () => {
|
||||
if(true) {
|
||||
it("shows error", () => {
|
||||
expect(true).toBe(true);
|
||||
})
|
||||
}
|
||||
})"#,
|
||||
r#"describe("errors", () => {
|
||||
if (Math.random() > 0) {
|
||||
test("test2", () => {
|
||||
expect(true).toBeTruthy();
|
||||
});
|
||||
}
|
||||
});"#,
|
||||
];
|
||||
|
||||
Tester::new(NoConditionalTests::NAME, pass, fail).test_and_snapshot();
|
||||
}
|
||||
38
crates/oxc_linter/src/snapshots/no_conditional_tests.snap
Normal file
38
crates/oxc_linter/src/snapshots/no_conditional_tests.snap
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
---
|
||||
⚠ eslint-plugin-vitest(no-conditional-tests): Avoid having conditionals in tests
|
||||
╭─[no_conditional_tests.tsx:2:8]
|
||||
1 │ describe("shows error", () => {
|
||||
2 │ ╭─▶ if(true) {
|
||||
3 │ │ test("shows error", () => {
|
||||
4 │ │ expect(true).toBe(true);
|
||||
5 │ │ })
|
||||
6 │ ╰─▶ }
|
||||
7 │ })
|
||||
╰────
|
||||
help: Remove the surrounding if statement.
|
||||
|
||||
⚠ eslint-plugin-vitest(no-conditional-tests): Avoid having conditionals in tests
|
||||
╭─[no_conditional_tests.tsx:3:8]
|
||||
2 │ describe("shows error", () => {
|
||||
3 │ ╭─▶ if(true) {
|
||||
4 │ │ it("shows error", () => {
|
||||
5 │ │ expect(true).toBe(true);
|
||||
6 │ │ })
|
||||
7 │ ╰─▶ }
|
||||
8 │ })
|
||||
╰────
|
||||
help: Remove the surrounding if statement.
|
||||
|
||||
⚠ eslint-plugin-vitest(no-conditional-tests): Avoid having conditionals in tests
|
||||
╭─[no_conditional_tests.tsx:2:8]
|
||||
1 │ describe("errors", () => {
|
||||
2 │ ╭─▶ if (Math.random() > 0) {
|
||||
3 │ │ test("test2", () => {
|
||||
4 │ │ expect(true).toBeTruthy();
|
||||
5 │ │ });
|
||||
6 │ ╰─▶ }
|
||||
7 │ });
|
||||
╰────
|
||||
help: Remove the surrounding if statement.
|
||||
Loading…
Reference in a new issue