Skip to content

Commit

Permalink
feat(linter): detect jest file by default glob pattern (#2408)
Browse files Browse the repository at this point in the history
closes: #2397
  • Loading branch information
mysteryven committed Feb 13, 2024
1 parent b5deb9a commit d9f073e
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 19 deletions.
42 changes: 33 additions & 9 deletions crates/oxc_linter/src/rules/jest/no_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,30 @@ impl Rule for NoExport {
#[test]
fn test() {
use crate::tester::Tester;
use std::path::PathBuf;

let pass = vec![
("describe('a test', () => { expect(1).toBe(1); })", None),
("window.location = 'valid'", None),
("module.somethingElse = 'foo';", None),
("export const myThing = 'valid'", None),
("export default function () {}", None),
("module.exports = function(){}", None),
("module.exports.myThing = 'valid';", None),
(
"describe('a test', () => { expect(1).toBe(1); })",
None,
None,
Some(PathBuf::from("foo.test.js")),
),
("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),
("module.exports = function(){}", None, None, None),
("module.exports.myThing = 'valid';", None, None, None),
];

let fail = vec![
("export const myThing = 'invalid'; test('a test', () => { expect(1).toBe(1);});", None),
(
"export const myThing = 'invalid'; test('a test', () => { expect(1).toBe(1);});",
None,
None,
Some(PathBuf::from("foo.test.js")),
),
(
"
export const myThing = 'invalid';
Expand All @@ -79,6 +90,8 @@ fn test() {
});
",
None,
None,
Some(PathBuf::from("foo.test.js")),
),
(
"
Expand All @@ -89,6 +102,8 @@ fn test() {
});
",
None,
None,
Some(PathBuf::from("foo.test.js")),
),
(
"
Expand All @@ -98,8 +113,15 @@ fn test() {
});
",
None,
None,
Some(PathBuf::from("foo.test.js")),
),
(
"export default function() {}; test('a test', () => { expect(1).toBe(1);});",
None,
None,
Some(PathBuf::from("foo.test.js")),
),
("export default function() {}; test('a test', () => { expect(1).toBe(1);});", None),
(
"
const foo = 1;
Expand All @@ -109,6 +131,8 @@ fn test() {
export {foo, bar};
",
None,
None,
Some(PathBuf::from("foo.test.js")),
),
// TODO: support `module.exports`
// ("module.exports['invalid'] = function() {}; test('a test', () => { expect(1).toBe(1);});", None),
Expand Down
51 changes: 41 additions & 10 deletions crates/oxc_linter/src/utils/jest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,19 @@ pub enum JestGeneralFnKind {
Jest,
}

/// <https://jestjs.io/docs/configuration#testmatch-arraystring>
pub fn is_jest_file(ctx: &LintContext) -> bool {
if JEST_METHOD_NAMES
.iter()
.any(|name| ctx.scopes().root_unresolved_references().contains_key(*name))
{
if ctx.file_path().components().any(|c| match c {
std::path::Component::Normal(p) => p == std::ffi::OsStr::new("__tests__"),
_ => false,
}) {
return true;
};

let import_entries = &ctx.semantic().module_record().import_entries;
}

return import_entries.iter().any(|import_entry| {
matches!(import_entry.module_request.name().as_str(), "@jest/globals")
});
let file_path = ctx.file_path().to_string_lossy();
["spec.js", "spec.jsx", "spec.ts", "spec.tsx", "test.js", "test.jsx", "test.ts", "test.tsx"]
.iter()
.any(|ext| file_path.ends_with(ext))
}

pub fn is_type_of_jest_fn_call<'a>(
Expand Down Expand Up @@ -286,3 +286,34 @@ pub fn get_node_name_vec<'a>(expr: &'a Expression<'a>) -> Vec<Cow<'a, str>> {
fn is_pure_string(template_literal: &TemplateLiteral) -> bool {
template_literal.expressions.is_empty() && template_literal.quasis.len() == 1
}
#[cfg(test)]
mod test {
use crate::LintContext;
use oxc_allocator::Allocator;
use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder;
use oxc_span::SourceType;
use std::{path::Path, rc::Rc};

#[test]
fn test_is_jest_file() {
let allocator = Allocator::default();
let source_type = SourceType::default();
let parser_ret = Parser::new(&allocator, "", source_type).parse();
let program = allocator.alloc(parser_ret.program);
let semantic_ret = SemanticBuilder::new("", source_type).build(program).semantic;
let semantic_ret = Rc::new(semantic_ret);

let path = Path::new("foo.js");
let ctx = LintContext::new(Box::from(path), &semantic_ret);
assert!(!super::is_jest_file(&ctx));

let path = Path::new("foo.test.js");
let ctx = LintContext::new(Box::from(path), &semantic_ret);
assert!(super::is_jest_file(&ctx));

let path = Path::new("__tests__/foo/test.spec.js");
let ctx = LintContext::new(Box::from(path), &semantic_ret);
assert!(super::is_jest_file(&ctx));
}
}

0 comments on commit d9f073e

Please sign in to comment.