mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(linter): support eslint-plugin-vitest/valid-describe-callback (#4185)
Rule detail: [link](https://github.com/veritem/eslint-plugin-vitest/blob/main/src/rules/valid-describe-callback.ts) --------- Co-authored-by: wenzhe <mysteryven@gmail.com>
This commit is contained in:
parent
aab7aaaa06
commit
126b66c4f8
3 changed files with 430 additions and 10 deletions
|
|
@ -10,15 +10,20 @@ use crate::{
|
|||
context::LintContext,
|
||||
rule::Rule,
|
||||
utils::{
|
||||
collect_possible_jest_call_node, parse_general_jest_fn_call, JestFnKind, JestGeneralFnKind,
|
||||
PossibleJestNode,
|
||||
collect_possible_jest_call_node, get_test_plugin_name, parse_general_jest_fn_call,
|
||||
JestFnKind, JestGeneralFnKind, PossibleJestNode, TestPluginName,
|
||||
},
|
||||
};
|
||||
|
||||
fn valid_describe_callback_diagnostic(x0: &str, x1: &str, span2: Span) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn(format!("eslint-plugin-jest(valid-describe-callback): {x0:?}"))
|
||||
.with_help(format!("{x1:?}"))
|
||||
.with_label(span2)
|
||||
fn valid_describe_callback_diagnostic(
|
||||
x0: TestPluginName,
|
||||
x1: &str,
|
||||
x2: &str,
|
||||
span3: Span,
|
||||
) -> OxcDiagnostic {
|
||||
OxcDiagnostic::warn(format!("{x0}(valid-describe-callback): {x1:?}"))
|
||||
.with_help(format!("{x2:?}"))
|
||||
.with_label(span3)
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
|
|
@ -58,6 +63,17 @@ declare_oxc_lint!(
|
|||
/// expect(myFunction()).toBeTruthy();
|
||||
/// }));
|
||||
/// ```
|
||||
///
|
||||
/// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/valid-describe-callback.md),
|
||||
/// to use it, add the following configuration to your `.eslintrc.json`:
|
||||
///
|
||||
/// ```json
|
||||
/// {
|
||||
/// "rules": {
|
||||
/// "vitest/valid-describe-callback": "error"
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
ValidDescribeCallback,
|
||||
correctness
|
||||
);
|
||||
|
|
@ -151,7 +167,8 @@ fn find_first_return_stmt_span(function_body: &FunctionBody) -> Option<Span> {
|
|||
|
||||
fn diagnostic(ctx: &LintContext, span: Span, message: Message) {
|
||||
let (error, help) = message.details();
|
||||
ctx.diagnostic(valid_describe_callback_diagnostic(error, help, span));
|
||||
let plugin_name = get_test_plugin_name(ctx);
|
||||
ctx.diagnostic(valid_describe_callback_diagnostic(plugin_name, error, help, span));
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
|
@ -192,7 +209,7 @@ impl Message {
|
|||
fn test() {
|
||||
use crate::tester::Tester;
|
||||
|
||||
let pass = vec![
|
||||
let mut pass = vec![
|
||||
("describe.each([1, 2, 3])('%s', (a, b) => {});", None),
|
||||
("describe('foo', function() {})", None),
|
||||
("describe('foo', () => {})", None),
|
||||
|
|
@ -235,7 +252,7 @@ fn test() {
|
|||
),
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
let mut fail = vec![
|
||||
("describe.each()()", None),
|
||||
("describe['each']()()", None),
|
||||
("describe.each(() => {})()", None),
|
||||
|
|
@ -331,5 +348,157 @@ fn test() {
|
|||
("describe('foo', async function (done) {})", None),
|
||||
];
|
||||
|
||||
Tester::new(ValidDescribeCallback::NAME, pass, fail).with_jest_plugin(true).test_and_snapshot();
|
||||
let pass_vitest = vec![
|
||||
("describe.each([1, 2, 3])(\"%s\", (a, b) => {});", None),
|
||||
("describe(\"foo\", function() {})", None),
|
||||
("describe(\"foo\", () => {})", None),
|
||||
("describe(`foo`, () => {})", None),
|
||||
("xdescribe(\"foo\", () => {})", None),
|
||||
("fdescribe(\"foo\", () => {})", None),
|
||||
("describe.only(\"foo\", () => {})", None),
|
||||
("describe.skip(\"foo\", () => {})", None),
|
||||
("describe.todo(\"runPrettierFormat\");", None),
|
||||
(
|
||||
"
|
||||
describe('foo', () => {
|
||||
it('bar', () => {
|
||||
return Promise.resolve(42).then(value => {
|
||||
expect(value).toBe(42)
|
||||
})
|
||||
})
|
||||
})
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
describe('foo', () => {
|
||||
it('bar', async () => {
|
||||
expect(await Promise.resolve(42)).toBe(42)
|
||||
})
|
||||
})
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
if (hasOwnProperty(obj, key)) {
|
||||
}
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
describe.each`
|
||||
foo | foe
|
||||
${1} | ${2}
|
||||
`('$something', ({ foo, foe }) => {});
|
||||
",
|
||||
None,
|
||||
),
|
||||
];
|
||||
|
||||
let fail_vitest = vec![
|
||||
("describe.each()()", None),
|
||||
("describe[\"each\"]()()", None),
|
||||
("describe.each(() => {})()", None),
|
||||
("describe.each(() => {})(\"foo\")", None),
|
||||
("describe.each()(() => {})", None),
|
||||
("describe[\"each\"]()(() => {})", None),
|
||||
("describe.each(\"foo\")(() => {})", None),
|
||||
("describe.only.each(\"foo\")(() => {})", None),
|
||||
("describe(() => {})", None),
|
||||
("describe(\"foo\")", None),
|
||||
("describe(\"foo\", \"foo2\")", None),
|
||||
("describe()", None),
|
||||
("describe(\"foo\", async () => {})", None),
|
||||
("describe(\"foo\", async function () {})", None),
|
||||
("xdescribe(\"foo\", async function () {})", None),
|
||||
("fdescribe(\"foo\", async function () {})", None),
|
||||
("describe.only(\"foo\", async function () {})", None),
|
||||
("describe.skip(\"foo\", async function () {})", None),
|
||||
(
|
||||
"
|
||||
describe('sample case', () => {
|
||||
it('works', () => {
|
||||
expect(true).toEqual(true);
|
||||
});
|
||||
describe('async', async () => {
|
||||
await new Promise(setImmediate);
|
||||
it('breaks', () => {
|
||||
throw new Error('Fail');
|
||||
});
|
||||
});
|
||||
});
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
describe('foo', function () {
|
||||
return Promise.resolve().then(() => {
|
||||
it('breaks', () => {
|
||||
throw new Error('Fail')
|
||||
})
|
||||
})
|
||||
})
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
describe('foo', () => {
|
||||
return Promise.resolve().then(() => {
|
||||
it('breaks', () => {
|
||||
throw new Error('Fail')
|
||||
})
|
||||
})
|
||||
describe('nested', () => {
|
||||
return Promise.resolve().then(() => {
|
||||
it('breaks', () => {
|
||||
throw new Error('Fail')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
describe('foo', async () => {
|
||||
await something()
|
||||
it('does something')
|
||||
describe('nested', () => {
|
||||
return Promise.resolve().then(() => {
|
||||
it('breaks', () => {
|
||||
throw new Error('Fail')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
",
|
||||
None,
|
||||
),
|
||||
(
|
||||
"
|
||||
describe('foo', () =>
|
||||
test('bar', () => {})
|
||||
)
|
||||
",
|
||||
None,
|
||||
),
|
||||
("describe(\"foo\", done => {})", None),
|
||||
("describe(\"foo\", function (done) {})", None),
|
||||
("describe(\"foo\", function (one, two, three) {})", None),
|
||||
("describe(\"foo\", async function (done) {})", None),
|
||||
];
|
||||
|
||||
pass.extend(pass_vitest);
|
||||
fail.extend(fail_vitest);
|
||||
|
||||
Tester::new(ValidDescribeCallback::NAME, pass, fail)
|
||||
.with_jest_plugin(true)
|
||||
.with_vitest_plugin(true)
|
||||
.test_and_snapshot();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
assertion_line: 216
|
||||
---
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:1]
|
||||
|
|
@ -256,3 +257,252 @@ source: crates/oxc_linter/src/tester.rs
|
|||
· ────────────────────────
|
||||
╰────
|
||||
help: "Remove argument(s) of describe callback"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:1]
|
||||
1 │ describe.each()()
|
||||
· ─────────────────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:1]
|
||||
1 │ describe["each"]()()
|
||||
· ────────────────────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:1]
|
||||
1 │ describe.each(() => {})()
|
||||
· ─────────────────────────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:25]
|
||||
1 │ describe.each(() => {})("foo")
|
||||
· ─────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:17]
|
||||
1 │ describe.each()(() => {})
|
||||
· ────────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:20]
|
||||
1 │ describe["each"]()(() => {})
|
||||
· ────────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:22]
|
||||
1 │ describe.each("foo")(() => {})
|
||||
· ────────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:27]
|
||||
1 │ describe.only.each("foo")(() => {})
|
||||
· ────────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:10]
|
||||
1 │ describe(() => {})
|
||||
· ────────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:10]
|
||||
1 │ describe("foo")
|
||||
· ─────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Second argument must be a function"
|
||||
╭─[valid_describe_callback.tsx:1:17]
|
||||
1 │ describe("foo", "foo2")
|
||||
· ──────
|
||||
╰────
|
||||
help: "Replace second argument with a function"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Describe requires name and callback arguments"
|
||||
╭─[valid_describe_callback.tsx:1:1]
|
||||
1 │ describe()
|
||||
· ──────────
|
||||
╰────
|
||||
help: "Add name as first argument and callback as second argument"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "No async describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:17]
|
||||
1 │ describe("foo", async () => {})
|
||||
· ──────────────
|
||||
╰────
|
||||
help: "Remove `async` keyword"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "No async describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:17]
|
||||
1 │ describe("foo", async function () {})
|
||||
· ────────────────────
|
||||
╰────
|
||||
help: "Remove `async` keyword"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "No async describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:18]
|
||||
1 │ xdescribe("foo", async function () {})
|
||||
· ────────────────────
|
||||
╰────
|
||||
help: "Remove `async` keyword"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "No async describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:18]
|
||||
1 │ fdescribe("foo", async function () {})
|
||||
· ────────────────────
|
||||
╰────
|
||||
help: "Remove `async` keyword"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "No async describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:22]
|
||||
1 │ describe.only("foo", async function () {})
|
||||
· ────────────────────
|
||||
╰────
|
||||
help: "Remove `async` keyword"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "No async describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:22]
|
||||
1 │ describe.skip("foo", async function () {})
|
||||
· ────────────────────
|
||||
╰────
|
||||
help: "Remove `async` keyword"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "No async describe callback"
|
||||
╭─[valid_describe_callback.tsx:6:39]
|
||||
5 │ });
|
||||
6 │ ╭─▶ describe('async', async () => {
|
||||
7 │ │ await new Promise(setImmediate);
|
||||
8 │ │ it('breaks', () => {
|
||||
9 │ │ throw new Error('Fail');
|
||||
10 │ │ });
|
||||
11 │ ╰─▶ });
|
||||
12 │ });
|
||||
╰────
|
||||
help: "Remove `async` keyword"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected return statement in describe callback"
|
||||
╭─[valid_describe_callback.tsx:3:21]
|
||||
2 │ describe('foo', function () {
|
||||
3 │ ╭─▶ return Promise.resolve().then(() => {
|
||||
4 │ │ it('breaks', () => {
|
||||
5 │ │ throw new Error('Fail')
|
||||
6 │ │ })
|
||||
7 │ ╰─▶ })
|
||||
8 │ })
|
||||
╰────
|
||||
help: "Remove return statement in your describe callback"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected return statement in describe callback"
|
||||
╭─[valid_describe_callback.tsx:9:25]
|
||||
8 │ describe('nested', () => {
|
||||
9 │ ╭─▶ return Promise.resolve().then(() => {
|
||||
10 │ │ it('breaks', () => {
|
||||
11 │ │ throw new Error('Fail')
|
||||
12 │ │ })
|
||||
13 │ ╰─▶ })
|
||||
14 │ })
|
||||
╰────
|
||||
help: "Remove return statement in your describe callback"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected return statement in describe callback"
|
||||
╭─[valid_describe_callback.tsx:3:21]
|
||||
2 │ describe('foo', () => {
|
||||
3 │ ╭─▶ return Promise.resolve().then(() => {
|
||||
4 │ │ it('breaks', () => {
|
||||
5 │ │ throw new Error('Fail')
|
||||
6 │ │ })
|
||||
7 │ ╰─▶ })
|
||||
8 │ describe('nested', () => {
|
||||
╰────
|
||||
help: "Remove return statement in your describe callback"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected return statement in describe callback"
|
||||
╭─[valid_describe_callback.tsx:6:25]
|
||||
5 │ describe('nested', () => {
|
||||
6 │ ╭─▶ return Promise.resolve().then(() => {
|
||||
7 │ │ it('breaks', () => {
|
||||
8 │ │ throw new Error('Fail')
|
||||
9 │ │ })
|
||||
10 │ ╰─▶ })
|
||||
11 │ })
|
||||
╰────
|
||||
help: "Remove return statement in your describe callback"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "No async describe callback"
|
||||
╭─[valid_describe_callback.tsx:2:33]
|
||||
1 │
|
||||
2 │ ╭─▶ describe('foo', async () => {
|
||||
3 │ │ await something()
|
||||
4 │ │ it('does something')
|
||||
5 │ │ describe('nested', () => {
|
||||
6 │ │ return Promise.resolve().then(() => {
|
||||
7 │ │ it('breaks', () => {
|
||||
8 │ │ throw new Error('Fail')
|
||||
9 │ │ })
|
||||
10 │ │ })
|
||||
11 │ │ })
|
||||
12 │ ╰─▶ })
|
||||
13 │
|
||||
╰────
|
||||
help: "Remove `async` keyword"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected return statement in describe callback"
|
||||
╭─[valid_describe_callback.tsx:3:21]
|
||||
2 │ describe('foo', () =>
|
||||
3 │ test('bar', () => {})
|
||||
· ─────────────────────
|
||||
4 │ )
|
||||
╰────
|
||||
help: "Remove return statement in your describe callback"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected argument(s) in describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:17]
|
||||
1 │ describe("foo", done => {})
|
||||
· ──────────
|
||||
╰────
|
||||
help: "Remove argument(s) of describe callback"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected argument(s) in describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:17]
|
||||
1 │ describe("foo", function (done) {})
|
||||
· ──────────────────
|
||||
╰────
|
||||
help: "Remove argument(s) of describe callback"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected argument(s) in describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:17]
|
||||
1 │ describe("foo", function (one, two, three) {})
|
||||
· ─────────────────────────────
|
||||
╰────
|
||||
help: "Remove argument(s) of describe callback"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "No async describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:17]
|
||||
1 │ describe("foo", async function (done) {})
|
||||
· ────────────────────────
|
||||
╰────
|
||||
help: "Remove `async` keyword"
|
||||
|
||||
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected argument(s) in describe callback"
|
||||
╭─[valid_describe_callback.tsx:1:17]
|
||||
1 │ describe("foo", async function (done) {})
|
||||
· ────────────────────────
|
||||
╰────
|
||||
help: "Remove argument(s) of describe callback"
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ pub fn is_jest_rule_adapted_to_vitest(rule_name: &str) -> bool {
|
|||
"no-focused-tests",
|
||||
"no-test-prefixes",
|
||||
"prefer-hooks-in-order",
|
||||
"valid-describe-callback",
|
||||
"valid-expect",
|
||||
];
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue