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:
Wenzhe Wang 2023-08-16 12:23:46 +08:00 committed by GitHub
parent ec85fd8b7d
commit 3022655965
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 347 additions and 0 deletions

View file

@ -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,
}

View 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![
("// fdescribe('foo', function () {})", None),
("// describe['skip']('foo', function () {})", 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();
}

View 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