Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(linter): eslint-plugin-vitest/require-local-test-context-for-concurrent-snapshots #4578

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions crates/oxc_linter/src/frameworks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ impl FrameworkFlags {
pub const fn is_vitest(self) -> bool {
self.contains(Self::Vitest)
}

#[inline]
pub const fn is_jest(self) -> bool {
self.contains(Self::Jest)
}
}

/// <https://jestjs.io/docs/configuration#testmatch-arraystring>
Expand All @@ -83,3 +88,7 @@ pub(crate) fn is_jestlike_file(path: &Path) -> bool {
pub(crate) fn has_vitest_imports(module_record: &ModuleRecord) -> bool {
module_record.import_entries.iter().any(|entry| entry.module_request.name() == "vitest")
}

pub(crate) fn has_jest_imports(module_record: &ModuleRecord) -> bool {
module_record.import_entries.iter().any(|entry| entry.module_request.name() == "@jest/globals")
}
10 changes: 6 additions & 4 deletions crates/oxc_linter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,13 @@ impl Linter {
if self.options.jest_plugin || self.options.vitest_plugin {
let mut test_flags = FrameworkFlags::empty();

if frameworks::is_jestlike_file(path) {
test_flags.set(FrameworkFlags::Jest, self.options.jest_plugin);
test_flags.set(FrameworkFlags::Vitest, self.options.vitest_plugin);
} else if frameworks::has_vitest_imports(ctx.module_record()) {
if frameworks::has_vitest_imports(ctx.module_record()) {
test_flags.set(FrameworkFlags::Vitest, true);
} else if frameworks::is_jestlike_file(path)
|| frameworks::has_jest_imports(ctx.module_record())
{
test_flags.set(FrameworkFlags::Jest, self.options.jest_plugin);
// test_flags.set(FrameworkFlags::Vitest, self.options.vitest_plugin);
}

ctx = ctx.and_frameworks(test_flags);
Expand Down
2 changes: 2 additions & 0 deletions crates/oxc_linter/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ mod vitest {
pub mod no_import_node_test;
pub mod prefer_to_be_falsy;
pub mod prefer_to_be_truthy;
pub mod require_local_test_context_for_concurrent_snapshots;
}

oxc_macros::declare_all_lint_rules! {
Expand Down Expand Up @@ -860,4 +861,5 @@ oxc_macros::declare_all_lint_rules! {
vitest::no_import_node_test,
vitest::prefer_to_be_falsy,
vitest::prefer_to_be_truthy,
vitest::require_local_test_context_for_concurrent_snapshots,
}
14 changes: 10 additions & 4 deletions crates/oxc_linter/src/rules/jest/no_disabled_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ fn test() {
"#,
"
import { test } from './test-utils';
test('something');
test('something');
",
];

Expand All @@ -262,10 +262,16 @@ fn test() {
r#"xit.each([])("foo", function () {})"#,
r#"it("has title but no callback")"#,
r#"test("has title but no callback")"#,
r#"it("contains a call to pending", function () { pending() })"#,
"pending();",
r#"
import { describe } from 'vitest';
import { it } from 'vitest';
it("contains a call to pending", function () { pending() })
"#,
"
import { it } from 'vitest';
pending();
",
r#"
import { describe } from 'vitest';
describe.skip("foo", function () {})
"#,
];
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/jest/no_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ fn test() {
),
("window.location = 'valid'", None, None, None),
("module.somethingElse = 'foo';", None, None, None),
("export const myThing = 'valid'", None, None, None),
("export default function () {}", None, None, None),
("export const myThing = 'valid'", None, None, Some(PathBuf::from("foo.js"))),
("export default function () {}", None, None, Some(PathBuf::from("foo.js"))),
("module.exports = function(){}", None, None, None),
("module.exports.myThing = 'valid';", None, None, None),
];
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/jest/require_hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ fn tests() {
setup();

it('is false', () => {
expect(true).toBe(false);
expect(true).toBe(false);
});
});
});
Expand Down Expand Up @@ -622,5 +622,5 @@ fn tests() {
),
];

Tester::new(RequireHook::NAME, pass, fail).test_and_snapshot();
Tester::new(RequireHook::NAME, pass, fail).with_jest_plugin(true).test_and_snapshot();
}
26 changes: 23 additions & 3 deletions crates/oxc_linter/src/rules/jest/valid_describe_callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,26 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>)
return;
}

if call_expr.arguments.len() == 0 {
let arg_len = call_expr.arguments.len();

// Handle describe.todo("runPrettierFormat")
if ctx.frameworks().is_vitest() && arg_len == 1 {
if let Some(member_expr) = call_expr.callee.as_member_expression() {
let Some(property_name) = member_expr.static_property_name() else {
return;
};
if property_name == "todo" {
return;
}
}
}

if arg_len == 0 {
diagnostic(ctx, call_expr.span, Message::NameAndCallback);
return;
}

if call_expr.arguments.len() == 1 {
if arg_len == 1 {
// For better error notice, we locate it to arguments[0]
diagnostic(ctx, call_expr.arguments[0].span(), Message::NameAndCallback);
return;
Expand Down Expand Up @@ -353,7 +367,13 @@ fn test() {
("fdescribe(\"foo\", () => {})", None),
("describe.only(\"foo\", () => {})", None),
("describe.skip(\"foo\", () => {})", None),
("describe.todo(\"runPrettierFormat\");", None),
(
"
import { describe } from 'vitest';
describe.todo(\"runPrettierFormat\");
",
None,
),
(
"
describe('foo', () => {
Expand Down
Loading