diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 3db35d40aba20..e21dc30e2899d 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -175,6 +175,7 @@ mod jest { pub mod no_alias_methods; pub mod no_commented_out_tests; pub mod no_conditional_expect; + pub mod no_conditional_in_test; pub mod no_confusing_set_timeout; pub mod no_deprecated_functions; pub mod no_disabled_tests; @@ -606,6 +607,7 @@ oxc_macros::declare_all_lint_rules! { jest::no_alias_methods, jest::no_commented_out_tests, jest::no_conditional_expect, + jest::no_conditional_in_test, jest::no_confusing_set_timeout, jest::no_deprecated_functions, jest::no_disabled_tests, diff --git a/crates/oxc_linter/src/rules/jest/no_conditional_in_test.rs b/crates/oxc_linter/src/rules/jest/no_conditional_in_test.rs new file mode 100644 index 0000000000000..36cc76ad0b0f1 --- /dev/null +++ b/crates/oxc_linter/src/rules/jest/no_conditional_in_test.rs @@ -0,0 +1,648 @@ +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::{is_type_of_jest_fn_call, JestFnKind, PossibleJestNode}, +}; + +fn no_conditional_in_test(span0: Span) -> OxcDiagnostic { + OxcDiagnostic::warn("Disallow conditional logic in tests") + .with_help("Avoid having conditionals in tests.") + .with_label(span0) +} + +#[derive(Debug, Default, Clone)] +pub struct NoConditionalInTest; + +declare_oxc_lint!( + /// ### What it does + /// This rule reports on any use of a conditional statement such as if, switch, and ternary expressions. + /// + /// ### Examples + /// + /// Examples of **incorrect** code for this rule: + /// ```js + /// it('foo', () => { + /// if (true) { + /// doTheThing(); + /// } + /// }); + /// + /// it('bar', () => { + /// switch (mode) { + /// case 'none': + /// generateNone(); + /// case 'single': + /// generateOne(); + /// case 'multiple': + /// generateMany(); + /// } + /// + /// expect(fixtures.length).toBeGreaterThan(-1); + /// }); + /// + /// it('baz', async () => { + /// const promiseValue = () => { + /// return something instanceof Promise + /// ? something + /// : Promise.resolve(something); + /// }; + /// + /// await expect(promiseValue()).resolves.toBe(1); + /// }); + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```js + /// describe('my tests', () => { + /// if (true) { + /// it('foo', () => { + /// doTheThing(); + /// }); + /// } + /// }); + /// + /// beforeEach(() => { + /// switch (mode) { + /// case 'none': + /// generateNone(); + /// case 'single': + /// generateOne(); + /// case 'multiple': + /// generateMany(); + /// } + /// }); + /// + /// it('bar', () => { + /// expect(fixtures.length).toBeGreaterThan(-1); + /// }); + /// + /// const promiseValue = something => { + /// return something instanceof Promise ? something : Promise.resolve(something); + /// }; + /// + /// it('baz', async () => { + /// await expect(promiseValue()).resolves.toBe(1); + /// }); + /// ``` + NoConditionalInTest, + pedantic, +); + +impl Rule for NoConditionalInTest { + fn run<'a>(&self, node: &oxc_semantic::AstNode<'a>, ctx: &LintContext<'a>) { + if matches!( + node.kind(), + AstKind::IfStatement(_) + | AstKind::SwitchStatement(_) + | AstKind::ConditionalExpression(_) + | AstKind::LogicalExpression(_) + ) { + let is_if_statement_in_test = ctx.nodes().iter_parents(node.id()).any(|node| { + let AstKind::CallExpression(call_expr) = node.kind() else { return false }; + let vitest_node = PossibleJestNode { node, original: None }; + + is_type_of_jest_fn_call( + call_expr, + &vitest_node, + ctx, + &[JestFnKind::General(crate::utils::JestGeneralFnKind::Test)], + ) + }); + + if is_if_statement_in_test { + let span = match node.kind() { + AstKind::IfStatement(stmt) => stmt.span, + AstKind::SwitchStatement(stmt) => stmt.span, + AstKind::ConditionalExpression(expr) => expr.span, + AstKind::LogicalExpression(expr) => expr.span, + _ => unreachable!(), + }; + + ctx.diagnostic(no_conditional_in_test(span)); + } + } + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + "const x = y ? 1 : 0", + " + const foo = function (bar) { + return foo ? bar : null; + }; + + it('foo', () => { + foo(); + }); + ", + " + const foo = function (bar) { + return foo ? bar : null; + }; + + it.each()('foo', function () { + foo(); + }); + ", + " + fit.concurrent('foo', () => { + switch('bar') {} + }) + ", + "it('foo', () => {})", + " + switch (true) { + case true: {} + } + ", + " + it('foo', () => {}); + function myTest() { + switch ('bar') { + } + } + ", + " + foo('bar', () => { + switch(baz) {} + }) + ", + " + describe('foo', () => { + switch('bar') {} + }) + ", + " + describe.skip('foo', () => { + switch('bar') {} + }) + ", + " + describe.skip.each()('foo', () => { + switch('bar') {} + }) + ", + " + xdescribe('foo', () => { + switch('bar') {} + }) + ", + " + fdescribe('foo', () => { + switch('bar') {} + }) + ", + " + describe('foo', () => { + switch('bar') {} + }) + switch('bar') {} + ", + " + describe('foo', () => { + afterEach(() => { + switch('bar') {} + }); + }); + ", + " + const values = something.map(thing => { + switch (thing.isFoo) { + case true: + return thing.foo; + default: + return thing.bar; + } + }); + + it('valid', () => { + expect(values).toStrictEqual(['foo']); + }); + ", + " + describe('valid', () => { + const values = something.map(thing => { + switch (thing.isFoo) { + case true: + return thing.foo; + default: + return thing.bar; + } + }); + it('still valid', () => { + expect(values).toStrictEqual(['foo']); + }); + }); + ", + "if (foo) {}", + "it('foo', () => {})", + r#"it("foo", function () {})"#, + "it('foo', () => {}); function myTest() { if ('bar') {} }", + " + foo('bar', () => { + if (baz) {} + }) + ", + " + describe('foo', () => { + if ('bar') {} + }) + ", + " + describe.skip('foo', () => { + if ('bar') {} + }) + ", + " + xdescribe('foo', () => { + if ('bar') {} + }) + ", + " + fdescribe('foo', () => { + if ('bar') {} + }) + ", + " + describe('foo', () => { + if ('bar') {} + }) + if ('baz') {} + ", + " + describe('foo', () => { + afterEach(() => { + if ('bar') {} + }); + }) + ", + " + describe.each``('foo', () => { + afterEach(() => { + if ('bar') {} + }); + }) + ", + " + describe('foo', () => { + beforeEach(() => { + if ('bar') {} + }); + }) + ", + "const foo = bar ? foo : baz;", + " + const values = something.map((thing) => { + if (thing.isFoo) { + return thing.foo + } else { + return thing.bar; + } + }); + + describe('valid', () => { + it('still valid', () => { + expect(values).toStrictEqual(['foo']); + }); + }); + ", + " + describe('valid', () => { + const values = something.map((thing) => { + if (thing.isFoo) { + return thing.foo + } else { + return thing.bar; + } + }); + + describe('still valid', () => { + it('really still valid', () => { + expect(values).toStrictEqual(['foo']); + }); + }); + }); + ", + " + fit.concurrent('foo', () => { + if ('bar') {} + }) + ", + ]; + + let fail = vec![ + " + it('foo', () => { + expect(bar ? foo : baz).toBe(boo); + }) + ", + " + it('foo', function () { + const foo = function (bar) { + return foo ? bar : null; + }; + }); + ", + " + it('foo', () => { + const foo = bar ? foo : baz; + }) + ", + " + it('foo', () => { + const foo = bar ? foo : baz; + }) + const foo = bar ? foo : baz; + ", + " + it('foo', () => { + const foo = bar ? foo : baz; + const anotherFoo = anotherBar ? anotherFoo : anotherBaz; + }) + ", + " + it('is invalid', () => { + const values = something.map(thing => { + switch (thing.isFoo) { + case true: + return thing.foo; + default: + return thing.bar; + } + }); + + expect(values).toStrictEqual(['foo']); + }); + ", + " + it('foo', () => { + switch (true) { + case true: {} + } + }) + ", + " + it('foo', () => { + switch('bar') {} + }) + ", + " + it.skip('foo', () => { + switch('bar') {} + }) + ", + " + it.only('foo', () => { + switch('bar') {} + }) + ", + " + xit('foo', () => { + switch('bar') {} + }) + ", + " + fit('foo', () => { + switch('bar') {} + }) + ", + " + test('foo', () => { + switch('bar') {} + }) + ", + " + test.skip('foo', () => { + switch('bar') {} + }) + ", + " + test.only('foo', () => { + switch('bar') {} + }) + ", + " + xtest('foo', () => { + switch('bar') {} + }) + ", + " + xtest('foo', function () { + switch('bar') {} + }) + ", + " + describe('foo', () => { + it('bar', () => { + + switch('bar') {} + }) + }) + ", + " + describe('foo', () => { + it('bar', () => { + switch('bar') {} + }) + it('baz', () => { + switch('qux') {} + switch('quux') {} + }) + }) + ", + " + it('foo', () => { + callExpression() + switch ('bar') {} + }) + ", + " + describe('valid', () => { + describe('still valid', () => { + it('is not valid', () => { + const values = something.map((thing) => { + switch (thing.isFoo) { + case true: + return thing.foo; + default: + return thing.bar; + } + }); + + switch('invalid') { + case true: + expect(values).toStrictEqual(['foo']); + } + }); + }); + }); + ", + " + it('foo', () => { + const foo = function(bar) { + if (bar) { + return 1; + } else { + return 2; + } + }; + }); + ", + " + it('foo', () => { + function foo(bar) { + if (bar) { + return 1; + } else { + return 2; + } + }; + }); + ", + " + it('foo', () => { + if ('bar') {} + }) + ", + " + it.skip('foo', () => { + if ('bar') {} + }) + ", + " + it.skip('foo', function () { + if ('bar') {} + }) + ", + " + it.only('foo', () => { + if ('bar') {} + }) + ", + " + xit('foo', () => { + if ('bar') {} + }) + ", + " + fit('foo', () => { + if ('bar') {} + }) + ", + " + test('foo', () => { + if ('bar') {} + }) + ", + " + test.skip('foo', () => { + if ('bar') {} + }) + ", + " + test.only('foo', () => { + if ('bar') {} + }) + ", + " + xtest('foo', () => { + if ('bar') {} + }) + ", + " + describe('foo', () => { + it('bar', () => { + if ('bar') {} + }) + }) + ", + " + describe('foo', () => { + it('bar', () => { + if ('bar') {} + }) + it('baz', () => { + if ('qux') {} + if ('quux') {} + }) + }) + ", + " + it('foo', () => { + callExpression() + if ('bar') {} + }) + ", + " + it.each``('foo', () => { + callExpression() + if ('bar') {} + }) + ", + " + it.each()('foo', () => { + callExpression() + if ('bar') {} + }) + ", + " + it.only.each``('foo', () => { + callExpression() + if ('bar') {} + }) + ", + " + it.only.each()('foo', () => { + callExpression() + if ('bar') {} + }) + ", + " + describe('valid', () => { + describe('still valid', () => { + it('is invalid', () => { + const values = something.map((thing) => { + if (thing.isFoo) { + return thing.foo + } else { + return thing.bar; + } + }); + + if ('invalid') { + expect(values).toStrictEqual(['foo']); + } + }); + }); + }); + ", + r#" + test("shows error", () => { + if (1 === 2) { + expect(true).toBe(false); + } + }); + + test("does not show error", () => { + setTimeout(() => console.log("noop")); + if (1 === 2) { + expect(true).toBe(false); + } + }); + "#, + ]; + + Tester::new(NoConditionalInTest::NAME, pass, fail) + .with_jest_plugin(true) + .with_vitest_plugin(true) + .test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_conditional_in_test.snap b/crates/oxc_linter/src/snapshots/no_conditional_in_test.snap new file mode 100644 index 0000000000000..48c9890f84293 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_conditional_in_test.snap @@ -0,0 +1,475 @@ +--- +source: crates/oxc_linter/src/tester.rs +--- + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:21] + 2 │ it('foo', () => { + 3 │ expect(bar ? foo : baz).toBe(boo); + · ─────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:23] + 3 │ const foo = function (bar) { + 4 │ return foo ? bar : null; + · ──────────────── + 5 │ }; + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:26] + 2 │ it('foo', () => { + 3 │ const foo = bar ? foo : baz; + · ─────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:26] + 2 │ it('foo', () => { + 3 │ const foo = bar ? foo : baz; + · ─────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:26] + 2 │ it('foo', () => { + 3 │ const foo = bar ? foo : baz; + · ─────────────── + 4 │ const anotherFoo = anotherBar ? anotherFoo : anotherBaz; + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:33] + 3 │ const foo = bar ? foo : baz; + 4 │ const anotherFoo = anotherBar ? anotherFoo : anotherBaz; + · ──────────────────────────────────── + 5 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:16] + 3 │ const values = something.map(thing => { + 4 │ ╭─▶ switch (thing.isFoo) { + 5 │ │ case true: + 6 │ │ return thing.foo; + 7 │ │ default: + 8 │ │ return thing.bar; + 9 │ ╰─▶ } + 10 │ }); + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ it('foo', () => { + 3 │ ╭─▶ switch (true) { + 4 │ │ case true: {} + 5 │ ╰─▶ } + 6 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ it('foo', () => { + 3 │ switch('bar') {} + · ──────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ it.skip('foo', () => { + 3 │ switch('bar') {} + · ──────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ it.only('foo', () => { + 3 │ switch('bar') {} + · ──────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ xit('foo', () => { + 3 │ switch('bar') {} + · ──────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ fit('foo', () => { + 3 │ switch('bar') {} + · ──────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ test('foo', () => { + 3 │ switch('bar') {} + · ──────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ test.skip('foo', () => { + 3 │ switch('bar') {} + · ──────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ test.only('foo', () => { + 3 │ switch('bar') {} + · ──────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ xtest('foo', () => { + 3 │ switch('bar') {} + · ──────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ xtest('foo', function () { + 3 │ switch('bar') {} + · ──────────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:5:16] + 4 │ + 5 │ switch('bar') {} + · ──────────────── + 6 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:16] + 3 │ it('bar', () => { + 4 │ switch('bar') {} + · ──────────────── + 5 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:7:16] + 6 │ it('baz', () => { + 7 │ switch('qux') {} + · ──────────────── + 8 │ switch('quux') {} + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:8:16] + 7 │ switch('qux') {} + 8 │ switch('quux') {} + · ───────────────── + 9 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:14] + 3 │ callExpression() + 4 │ switch ('bar') {} + · ───────────────── + 5 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:6:20] + 5 │ const values = something.map((thing) => { + 6 │ ╭─▶ switch (thing.isFoo) { + 7 │ │ case true: + 8 │ │ return thing.foo; + 9 │ │ default: + 10 │ │ return thing.bar; + 11 │ ╰─▶ } + 12 │ }); + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:14:18] + 13 │ + 14 │ ╭─▶ switch('invalid') { + 15 │ │ case true: + 16 │ │ expect(values).toStrictEqual(['foo']); + 17 │ ╰─▶ } + 18 │ }); + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:16] + 3 │ const foo = function(bar) { + 4 │ ╭─▶ if (bar) { + 5 │ │ return 1; + 6 │ │ } else { + 7 │ │ return 2; + 8 │ ╰─▶ } + 9 │ }; + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:16] + 3 │ function foo(bar) { + 4 │ ╭─▶ if (bar) { + 5 │ │ return 1; + 6 │ │ } else { + 7 │ │ return 2; + 8 │ ╰─▶ } + 9 │ }; + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ it('foo', () => { + 3 │ if ('bar') {} + · ───────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ it.skip('foo', () => { + 3 │ if ('bar') {} + · ───────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ it.skip('foo', function () { + 3 │ if ('bar') {} + · ───────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ it.only('foo', () => { + 3 │ if ('bar') {} + · ───────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ xit('foo', () => { + 3 │ if ('bar') {} + · ───────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ fit('foo', () => { + 3 │ if ('bar') {} + · ───────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ test('foo', () => { + 3 │ if ('bar') {} + · ───────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ test.skip('foo', () => { + 3 │ if ('bar') {} + · ───────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ test.only('foo', () => { + 3 │ if ('bar') {} + · ───────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ xtest('foo', () => { + 3 │ if ('bar') {} + · ───────────── + 4 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:16] + 3 │ it('bar', () => { + 4 │ if ('bar') {} + · ───────────── + 5 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:16] + 3 │ it('bar', () => { + 4 │ if ('bar') {} + · ───────────── + 5 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:7:16] + 6 │ it('baz', () => { + 7 │ if ('qux') {} + · ───────────── + 8 │ if ('quux') {} + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:8:16] + 7 │ if ('qux') {} + 8 │ if ('quux') {} + · ────────────── + 9 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:14] + 3 │ callExpression() + 4 │ if ('bar') {} + · ───────────── + 5 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:14] + 3 │ callExpression() + 4 │ if ('bar') {} + · ───────────── + 5 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:14] + 3 │ callExpression() + 4 │ if ('bar') {} + · ───────────── + 5 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:14] + 3 │ callExpression() + 4 │ if ('bar') {} + · ───────────── + 5 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:4:14] + 3 │ callExpression() + 4 │ if ('bar') {} + · ───────────── + 5 │ }) + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:6:20] + 5 │ const values = something.map((thing) => { + 6 │ ╭─▶ if (thing.isFoo) { + 7 │ │ return thing.foo + 8 │ │ } else { + 9 │ │ return thing.bar; + 10 │ ╰─▶ } + 11 │ }); + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:13:18] + 12 │ + 13 │ ╭─▶ if ('invalid') { + 14 │ │ expect(values).toStrictEqual(['foo']); + 15 │ ╰─▶ } + 16 │ }); + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:3:14] + 2 │ test("shows error", () => { + 3 │ ╭─▶ if (1 === 2) { + 4 │ │ expect(true).toBe(false); + 5 │ ╰─▶ } + 6 │ }); + ╰──── + help: Avoid having conditionals in tests. + + ⚠ eslint-plugin-vitest(no-conditional-in-test): Disallow conditional logic in tests + ╭─[no_conditional_in_test.tsx:10:14] + 9 │ setTimeout(() => console.log("noop")); + 10 │ ╭─▶ if (1 === 2) { + 11 │ │ expect(true).toBe(false); + 12 │ ╰─▶ } + 13 │ }); + ╰──── + help: Avoid having conditionals in tests. diff --git a/crates/oxc_linter/src/utils/mod.rs b/crates/oxc_linter/src/utils/mod.rs index 5a9586f78015b..485fc7d625f7c 100644 --- a/crates/oxc_linter/src/utils/mod.rs +++ b/crates/oxc_linter/src/utils/mod.rs @@ -23,6 +23,7 @@ pub fn is_jest_rule_adapted_to_vitest(rule_name: &str) -> bool { "expect-expect", "no-alias-methods", "no-conditional-expect", + "no-conditional-in-test", "no-commented-out-tests", "no-disabled-tests", "no-focused-tests",