mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 12:51:57 +00:00
feat(linter): add no-commented-out-tests (#723)
port
[no-commented-out-tests](e894f51a0d/docs/rules/no-commented-out-tests.md)
This commit is contained in:
parent
ec85fd8b7d
commit
3022655965
3 changed files with 347 additions and 0 deletions
|
|
@ -91,6 +91,7 @@ mod typescript {
|
|||
}
|
||||
|
||||
mod jest {
|
||||
pub mod no_commented_out_tests;
|
||||
pub mod no_disabled_tests;
|
||||
pub mod no_focused_tests;
|
||||
pub mod no_test_prefixes;
|
||||
|
|
@ -178,4 +179,5 @@ oxc_macros::declare_all_lint_rules! {
|
|||
jest::no_test_prefixes,
|
||||
jest::no_focused_tests,
|
||||
jest::valid_describe_callback,
|
||||
jest::no_commented_out_tests,
|
||||
}
|
||||
|
|
|
|||
175
crates/oxc_linter/src/rules/jest/no_commented_out_tests.rs
Normal file
175
crates/oxc_linter/src/rules/jest/no_commented_out_tests.rs
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
use oxc_diagnostics::{
|
||||
miette::{self, Diagnostic},
|
||||
thiserror::Error,
|
||||
};
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("Some tests seem to be commented")]
|
||||
#[diagnostic(severity(warning), help("Remove or uncomment this comment"))]
|
||||
struct NoCommentedOutTestsDiagnostic(#[label] pub Span);
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct NoCommentedOutTests;
|
||||
|
||||
declare_oxc_lint!(
|
||||
/// ### What it does
|
||||
///
|
||||
/// This rule raises a warning about commented out tests. It's similar to
|
||||
/// no-disabled-tests rule.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
///
|
||||
/// You may forget to uncomment some tests. This rule raises a warning about commented out tests. It's similar to
|
||||
/// no-disabled-tests rule.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```javascript
|
||||
/// // describe('foo', () => {});
|
||||
/// // it('foo', () => {});
|
||||
/// // test('foo', () => {});
|
||||
///
|
||||
/// // describe.skip('foo', () => {});
|
||||
/// // it.skip('foo', () => {});
|
||||
/// // test.skip('foo', () => {});
|
||||
/// ```
|
||||
NoCommentedOutTests,
|
||||
suspicious
|
||||
);
|
||||
|
||||
impl Rule for NoCommentedOutTests {
|
||||
fn run_once(&self, ctx: &LintContext) {
|
||||
let comments = ctx.semantic().trivias().comments();
|
||||
let source_text = ctx.semantic().source_text();
|
||||
// /^\s*[xf]?(test|it|describe)(\.\w+|\[['"]\w+['"]\])?\s*\(/mu
|
||||
let re =
|
||||
Regex::new(r#"(?mu)^\s*[xf]?(test|it|describe)(\.\w+|\[['"]\w+['"]\])?\s*\("#).unwrap();
|
||||
let commented_tests = comments.iter().filter_map(|(start, comment)| {
|
||||
let start = *start;
|
||||
let end = comment.end();
|
||||
let text = &source_text[(start as usize)..(end as usize)];
|
||||
if re.is_match(text) {
|
||||
Some(Span::new(start, end))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
for span in commented_tests {
|
||||
ctx.diagnostic(NoCommentedOutTestsDiagnostic(span));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
use crate::tester::Tester;
|
||||
|
||||
let pass = vec![
|
||||
("// foo('bar', function () {})", None),
|
||||
("describe('foo', function () {})", None),
|
||||
("it('foo', function () {})", None),
|
||||
("describe.only('foo', function () {})", None),
|
||||
("it.only('foo', function () {})", None),
|
||||
("it.concurrent('foo', function () {})", None),
|
||||
("test('foo', function () {})", None),
|
||||
("test.only('foo', function () {})", None),
|
||||
("test.concurrent('foo', function () {})", None),
|
||||
("var appliedSkip = describe.skip; appliedSkip.apply(describe)", None),
|
||||
("var calledSkip = it.skip; calledSkip.call(it)", None),
|
||||
("({ f: function () {} }).f()", None),
|
||||
("(a || b).f()", None),
|
||||
("itHappensToStartWithIt()", None),
|
||||
("testSomething()", None),
|
||||
("// latest(dates)", None),
|
||||
("// TODO: unify with Git implementation from Shipit (?)", None),
|
||||
("#!/usr/bin/env node", None),
|
||||
(
|
||||
r#"
|
||||
import { pending } from "actions"
|
||||
test("foo", () => { expect(pending()).toEqual({}) })
|
||||
"#,
|
||||
None,
|
||||
),
|
||||
(
|
||||
r#"
|
||||
const { pending } = require("actions")
|
||||
test("foo", () => { expect(pending()).toEqual({}) })
|
||||
"#,
|
||||
None,
|
||||
),
|
||||
(
|
||||
r#"
|
||||
test("foo", () => {
|
||||
const pending = getPending()
|
||||
expect(pending()).toEqual({})
|
||||
})
|
||||
"#,
|
||||
None,
|
||||
),
|
||||
(
|
||||
r#"
|
||||
test("foo", () => { expect(pending()).toEqual({}) })
|
||||
function pending() { return {} }
|
||||
"#,
|
||||
None,
|
||||
),
|
||||
];
|
||||
|
||||
let fail = vec {})", None),
|
||||
("// describe['skip']('foo', function () {})", None),
|
||||
("// it.skip('foo', function () {})", None),
|
||||
("// it.only('foo', function () {})", None),
|
||||
("// it.concurrent('foo', function () {})", None),
|
||||
("// it['skip']('foo', function () {})", None),
|
||||
("// test.skip('foo', function () {})", None),
|
||||
("// test.concurrent('foo', function () {})", None),
|
||||
("// test['skip']('foo', function () {})", None),
|
||||
("// xdescribe('foo', function () {})", None),
|
||||
("// xit('foo', function () {})", None),
|
||||
("// fit('foo', function () {})", None),
|
||||
("// xtest('foo', function () {})", None),
|
||||
(
|
||||
r#"
|
||||
// test(
|
||||
// "foo", function () {}
|
||||
// )
|
||||
"#,
|
||||
None,
|
||||
),
|
||||
(
|
||||
r#"
|
||||
/* test
|
||||
(
|
||||
"foo", function () {}
|
||||
)
|
||||
*/
|
||||
"#,
|
||||
None,
|
||||
),
|
||||
("// it('has title but no callback')", None),
|
||||
("// it()", None),
|
||||
("// test.someNewMethodThatMightBeAddedInTheFuture()", None),
|
||||
("// test['someNewMethodThatMightBeAddedInTheFuture']()", None),
|
||||
("// test('has title but no callback')", None),
|
||||
(
|
||||
r#"
|
||||
foo()
|
||||
/*
|
||||
describe('has title but no callback', () => {})
|
||||
*/
|
||||
bar()
|
||||
"#,
|
||||
None,
|
||||
),
|
||||
];
|
||||
|
||||
Tester::new(NoCommentedOutTests::NAME, pass, fail).test_and_snapshot();
|
||||
}
|
||||
170
crates/oxc_linter/src/snapshots/no_commented_out_tests.snap
Normal file
170
crates/oxc_linter/src/snapshots/no_commented_out_tests.snap
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
expression: no_commented_out_tests
|
||||
---
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // fdescribe('foo', function () {})
|
||||
· ─────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // describe['skip']('foo', function () {})
|
||||
· ────────────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // describe['skip']('foo', function () {})
|
||||
· ────────────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // it.skip('foo', function () {})
|
||||
· ───────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // it.only('foo', function () {})
|
||||
· ───────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // it.concurrent('foo', function () {})
|
||||
· ─────────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // it['skip']('foo', function () {})
|
||||
· ──────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // test.skip('foo', function () {})
|
||||
· ─────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // test.concurrent('foo', function () {})
|
||||
· ───────────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // test['skip']('foo', function () {})
|
||||
· ────────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // xdescribe('foo', function () {})
|
||||
· ─────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // xit('foo', function () {})
|
||||
· ───────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // fit('foo', function () {})
|
||||
· ───────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // xtest('foo', function () {})
|
||||
· ─────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │
|
||||
2 │ // test(
|
||||
· ───────
|
||||
3 │ // "foo", function () {}
|
||||
4 │ // )
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │
|
||||
2 │ ╭─▶ /* test
|
||||
3 │ │ (
|
||||
4 │ │ "foo", function () {}
|
||||
5 │ │ )
|
||||
6 │ ╰─▶ */
|
||||
7 │
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // it('has title but no callback')
|
||||
· ────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // it()
|
||||
· ─────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // test.someNewMethodThatMightBeAddedInTheFuture()
|
||||
· ────────────────────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // test['someNewMethodThatMightBeAddedInTheFuture']()
|
||||
· ───────────────────────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:1:1]
|
||||
1 │ // test('has title but no callback')
|
||||
· ──────────────────────────────────
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
⚠ Some tests seem to be commented
|
||||
╭─[no_commented_out_tests.tsx:2:1]
|
||||
2 │ foo()
|
||||
3 │ ╭─▶ /*
|
||||
4 │ │ describe('has title but no callback', () => {})
|
||||
5 │ ╰─▶ */
|
||||
6 │ bar()
|
||||
╰────
|
||||
help: Remove or uncomment this comment
|
||||
|
||||
|
||||
Loading…
Reference in a new issue