From 8e71356f3971d56cca00753999d18f33b91045f4 Mon Sep 17 00:00:00 2001 From: eryue0220 Date: Mon, 27 May 2024 22:14:01 +0800 Subject: [PATCH 1/6] feat: add rule --- crates/oxc_linter/src/rules.rs | 2 + .../src/rules/jest/no_large_snapshots.rs | 554 +++++++++++++++ .../src/snapshots/no_large_snapshots.snap | 659 ++++++++++++++++++ crates/oxc_span/src/source_type.rs | 5 +- 4 files changed, 1218 insertions(+), 2 deletions(-) create mode 100644 crates/oxc_linter/src/rules/jest/no_large_snapshots.rs create mode 100644 crates/oxc_linter/src/snapshots/no_large_snapshots.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 8b1d0f0d75636..62a9e6ab39a24 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -155,6 +155,7 @@ mod jest { pub mod no_identical_title; pub mod no_interpolation_in_snapshots; pub mod no_jasmine_globals; + pub mod no_large_snapshots; pub mod no_mocks_import; pub mod no_restricted_jest_methods; pub mod no_restricted_matchers; @@ -514,6 +515,7 @@ oxc_macros::declare_all_lint_rules! { jest::no_identical_title, jest::no_interpolation_in_snapshots, jest::no_jasmine_globals, + jest::no_large_snapshots, jest::no_mocks_import, jest::no_restricted_jest_methods, jest::no_restricted_matchers, diff --git a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs new file mode 100644 index 0000000000000..875d29f13d152 --- /dev/null +++ b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs @@ -0,0 +1,554 @@ +use oxc_ast::{ + ast::{Expression, ExpressionStatement, MemberExpression}, + AstKind, +}; +use oxc_diagnostics::OxcDiagnostic; +use oxc_macros::declare_oxc_lint; +use oxc_span::Span; +use regex::Regex; +use rustc_hash::{FxHashMap, FxHasher}; +use std::{collections::HashMap, hash::BuildHasherDefault, ops::Deref, path::Path}; + +use crate::{ + context::LintContext, + rule::Rule, + utils::{collect_possible_jest_call_node, parse_expect_jest_fn_call, PossibleJestNode}, +}; + +fn no_snapshot(x0: usize, span0: Span) -> OxcDiagnostic { + OxcDiagnostic::warn("eslint-plugin-jest(no-large-snapshots): Disallow large snapshots.") + .with_help(format!("`{x0:?}`s should begin with lowercase")) + .with_labels([span0.into()]) +} + +fn too_long_snapshots(x0: usize, x1: usize, span0: Span) -> OxcDiagnostic { + OxcDiagnostic::warn("eslint-plugin-jest(no-large-snapshots): Disallow large snapshots.") + .with_help(format!( + "Expected Jest snapshot to be smaller than {x0:?} lines but was {x1:?} lines long" + )) + .with_labels([span0.into()]) +} + +#[derive(Debug, Default, Clone)] +pub struct NoLargeSnapshots(Box); + +#[derive(Debug, Default, Clone)] +pub struct NoLargeSnapshotsConfig { + pub max_size: usize, + pub inline_max_size: usize, + pub allowed_snapshots: FxHashMap>, +} + +impl Deref for NoLargeSnapshots { + type Target = NoLargeSnapshotsConfig; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +declare_oxc_lint!( + /// ### What it does + /// + /// When using Jest's snapshot capability one should be mindful of the size of + /// created snapshots. As a general best practice snapshots should be limited in + /// size in order to be more manageable and reviewable. A stored snapshot is only as + /// good as its review and as such keeping it short, sweet, and readable is + /// important to allow for thorough reviews. + /// + /// ### Example + /// + /// ```javascript + /// + /// // invalid + /// exports[`a large snapshot 1`] = ` + /// line 1 + /// line 2 + /// line 3 + /// line 4 + /// line 5 + /// line 6 + /// line 7 + /// line 8 + /// line 9 + /// line 10 + /// line 11 + /// line 12 + /// line 13 + /// line 14 + /// line 15 + /// line 16 + /// line 17 + /// line 18 + /// line 19 + /// line 20 + /// line 21 + /// line 22 + /// line 23 + /// line 24 + /// line 25 + /// line 26 + /// line 27 + /// line 28 + /// line 29 + /// line 30 + /// line 31 + /// line 32 + /// line 33 + /// line 34 + /// line 35 + /// line 36 + /// line 37 + /// line 38 + /// line 39 + /// line 40 + /// line 41 + /// line 42 + /// line 43 + /// line 44 + /// line 45 + /// line 46 + /// line 47 + /// line 48 + /// line 49 + /// line 50 + /// line 51 + /// `; + /// + /// // valid + /// exports[`a more manageable and readable snapshot 1`] = ` + /// line 1 + /// line 2 + /// line 3 + /// line 4 + /// `; + /// ``` + /// + NoLargeSnapshots, + style, +); + +impl Rule for NoLargeSnapshots { + fn from_configuration(value: serde_json::Value) -> Self { + let config = value.get(0); + + let max_size = config + .and_then(|c| c.get("maxSize")) + .and_then(serde_json::Value::as_number) + .and_then(serde_json::Number::as_u64) + .map_or(50, |v| usize::try_from(v).unwrap_or(50)); + + let inline_max_size = config + .and_then(|c| c.get("inlineMaxSize")) + .and_then(serde_json::Value::as_number) + .and_then(serde_json::Number::as_u64) + .map_or(max_size, |v| usize::try_from(v).unwrap_or(max_size)); + + let allowed_snapshots = config + .and_then(|c| c.get("allowedSnapshots")) + .and_then(serde_json::Value::as_object) + .and_then(Self::compile_allowed_snapshots) + .unwrap_or_default(); + + Self(Box::new(NoLargeSnapshotsConfig { max_size, inline_max_size, allowed_snapshots })) + } + + fn run_once(&self, ctx: &LintContext) { + let is_snap = ctx.file_path().to_str().map_or(false, |p| { + Path::new(p).extension().map_or(false, |ext| ext.eq_ignore_ascii_case("snap")) + }); + + if is_snap { + for node in ctx.nodes().iter().collect::>() { + if let AstKind::ExpressionStatement(expr_stmt) = node.kind() { + self.report_in_expr_stmt(expr_stmt, ctx); + } + } + } else { + for possible_jest_node in &collect_possible_jest_call_node(ctx) { + self.run(possible_jest_node, ctx); + } + } + } +} + +impl NoLargeSnapshots { + fn run<'a>(&self, possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) { + let node = possible_jest_node.node; + let AstKind::CallExpression(call_expr) = node.kind() else { + return; + }; + let Some(jest_fn_call) = parse_expect_jest_fn_call(call_expr, possible_jest_node, ctx) + else { + return; + }; + + if jest_fn_call.args.len() > 0 + && jest_fn_call.members.iter().any(|member| { + member.is_name_equal("toMatchInlineSnapshot") + || member.is_name_equal("toThrowErrorMatchingInlineSnapshot") + }) + { + let Some(first_arg) = jest_fn_call.args.first() else { + return; + }; + let Some(first_arg_expr) = first_arg.as_expression() else { + return; + }; + + let span = Self::get_span_from_expression(first_arg_expr); + self.report_in_span(span, ctx); + } + } + + fn report_in_expr_stmt(&self, expr_stmt: &ExpressionStatement, ctx: &LintContext) { + self.check_all_paths_are_absolute(); + + let line_count = Self::get_line_count(expr_stmt.span, ctx); + let allowed = match &expr_stmt.expression { + Expression::AssignmentExpression(assignment_expr) => { + let Some(member_expr) = assignment_expr.left.as_member_expression() else { + return; + }; + self.check_allowed_in_snapshots(member_expr, ctx) + } + Expression::BinaryExpression(binary_expr) => { + let Some(member_expr) = binary_expr.left.as_member_expression() else { + return; + }; + self.check_allowed_in_snapshots(member_expr, ctx) + } + Expression::LogicalExpression(logical_expr) => { + let Some(member_expr) = logical_expr.left.as_member_expression() else { + return; + }; + self.check_allowed_in_snapshots(member_expr, ctx) + } + _ => false, + }; + + if !allowed && line_count > self.max_size { + if line_count == 0 { + ctx.diagnostic(no_snapshot(line_count, expr_stmt.span)); + } else { + ctx.diagnostic(too_long_snapshots(self.max_size, line_count, expr_stmt.span)); + } + } + } + + fn report_in_span(&self, span: Span, ctx: &LintContext) { + self.check_all_paths_are_absolute(); + + let line_count = Self::get_line_count(span, ctx); + + if line_count > self.inline_max_size { + if self.inline_max_size == 0 { + ctx.diagnostic(no_snapshot(line_count, span)); + } else { + ctx.diagnostic(too_long_snapshots(self.inline_max_size, line_count, span)); + } + } + } + + fn check_allowed_in_snapshots( + &self, + member_expr: &MemberExpression, + ctx: &LintContext, + ) -> bool { + let Some(snapshot_name) = member_expr.static_property_name() else { + return false; + }; + let Some(file_name) = ctx.file_path().to_str() else { + return false; + }; + + let Some(allowed_snapshots_in_file) = self.allowed_snapshots.get(file_name) else { + return false; + }; + + allowed_snapshots_in_file.iter().any(|allowed_snapshot| { + match Regex::new(allowed_snapshot) { + Ok(regex) => regex.is_match(snapshot_name), + Err(_) => snapshot_name == allowed_snapshot, + } + }) + } + + fn check_all_paths_are_absolute(&self) { + let all_paths_are_absolute = + self.allowed_snapshots.keys().all(|p| Path::new(p).is_absolute()); + + assert!(all_paths_are_absolute, + "All paths for allowedSnapshots must be absolute. You can use JS config and `path.resolve`", + ); + } + + fn get_line_count(span: Span, ctx: &LintContext) -> usize { + let start = span.start as usize; + let start = if start == 0 { 1 } else { start }; + let end = span.end as usize; + let start = ctx.source_text()[..start].lines().count(); + let end = ctx.source_text()[start..end].lines().count(); + + end - start + } + + fn get_span_from_expression(expr: &Expression) -> Span { + match expr { + Expression::BooleanLiteral(bool_literal) => bool_literal.span, + Expression::NullLiteral(null_literal) => null_literal.span, + Expression::NumericLiteral(numeric_literal) => numeric_literal.span, + Expression::BigintLiteral(bigint_literal) => bigint_literal.span, + Expression::RegExpLiteral(regexp_literal) => regexp_literal.span, + Expression::StringLiteral(string_literal) => string_literal.span, + Expression::TemplateLiteral(template_literal) => template_literal.span, + + Expression::Identifier(ident) => ident.span, + + Expression::MetaProperty(meta_property) => meta_property.span, + Expression::Super(super_expr) => super_expr.span, + + Expression::ArrayExpression(array_expr) => array_expr.span, + Expression::ArrowFunctionExpression(arrow_func_expr) => arrow_func_expr.span, + Expression::AssignmentExpression(assignment_expr) => assignment_expr.span, + Expression::AwaitExpression(await_expr) => await_expr.span, + Expression::BinaryExpression(binary_expr) => binary_expr.span, + Expression::CallExpression(call_expr) => call_expr.span, + Expression::ChainExpression(chain_expr) => chain_expr.span, + Expression::ClassExpression(class_expr) => class_expr.span, + Expression::ConditionalExpression(conditional_expr) => conditional_expr.span, + Expression::FunctionExpression(func_expr) => func_expr.span, + Expression::ImportExpression(import_expr) => import_expr.span, + Expression::LogicalExpression(logical_expr) => logical_expr.span, + Expression::NewExpression(new_expr) => new_expr.span, + Expression::ObjectExpression(object_expr) => object_expr.span, + Expression::ParenthesizedExpression(parenthesized_expr) => parenthesized_expr.span, + Expression::SequenceExpression(sequence_expr) => sequence_expr.span, + Expression::TaggedTemplateExpression(tagged_temp_expr) => tagged_temp_expr.span, + Expression::ThisExpression(this_expr) => this_expr.span, + Expression::UnaryExpression(unary_expr) => unary_expr.span, + Expression::UpdateExpression(update_expr) => update_expr.span, + Expression::YieldExpression(yield_expr) => yield_expr.span, + Expression::PrivateInExpression(private_in_expr) => private_in_expr.span, + + Expression::JSXElement(jsx_element) => jsx_element.span, + Expression::JSXFragment(jsx_fragment) => jsx_fragment.span, + + Expression::TSAsExpression(ts_as_expr) => ts_as_expr.span, + Expression::TSSatisfiesExpression(ts_satisfies_expr) => ts_satisfies_expr.span, + Expression::TSTypeAssertion(ts_type_assertion) => ts_type_assertion.span, + Expression::TSNonNullExpression(ts_non_null_expr) => ts_non_null_expr.span, + Expression::TSInstantiationExpression(ts_instantiation_expr) => { + ts_instantiation_expr.span + } + + Expression::ComputedMemberExpression(computed_mem_expr) => computed_mem_expr.span, + Expression::StaticMemberExpression(static_mem_expr) => static_mem_expr.span, + Expression::PrivateFieldExpression(private_field_expr) => private_field_expr.span, + } + } + + #[allow(clippy::unnecessary_wraps)] + pub fn compile_allowed_snapshots( + matchers: &serde_json::Map, + ) -> Option, BuildHasherDefault>> { + Some( + matchers + .iter() + .map(|(key, value)| { + let serde_json::Value::Array(configs) = value else { + return (String::from(key), vec![]); + }; + + let configs = configs + .iter() + .filter_map(|c| c.as_str().map(std::string::ToString::to_string)) + .collect(); + + (String::from(key), configs) + }) + .collect(), + ) + } +} + +#[test] +fn test() { + use crate::tester::Tester; + use std::path::PathBuf; + + fn generate_snapshot_lines(lines: usize) -> String { + let repeated_lines = "line\n".repeat(lines); + format!("`\n{repeated_lines}`") + } + + fn generate_exports_snapshot_string(lines: usize, title: Option<&str>) -> String { + let title = title.unwrap_or("a big component 1"); + format!("exports[`{}`] = {};", title, generate_snapshot_lines(lines)) + } + + fn generate_expect_inline_snaps_code(line: usize, matcher: &str) -> String { + format!("expect(something).{}({});", matcher, generate_snapshot_lines(line)) + } + + fn generate_match_inline_snapshot(line: usize) -> String { + generate_expect_inline_snaps_code(line, "toMatchInlineSnapshot") + } + + fn generate_throw_error_matching_inline_snapshot(line: usize) -> String { + generate_expect_inline_snaps_code(line, "toThrowErrorMatchingInlineSnapshot") + } + + let tow_match_inline_cases = generate_match_inline_snapshot(2); + let two_throw_error_match_cases = generate_throw_error_matching_inline_snapshot(2); + let twenty_match_inline_cases = generate_match_inline_snapshot(20); + let sixty_match_inline_cases = generate_match_inline_snapshot(60); + let sixty_cases = format!( + " + expect( + functionUnderTest( + arg1, + arg2, + arg3 + ) + ).toMatchInlineSnapshot({}) + ", + generate_snapshot_lines(60) + ); + let twenty_exports_snapshot = generate_exports_snapshot_string(20, None); + let fifty_eight_exports_snapshot = generate_exports_snapshot_string(58, None); + + let pass = vec![ + ("expect(something)", None, None, None), + ("expect(something).toBe(1)", None, None, None), + ("expect(something).toMatchInlineSnapshot", None, None, None), + ("expect(something).toMatchInlineSnapshot()", None, None, None), + (tow_match_inline_cases.as_str(), None, None, None), + (two_throw_error_match_cases.as_str(), None, None, None), + ( + twenty_match_inline_cases.as_str(), + Some(serde_json::json!([{ "maxSize": 19, "inlineMaxSize": 21 }])), + None, + None, + ), + ( + sixty_match_inline_cases.as_str(), + Some(serde_json::json!([{ "maxSize": 61 }])), + None, + None, + ), + (sixty_cases.as_str(), Some(serde_json::json!([{ "maxSize": 61 }])), None, None), + // '/mock-component.jsx.snap' + ( + twenty_exports_snapshot.as_str(), + None, + None, + Some(PathBuf::from("/mock-component.jsx.snap")), + ), + // '/mock-component.jsx.snap' + ( + fifty_eight_exports_snapshot.as_str(), + Some(serde_json::json!([{ + "allowedSnapshots": { + "/mock-component.jsx.snap": ["a big component 1"] + } + }])), + None, + Some(PathBuf::from("/mock-component.jsx.snap")), + ), + // '/mock-component.jsx.snap' + ( + twenty_exports_snapshot.as_str(), + Some(serde_json::json!([{ "maxSize": 21, "inlineMaxSize": 19 }])), + None, + Some(PathBuf::from("/mock-component.jsx.snap")), + ), + ]; + + let fifty_match_inline_cases = generate_match_inline_snapshot(50); + let fifty_throw_error_match_cases = generate_throw_error_matching_inline_snapshot(50); + + let fifty_two_exports_snapshot = generate_exports_snapshot_string(58, None); + let one_hundred_exports_snapshot = generate_exports_snapshot_string(100, None); + let one_exports_snapshot = generate_exports_snapshot_string(1, None); + let fifty_eight_exports_snapshot = generate_exports_snapshot_string(58, None); + let vec_to_str = [ + generate_exports_snapshot_string(58, Some("a big component w/ text")), + generate_exports_snapshot_string(58, Some("a big component 2")), + ] + .join("\n\n"); + + let fail = vec![ + (fifty_match_inline_cases.as_str(), None, None, None), + (fifty_throw_error_match_cases.as_str(), None, None, None), + ( + fifty_throw_error_match_cases.as_str(), + Some(serde_json::json!([{ "maxSize": 51, "inlineMaxSize": 50 }])), + None, + None, + ), + // '/mock-component.jsx.snap' + ( + fifty_two_exports_snapshot.as_str(), + None, + None, + Some(PathBuf::from("/mock-component.jsx.snap")), + ), + // '/mock-component.jsx.snap' + ( + one_hundred_exports_snapshot.as_str(), + Some(serde_json::json!([{ "maxSize": 70 }])), + None, + Some(PathBuf::from("/mock-component.jsx.snap")), + ), + // '/mock-component.jsx.snap' + ( + one_hundred_exports_snapshot.as_str(), + Some(serde_json::json!([{ "maxSize": 70, "inlineMaxSize": 101 }])), + None, + Some(PathBuf::from("/mock-component.jsx.snap")), + ), + // '/mock-component.jsx.snap' + ( + one_exports_snapshot.as_str(), + Some(serde_json::json!([{ "maxSize": 0 }])), + None, + Some(PathBuf::from("/mock-component.jsx.snap")), + ), + // '/mock-component.jsx.snap' + ( + fifty_eight_exports_snapshot.as_str(), + Some(serde_json::json!([{ + "allowedSnapshots": { + "/another-mock-component.jsx.snap": [r"a big component \d+"] + } + }])), + None, + Some(PathBuf::from("/mock-component.jsx.snap")), + ), + // '/mock-component.jsx.snap' + ( + vec_to_str.as_str(), + Some(serde_json::json!([{ + "allowedSnapshots": { + "/mock-component.jsx.snap": [r"a big component \d+"], + }, + }])), + None, + Some(PathBuf::from("/mock-component.jsx.snap")), + ), + // '/mock-component.jsx.snap' + ( + vec_to_str.as_str(), + Some(serde_json::json!([{ + "allowedSnapshots": { + "/mock-component.jsx.snap": ["a big component 2"], + }, + }])), + None, + Some(PathBuf::from("/mock-component.jsx.snap")), + ), + ]; + + Tester::new(NoLargeSnapshots::NAME, pass, fail).with_jest_plugin(true).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_large_snapshots.snap b/crates/oxc_linter/src/snapshots/no_large_snapshots.snap new file mode 100644 index 0000000000000..a090287a83a61 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_large_snapshots.snap @@ -0,0 +1,659 @@ +--- +source: crates/oxc_linter/src/tester.rs +assertion_line: 161 +expression: no_large_snapshots +--- + ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. + ╭─[no_large_snapshots.tsx:1:41] + 1 │ ╭─▶ expect(something).toMatchInlineSnapshot(` + 2 │ │ line + 3 │ │ line + 4 │ │ line + 5 │ │ line + 6 │ │ line + 7 │ │ line + 8 │ │ line + 9 │ │ line + 10 │ │ line + 11 │ │ line + 12 │ │ line + 13 │ │ line + 14 │ │ line + 15 │ │ line + 16 │ │ line + 17 │ │ line + 18 │ │ line + 19 │ │ line + 20 │ │ line + 21 │ │ line + 22 │ │ line + 23 │ │ line + 24 │ │ line + 25 │ │ line + 26 │ │ line + 27 │ │ line + 28 │ │ line + 29 │ │ line + 30 │ │ line + 31 │ │ line + 32 │ │ line + 33 │ │ line + 34 │ │ line + 35 │ │ line + 36 │ │ line + 37 │ │ line + 38 │ │ line + 39 │ │ line + 40 │ │ line + 41 │ │ line + 42 │ │ line + 43 │ │ line + 44 │ │ line + 45 │ │ line + 46 │ │ line + 47 │ │ line + 48 │ │ line + 49 │ │ line + 50 │ │ line + 51 │ │ line + 52 │ ╰─▶ `); + ╰──── + help: Expected Jest snapshot to be smaller than 50 lines but was 51 lines long + + ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. + ╭─[no_large_snapshots.tsx:1:54] + 1 │ ╭─▶ expect(something).toThrowErrorMatchingInlineSnapshot(` + 2 │ │ line + 3 │ │ line + 4 │ │ line + 5 │ │ line + 6 │ │ line + 7 │ │ line + 8 │ │ line + 9 │ │ line + 10 │ │ line + 11 │ │ line + 12 │ │ line + 13 │ │ line + 14 │ │ line + 15 │ │ line + 16 │ │ line + 17 │ │ line + 18 │ │ line + 19 │ │ line + 20 │ │ line + 21 │ │ line + 22 │ │ line + 23 │ │ line + 24 │ │ line + 25 │ │ line + 26 │ │ line + 27 │ │ line + 28 │ │ line + 29 │ │ line + 30 │ │ line + 31 │ │ line + 32 │ │ line + 33 │ │ line + 34 │ │ line + 35 │ │ line + 36 │ │ line + 37 │ │ line + 38 │ │ line + 39 │ │ line + 40 │ │ line + 41 │ │ line + 42 │ │ line + 43 │ │ line + 44 │ │ line + 45 │ │ line + 46 │ │ line + 47 │ │ line + 48 │ │ line + 49 │ │ line + 50 │ │ line + 51 │ │ line + 52 │ ╰─▶ `); + ╰──── + help: Expected Jest snapshot to be smaller than 50 lines but was 51 lines long + + ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. + ╭─[no_large_snapshots.tsx:1:54] + 1 │ ╭─▶ expect(something).toThrowErrorMatchingInlineSnapshot(` + 2 │ │ line + 3 │ │ line + 4 │ │ line + 5 │ │ line + 6 │ │ line + 7 │ │ line + 8 │ │ line + 9 │ │ line + 10 │ │ line + 11 │ │ line + 12 │ │ line + 13 │ │ line + 14 │ │ line + 15 │ │ line + 16 │ │ line + 17 │ │ line + 18 │ │ line + 19 │ │ line + 20 │ │ line + 21 │ │ line + 22 │ │ line + 23 │ │ line + 24 │ │ line + 25 │ │ line + 26 │ │ line + 27 │ │ line + 28 │ │ line + 29 │ │ line + 30 │ │ line + 31 │ │ line + 32 │ │ line + 33 │ │ line + 34 │ │ line + 35 │ │ line + 36 │ │ line + 37 │ │ line + 38 │ │ line + 39 │ │ line + 40 │ │ line + 41 │ │ line + 42 │ │ line + 43 │ │ line + 44 │ │ line + 45 │ │ line + 46 │ │ line + 47 │ │ line + 48 │ │ line + 49 │ │ line + 50 │ │ line + 51 │ │ line + 52 │ ╰─▶ `); + ╰──── + help: Expected Jest snapshot to be smaller than 50 lines but was 51 lines long + + ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. + ╭─[no_large_snapshots.tsx:1:1] + 1 │ ╭─▶ exports[`a big component 1`] = ` + 2 │ │ line + 3 │ │ line + 4 │ │ line + 5 │ │ line + 6 │ │ line + 7 │ │ line + 8 │ │ line + 9 │ │ line + 10 │ │ line + 11 │ │ line + 12 │ │ line + 13 │ │ line + 14 │ │ line + 15 │ │ line + 16 │ │ line + 17 │ │ line + 18 │ │ line + 19 │ │ line + 20 │ │ line + 21 │ │ line + 22 │ │ line + 23 │ │ line + 24 │ │ line + 25 │ │ line + 26 │ │ line + 27 │ │ line + 28 │ │ line + 29 │ │ line + 30 │ │ line + 31 │ │ line + 32 │ │ line + 33 │ │ line + 34 │ │ line + 35 │ │ line + 36 │ │ line + 37 │ │ line + 38 │ │ line + 39 │ │ line + 40 │ │ line + 41 │ │ line + 42 │ │ line + 43 │ │ line + 44 │ │ line + 45 │ │ line + 46 │ │ line + 47 │ │ line + 48 │ │ line + 49 │ │ line + 50 │ │ line + 51 │ │ line + 52 │ │ line + 53 │ │ line + 54 │ │ line + 55 │ │ line + 56 │ │ line + 57 │ │ line + 58 │ │ line + 59 │ │ line + 60 │ ╰─▶ `; + ╰──── + help: Expected Jest snapshot to be smaller than 50 lines but was 59 lines long + + ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. + ╭─[no_large_snapshots.tsx:1:1] + 1 │ ╭─▶ exports[`a big component 1`] = ` + 2 │ │ line + 3 │ │ line + 4 │ │ line + 5 │ │ line + 6 │ │ line + 7 │ │ line + 8 │ │ line + 9 │ │ line + 10 │ │ line + 11 │ │ line + 12 │ │ line + 13 │ │ line + 14 │ │ line + 15 │ │ line + 16 │ │ line + 17 │ │ line + 18 │ │ line + 19 │ │ line + 20 │ │ line + 21 │ │ line + 22 │ │ line + 23 │ │ line + 24 │ │ line + 25 │ │ line + 26 │ │ line + 27 │ │ line + 28 │ │ line + 29 │ │ line + 30 │ │ line + 31 │ │ line + 32 │ │ line + 33 │ │ line + 34 │ │ line + 35 │ │ line + 36 │ │ line + 37 │ │ line + 38 │ │ line + 39 │ │ line + 40 │ │ line + 41 │ │ line + 42 │ │ line + 43 │ │ line + 44 │ │ line + 45 │ │ line + 46 │ │ line + 47 │ │ line + 48 │ │ line + 49 │ │ line + 50 │ │ line + 51 │ │ line + 52 │ │ line + 53 │ │ line + 54 │ │ line + 55 │ │ line + 56 │ │ line + 57 │ │ line + 58 │ │ line + 59 │ │ line + 60 │ │ line + 61 │ │ line + 62 │ │ line + 63 │ │ line + 64 │ │ line + 65 │ │ line + 66 │ │ line + 67 │ │ line + 68 │ │ line + 69 │ │ line + 70 │ │ line + 71 │ │ line + 72 │ │ line + 73 │ │ line + 74 │ │ line + 75 │ │ line + 76 │ │ line + 77 │ │ line + 78 │ │ line + 79 │ │ line + 80 │ │ line + 81 │ │ line + 82 │ │ line + 83 │ │ line + 84 │ │ line + 85 │ │ line + 86 │ │ line + 87 │ │ line + 88 │ │ line + 89 │ │ line + 90 │ │ line + 91 │ │ line + 92 │ │ line + 93 │ │ line + 94 │ │ line + 95 │ │ line + 96 │ │ line + 97 │ │ line + 98 │ │ line + 99 │ │ line + 100 │ │ line + 101 │ │ line + 102 │ ╰─▶ `; + ╰──── + help: Expected Jest snapshot to be smaller than 70 lines but was 101 lines long + + ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. + ╭─[no_large_snapshots.tsx:1:1] + 1 │ ╭─▶ exports[`a big component 1`] = ` + 2 │ │ line + 3 │ │ line + 4 │ │ line + 5 │ │ line + 6 │ │ line + 7 │ │ line + 8 │ │ line + 9 │ │ line + 10 │ │ line + 11 │ │ line + 12 │ │ line + 13 │ │ line + 14 │ │ line + 15 │ │ line + 16 │ │ line + 17 │ │ line + 18 │ │ line + 19 │ │ line + 20 │ │ line + 21 │ │ line + 22 │ │ line + 23 │ │ line + 24 │ │ line + 25 │ │ line + 26 │ │ line + 27 │ │ line + 28 │ │ line + 29 │ │ line + 30 │ │ line + 31 │ │ line + 32 │ │ line + 33 │ │ line + 34 │ │ line + 35 │ │ line + 36 │ │ line + 37 │ │ line + 38 │ │ line + 39 │ │ line + 40 │ │ line + 41 │ │ line + 42 │ │ line + 43 │ │ line + 44 │ │ line + 45 │ │ line + 46 │ │ line + 47 │ │ line + 48 │ │ line + 49 │ │ line + 50 │ │ line + 51 │ │ line + 52 │ │ line + 53 │ │ line + 54 │ │ line + 55 │ │ line + 56 │ │ line + 57 │ │ line + 58 │ │ line + 59 │ │ line + 60 │ │ line + 61 │ │ line + 62 │ │ line + 63 │ │ line + 64 │ │ line + 65 │ │ line + 66 │ │ line + 67 │ │ line + 68 │ │ line + 69 │ │ line + 70 │ │ line + 71 │ │ line + 72 │ │ line + 73 │ │ line + 74 │ │ line + 75 │ │ line + 76 │ │ line + 77 │ │ line + 78 │ │ line + 79 │ │ line + 80 │ │ line + 81 │ │ line + 82 │ │ line + 83 │ │ line + 84 │ │ line + 85 │ │ line + 86 │ │ line + 87 │ │ line + 88 │ │ line + 89 │ │ line + 90 │ │ line + 91 │ │ line + 92 │ │ line + 93 │ │ line + 94 │ │ line + 95 │ │ line + 96 │ │ line + 97 │ │ line + 98 │ │ line + 99 │ │ line + 100 │ │ line + 101 │ │ line + 102 │ ╰─▶ `; + ╰──── + help: Expected Jest snapshot to be smaller than 70 lines but was 101 lines long + + ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. + ╭─[no_large_snapshots.tsx:1:1] + 1 │ ╭─▶ exports[`a big component 1`] = ` + 2 │ │ line + 3 │ ╰─▶ `; + ╰──── + help: Expected Jest snapshot to be smaller than 0 lines but was 2 lines long + + ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. + ╭─[no_large_snapshots.tsx:1:1] + 1 │ ╭─▶ exports[`a big component 1`] = ` + 2 │ │ line + 3 │ │ line + 4 │ │ line + 5 │ │ line + 6 │ │ line + 7 │ │ line + 8 │ │ line + 9 │ │ line + 10 │ │ line + 11 │ │ line + 12 │ │ line + 13 │ │ line + 14 │ │ line + 15 │ │ line + 16 │ │ line + 17 │ │ line + 18 │ │ line + 19 │ │ line + 20 │ │ line + 21 │ │ line + 22 │ │ line + 23 │ │ line + 24 │ │ line + 25 │ │ line + 26 │ │ line + 27 │ │ line + 28 │ │ line + 29 │ │ line + 30 │ │ line + 31 │ │ line + 32 │ │ line + 33 │ │ line + 34 │ │ line + 35 │ │ line + 36 │ │ line + 37 │ │ line + 38 │ │ line + 39 │ │ line + 40 │ │ line + 41 │ │ line + 42 │ │ line + 43 │ │ line + 44 │ │ line + 45 │ │ line + 46 │ │ line + 47 │ │ line + 48 │ │ line + 49 │ │ line + 50 │ │ line + 51 │ │ line + 52 │ │ line + 53 │ │ line + 54 │ │ line + 55 │ │ line + 56 │ │ line + 57 │ │ line + 58 │ │ line + 59 │ │ line + 60 │ ╰─▶ `; + ╰──── + help: Expected Jest snapshot to be smaller than 50 lines but was 59 lines long + + ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. + ╭─[no_large_snapshots.tsx:1:1] + 1 │ ╭─▶ exports[`a big component w/ text`] = ` + 2 │ │ line + 3 │ │ line + 4 │ │ line + 5 │ │ line + 6 │ │ line + 7 │ │ line + 8 │ │ line + 9 │ │ line + 10 │ │ line + 11 │ │ line + 12 │ │ line + 13 │ │ line + 14 │ │ line + 15 │ │ line + 16 │ │ line + 17 │ │ line + 18 │ │ line + 19 │ │ line + 20 │ │ line + 21 │ │ line + 22 │ │ line + 23 │ │ line + 24 │ │ line + 25 │ │ line + 26 │ │ line + 27 │ │ line + 28 │ │ line + 29 │ │ line + 30 │ │ line + 31 │ │ line + 32 │ │ line + 33 │ │ line + 34 │ │ line + 35 │ │ line + 36 │ │ line + 37 │ │ line + 38 │ │ line + 39 │ │ line + 40 │ │ line + 41 │ │ line + 42 │ │ line + 43 │ │ line + 44 │ │ line + 45 │ │ line + 46 │ │ line + 47 │ │ line + 48 │ │ line + 49 │ │ line + 50 │ │ line + 51 │ │ line + 52 │ │ line + 53 │ │ line + 54 │ │ line + 55 │ │ line + 56 │ │ line + 57 │ │ line + 58 │ │ line + 59 │ │ line + 60 │ ╰─▶ `; + 61 │ + ╰──── + help: Expected Jest snapshot to be smaller than 50 lines but was 59 lines long + + ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. + ╭─[no_large_snapshots.tsx:1:1] + 1 │ ╭─▶ exports[`a big component w/ text`] = ` + 2 │ │ line + 3 │ │ line + 4 │ │ line + 5 │ │ line + 6 │ │ line + 7 │ │ line + 8 │ │ line + 9 │ │ line + 10 │ │ line + 11 │ │ line + 12 │ │ line + 13 │ │ line + 14 │ │ line + 15 │ │ line + 16 │ │ line + 17 │ │ line + 18 │ │ line + 19 │ │ line + 20 │ │ line + 21 │ │ line + 22 │ │ line + 23 │ │ line + 24 │ │ line + 25 │ │ line + 26 │ │ line + 27 │ │ line + 28 │ │ line + 29 │ │ line + 30 │ │ line + 31 │ │ line + 32 │ │ line + 33 │ │ line + 34 │ │ line + 35 │ │ line + 36 │ │ line + 37 │ │ line + 38 │ │ line + 39 │ │ line + 40 │ │ line + 41 │ │ line + 42 │ │ line + 43 │ │ line + 44 │ │ line + 45 │ │ line + 46 │ │ line + 47 │ │ line + 48 │ │ line + 49 │ │ line + 50 │ │ line + 51 │ │ line + 52 │ │ line + 53 │ │ line + 54 │ │ line + 55 │ │ line + 56 │ │ line + 57 │ │ line + 58 │ │ line + 59 │ │ line + 60 │ ╰─▶ `; + 61 │ + ╰──── + help: Expected Jest snapshot to be smaller than 50 lines but was 59 lines long diff --git a/crates/oxc_span/src/source_type.rs b/crates/oxc_span/src/source_type.rs index 65284e1cb2669..e6988ec36677a 100644 --- a/crates/oxc_span/src/source_type.rs +++ b/crates/oxc_span/src/source_type.rs @@ -71,7 +71,8 @@ impl Default for SourceType { } /// Valid file extensions -pub const VALID_EXTENSIONS: [&str; 8] = ["js", "mjs", "cjs", "jsx", "ts", "mts", "cts", "tsx"]; +pub const VALID_EXTENSIONS: [&str; 9] = + ["js", "mjs", "cjs", "jsx", "ts", "mts", "cts", "tsx", "snap"]; impl SourceType { pub fn is_script(self) -> bool { @@ -188,7 +189,7 @@ impl SourceType { "mts" if file_name.ends_with(".d.mts") => Language::TypeScriptDefinition, "cts" if file_name.ends_with(".d.cts") => Language::TypeScriptDefinition, _ => { - debug_assert!(matches!(extension, "ts" | "mts" | "cts" | "tsx")); + debug_assert!(matches!(extension, "ts" | "mts" | "cts" | "tsx" | "snap")); Language::TypeScript } }; From b0cd0073f1873f877dc71993e4303c87d5e62440 Mon Sep 17 00:00:00 2001 From: eryue0220 Date: Tue, 28 May 2024 00:06:31 +0800 Subject: [PATCH 2/6] fix: platform bug --- .../src/rules/jest/no_large_snapshots.rs | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs index 875d29f13d152..5d2721cd6e224 100644 --- a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs +++ b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs @@ -399,6 +399,16 @@ fn test() { generate_expect_inline_snaps_code(line, "toThrowErrorMatchingInlineSnapshot") } + #[cfg(target_os = "windows")] + let snap_path = "c:\\mock-component.jsx.snap"; + #[cfg(target_os = "windows")] + let another_snap_path = "c:\\another-mock-component.jsx.snaps"; + + #[cfg(not(target_os = "windows"))] + let snap_path = "/mock-component.jsx.snap"; + #[cfg(not(target_os = "windows"))] + let another_snap_path = "/another-mock-component.jsx.snap"; + let tow_match_inline_cases = generate_match_inline_snapshot(2); let two_throw_error_match_cases = generate_throw_error_matching_inline_snapshot(2); let twenty_match_inline_cases = generate_match_inline_snapshot(20); @@ -439,29 +449,24 @@ fn test() { ), (sixty_cases.as_str(), Some(serde_json::json!([{ "maxSize": 61 }])), None, None), // '/mock-component.jsx.snap' - ( - twenty_exports_snapshot.as_str(), - None, - None, - Some(PathBuf::from("/mock-component.jsx.snap")), - ), + (twenty_exports_snapshot.as_str(), None, None, Some(PathBuf::from(snap_path))), // '/mock-component.jsx.snap' ( fifty_eight_exports_snapshot.as_str(), Some(serde_json::json!([{ "allowedSnapshots": { - "/mock-component.jsx.snap": ["a big component 1"] + snap_path.to_string(): ["a big component 1"] } }])), None, - Some(PathBuf::from("/mock-component.jsx.snap")), + Some(PathBuf::from(snap_path)), ), // '/mock-component.jsx.snap' ( twenty_exports_snapshot.as_str(), Some(serde_json::json!([{ "maxSize": 21, "inlineMaxSize": 19 }])), None, - Some(PathBuf::from("/mock-component.jsx.snap")), + Some(PathBuf::from(snap_path)), ), ]; @@ -488,65 +493,60 @@ fn test() { None, ), // '/mock-component.jsx.snap' - ( - fifty_two_exports_snapshot.as_str(), - None, - None, - Some(PathBuf::from("/mock-component.jsx.snap")), - ), + (fifty_two_exports_snapshot.as_str(), None, None, Some(PathBuf::from(snap_path))), // '/mock-component.jsx.snap' ( one_hundred_exports_snapshot.as_str(), Some(serde_json::json!([{ "maxSize": 70 }])), None, - Some(PathBuf::from("/mock-component.jsx.snap")), + Some(PathBuf::from(snap_path)), ), // '/mock-component.jsx.snap' ( one_hundred_exports_snapshot.as_str(), Some(serde_json::json!([{ "maxSize": 70, "inlineMaxSize": 101 }])), None, - Some(PathBuf::from("/mock-component.jsx.snap")), + Some(PathBuf::from(snap_path)), ), // '/mock-component.jsx.snap' ( one_exports_snapshot.as_str(), Some(serde_json::json!([{ "maxSize": 0 }])), None, - Some(PathBuf::from("/mock-component.jsx.snap")), + Some(PathBuf::from(snap_path)), ), // '/mock-component.jsx.snap' ( fifty_eight_exports_snapshot.as_str(), Some(serde_json::json!([{ "allowedSnapshots": { - "/another-mock-component.jsx.snap": [r"a big component \d+"] + another_snap_path.to_string(): [r"a big component \d+"] } }])), None, - Some(PathBuf::from("/mock-component.jsx.snap")), + Some(PathBuf::from(snap_path)), ), // '/mock-component.jsx.snap' ( vec_to_str.as_str(), Some(serde_json::json!([{ "allowedSnapshots": { - "/mock-component.jsx.snap": [r"a big component \d+"], + snap_path.to_string(): [r"a big component \d+"], }, }])), None, - Some(PathBuf::from("/mock-component.jsx.snap")), + Some(PathBuf::from(snap_path)), ), // '/mock-component.jsx.snap' ( vec_to_str.as_str(), Some(serde_json::json!([{ "allowedSnapshots": { - "/mock-component.jsx.snap": ["a big component 2"], + snap_path.to_string(): ["a big component 2"], }, }])), None, - Some(PathBuf::from("/mock-component.jsx.snap")), + Some(PathBuf::from(snap_path)), ), ]; From e70a4c455306c6fd8078e1a682b018fceaa4036d Mon Sep 17 00:00:00 2001 From: eryue0220 Date: Thu, 30 May 2024 22:15:51 +0800 Subject: [PATCH 3/6] fix: cr --- .../src/rules/jest/no_large_snapshots.rs | 59 +------------------ 1 file changed, 2 insertions(+), 57 deletions(-) diff --git a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs index 5d2721cd6e224..316ed7b2badec 100644 --- a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs +++ b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs @@ -4,7 +4,7 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::Span; +use oxc_span::{GetSpan, Span}; use regex::Regex; use rustc_hash::{FxHashMap, FxHasher}; use std::{collections::HashMap, hash::BuildHasherDefault, ops::Deref, path::Path}; @@ -196,7 +196,7 @@ impl NoLargeSnapshots { return; }; - let span = Self::get_span_from_expression(first_arg_expr); + let span = first_arg_expr.span(); self.report_in_span(span, ctx); } } @@ -293,61 +293,6 @@ impl NoLargeSnapshots { end - start } - fn get_span_from_expression(expr: &Expression) -> Span { - match expr { - Expression::BooleanLiteral(bool_literal) => bool_literal.span, - Expression::NullLiteral(null_literal) => null_literal.span, - Expression::NumericLiteral(numeric_literal) => numeric_literal.span, - Expression::BigintLiteral(bigint_literal) => bigint_literal.span, - Expression::RegExpLiteral(regexp_literal) => regexp_literal.span, - Expression::StringLiteral(string_literal) => string_literal.span, - Expression::TemplateLiteral(template_literal) => template_literal.span, - - Expression::Identifier(ident) => ident.span, - - Expression::MetaProperty(meta_property) => meta_property.span, - Expression::Super(super_expr) => super_expr.span, - - Expression::ArrayExpression(array_expr) => array_expr.span, - Expression::ArrowFunctionExpression(arrow_func_expr) => arrow_func_expr.span, - Expression::AssignmentExpression(assignment_expr) => assignment_expr.span, - Expression::AwaitExpression(await_expr) => await_expr.span, - Expression::BinaryExpression(binary_expr) => binary_expr.span, - Expression::CallExpression(call_expr) => call_expr.span, - Expression::ChainExpression(chain_expr) => chain_expr.span, - Expression::ClassExpression(class_expr) => class_expr.span, - Expression::ConditionalExpression(conditional_expr) => conditional_expr.span, - Expression::FunctionExpression(func_expr) => func_expr.span, - Expression::ImportExpression(import_expr) => import_expr.span, - Expression::LogicalExpression(logical_expr) => logical_expr.span, - Expression::NewExpression(new_expr) => new_expr.span, - Expression::ObjectExpression(object_expr) => object_expr.span, - Expression::ParenthesizedExpression(parenthesized_expr) => parenthesized_expr.span, - Expression::SequenceExpression(sequence_expr) => sequence_expr.span, - Expression::TaggedTemplateExpression(tagged_temp_expr) => tagged_temp_expr.span, - Expression::ThisExpression(this_expr) => this_expr.span, - Expression::UnaryExpression(unary_expr) => unary_expr.span, - Expression::UpdateExpression(update_expr) => update_expr.span, - Expression::YieldExpression(yield_expr) => yield_expr.span, - Expression::PrivateInExpression(private_in_expr) => private_in_expr.span, - - Expression::JSXElement(jsx_element) => jsx_element.span, - Expression::JSXFragment(jsx_fragment) => jsx_fragment.span, - - Expression::TSAsExpression(ts_as_expr) => ts_as_expr.span, - Expression::TSSatisfiesExpression(ts_satisfies_expr) => ts_satisfies_expr.span, - Expression::TSTypeAssertion(ts_type_assertion) => ts_type_assertion.span, - Expression::TSNonNullExpression(ts_non_null_expr) => ts_non_null_expr.span, - Expression::TSInstantiationExpression(ts_instantiation_expr) => { - ts_instantiation_expr.span - } - - Expression::ComputedMemberExpression(computed_mem_expr) => computed_mem_expr.span, - Expression::StaticMemberExpression(static_mem_expr) => static_mem_expr.span, - Expression::PrivateFieldExpression(private_field_expr) => private_field_expr.span, - } - } - #[allow(clippy::unnecessary_wraps)] pub fn compile_allowed_snapshots( matchers: &serde_json::Map, From 583b0ad00e2c757233f34bedeae7469082902806 Mon Sep 17 00:00:00 2001 From: eryue0220 Date: Thu, 30 May 2024 22:25:51 +0800 Subject: [PATCH 4/6] fix: cr --- .../oxc_linter/src/rules/jest/no_large_snapshots.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs index 316ed7b2badec..99ecfb1295576 100644 --- a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs +++ b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs @@ -202,8 +202,6 @@ impl NoLargeSnapshots { } fn report_in_expr_stmt(&self, expr_stmt: &ExpressionStatement, ctx: &LintContext) { - self.check_all_paths_are_absolute(); - let line_count = Self::get_line_count(expr_stmt.span, ctx); let allowed = match &expr_stmt.expression { Expression::AssignmentExpression(assignment_expr) => { @@ -237,8 +235,6 @@ impl NoLargeSnapshots { } fn report_in_span(&self, span: Span, ctx: &LintContext) { - self.check_all_paths_are_absolute(); - let line_count = Self::get_line_count(span, ctx); if line_count > self.inline_max_size { @@ -274,15 +270,6 @@ impl NoLargeSnapshots { }) } - fn check_all_paths_are_absolute(&self) { - let all_paths_are_absolute = - self.allowed_snapshots.keys().all(|p| Path::new(p).is_absolute()); - - assert!(all_paths_are_absolute, - "All paths for allowedSnapshots must be absolute. You can use JS config and `path.resolve`", - ); - } - fn get_line_count(span: Span, ctx: &LintContext) -> usize { let start = span.start as usize; let start = if start == 0 { 1 } else { start }; From 66155db7d4a1d4f91dbba172b32c283e7f710cf8 Mon Sep 17 00:00:00 2001 From: eryue0220 Date: Sun, 2 Jun 2024 14:46:13 +0800 Subject: [PATCH 5/6] fix: remove snap type --- .../src/rules/jest/no_large_snapshots.rs | 184 +++---- .../src/snapshots/no_large_snapshots.snap | 484 ------------------ crates/oxc_span/src/source_type.rs | 5 +- 3 files changed, 95 insertions(+), 578 deletions(-) diff --git a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs index 99ecfb1295576..56af1ba6ddf16 100644 --- a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs +++ b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs @@ -274,8 +274,8 @@ impl NoLargeSnapshots { let start = span.start as usize; let start = if start == 0 { 1 } else { start }; let end = span.end as usize; - let start = ctx.source_text()[..start].lines().count(); let end = ctx.source_text()[start..end].lines().count(); + let start = ctx.source_text()[..start].lines().count(); end - start } @@ -307,17 +307,17 @@ impl NoLargeSnapshots { #[test] fn test() { use crate::tester::Tester; - use std::path::PathBuf; + // use std::path::PathBuf; fn generate_snapshot_lines(lines: usize) -> String { let repeated_lines = "line\n".repeat(lines); format!("`\n{repeated_lines}`") } - fn generate_exports_snapshot_string(lines: usize, title: Option<&str>) -> String { - let title = title.unwrap_or("a big component 1"); - format!("exports[`{}`] = {};", title, generate_snapshot_lines(lines)) - } + // fn generate_exports_snapshot_string(lines: usize, title: Option<&str>) -> String { + // let title = title.unwrap_or("a big component 1"); + // format!("exports[`{}`] = {};", title, generate_snapshot_lines(lines)) + // } fn generate_expect_inline_snaps_code(line: usize, matcher: &str) -> String { format!("expect(something).{}({});", matcher, generate_snapshot_lines(line)) @@ -331,15 +331,17 @@ fn test() { generate_expect_inline_snaps_code(line, "toThrowErrorMatchingInlineSnapshot") } - #[cfg(target_os = "windows")] - let snap_path = "c:\\mock-component.jsx.snap"; - #[cfg(target_os = "windows")] - let another_snap_path = "c:\\another-mock-component.jsx.snaps"; + // Note: Currently oxlint didn't check `.snap` file + // + // #[cfg(target_os = "windows")] + // let snap_path = "c:\\mock-component.jsx.snap"; + // #[cfg(target_os = "windows")] + // let another_snap_path = "c:\\another-mock-component.jsx.snap"; - #[cfg(not(target_os = "windows"))] - let snap_path = "/mock-component.jsx.snap"; - #[cfg(not(target_os = "windows"))] - let another_snap_path = "/another-mock-component.jsx.snap"; + // #[cfg(not(target_os = "windows"))] + // let snap_path = "/mock-component.jsx.snap"; + // #[cfg(not(target_os = "windows"))] + // let another_snap_path = "/another-mock-component.jsx.snap"; let tow_match_inline_cases = generate_match_inline_snapshot(2); let two_throw_error_match_cases = generate_throw_error_matching_inline_snapshot(2); @@ -357,8 +359,8 @@ fn test() { ", generate_snapshot_lines(60) ); - let twenty_exports_snapshot = generate_exports_snapshot_string(20, None); - let fifty_eight_exports_snapshot = generate_exports_snapshot_string(58, None); + // let twenty_exports_snapshot = generate_exports_snapshot_string(20, None); + // let fifty_eight_exports_snapshot = generate_exports_snapshot_string(58, None); let pass = vec![ ("expect(something)", None, None, None), @@ -381,39 +383,39 @@ fn test() { ), (sixty_cases.as_str(), Some(serde_json::json!([{ "maxSize": 61 }])), None, None), // '/mock-component.jsx.snap' - (twenty_exports_snapshot.as_str(), None, None, Some(PathBuf::from(snap_path))), + // (twenty_exports_snapshot.as_str(), None, None, Some(PathBuf::from(snap_path))), // '/mock-component.jsx.snap' - ( - fifty_eight_exports_snapshot.as_str(), - Some(serde_json::json!([{ - "allowedSnapshots": { - snap_path.to_string(): ["a big component 1"] - } - }])), - None, - Some(PathBuf::from(snap_path)), - ), + // ( + // fifty_eight_exports_snapshot.as_str(), + // Some(serde_json::json!([{ + // "allowedSnapshots": { + // snap_path.to_string(): ["a big component 1"] + // } + // }])), + // None, + // Some(PathBuf::from(snap_path)), + // ), // '/mock-component.jsx.snap' - ( - twenty_exports_snapshot.as_str(), - Some(serde_json::json!([{ "maxSize": 21, "inlineMaxSize": 19 }])), - None, - Some(PathBuf::from(snap_path)), - ), + // ( + // twenty_exports_snapshot.as_str(), + // Some(serde_json::json!([{ "maxSize": 21, "inlineMaxSize": 19 }])), + // None, + // Some(PathBuf::from(snap_path)), + // ), ]; let fifty_match_inline_cases = generate_match_inline_snapshot(50); let fifty_throw_error_match_cases = generate_throw_error_matching_inline_snapshot(50); - let fifty_two_exports_snapshot = generate_exports_snapshot_string(58, None); - let one_hundred_exports_snapshot = generate_exports_snapshot_string(100, None); - let one_exports_snapshot = generate_exports_snapshot_string(1, None); - let fifty_eight_exports_snapshot = generate_exports_snapshot_string(58, None); - let vec_to_str = [ - generate_exports_snapshot_string(58, Some("a big component w/ text")), - generate_exports_snapshot_string(58, Some("a big component 2")), - ] - .join("\n\n"); + // let fifty_two_exports_snapshot = generate_exports_snapshot_string(58, None); + // let one_hundred_exports_snapshot = generate_exports_snapshot_string(100, None); + // let one_exports_snapshot = generate_exports_snapshot_string(1, None); + // let fifty_eight_exports_snapshot = generate_exports_snapshot_string(58, None); + // let vec_to_str = [ + // generate_exports_snapshot_string(58, Some("a big component w/ text")), + // generate_exports_snapshot_string(58, Some("a big component 2")), + // ] + // .join("\n\n"); let fail = vec![ (fifty_match_inline_cases.as_str(), None, None, None), @@ -425,61 +427,61 @@ fn test() { None, ), // '/mock-component.jsx.snap' - (fifty_two_exports_snapshot.as_str(), None, None, Some(PathBuf::from(snap_path))), + // (fifty_two_exports_snapshot.as_str(), None, None, Some(PathBuf::from(snap_path))), // '/mock-component.jsx.snap' - ( - one_hundred_exports_snapshot.as_str(), - Some(serde_json::json!([{ "maxSize": 70 }])), - None, - Some(PathBuf::from(snap_path)), - ), + // ( + // one_hundred_exports_snapshot.as_str(), + // Some(serde_json::json!([{ "maxSize": 70 }])), + // None, + // Some(PathBuf::from(snap_path)), + // ), // '/mock-component.jsx.snap' - ( - one_hundred_exports_snapshot.as_str(), - Some(serde_json::json!([{ "maxSize": 70, "inlineMaxSize": 101 }])), - None, - Some(PathBuf::from(snap_path)), - ), + // ( + // one_hundred_exports_snapshot.as_str(), + // Some(serde_json::json!([{ "maxSize": 70, "inlineMaxSize": 101 }])), + // None, + // Some(PathBuf::from(snap_path)), + // ), // '/mock-component.jsx.snap' - ( - one_exports_snapshot.as_str(), - Some(serde_json::json!([{ "maxSize": 0 }])), - None, - Some(PathBuf::from(snap_path)), - ), + // ( + // one_exports_snapshot.as_str(), + // Some(serde_json::json!([{ "maxSize": 0 }])), + // None, + // Some(PathBuf::from(snap_path)), + // ), // '/mock-component.jsx.snap' - ( - fifty_eight_exports_snapshot.as_str(), - Some(serde_json::json!([{ - "allowedSnapshots": { - another_snap_path.to_string(): [r"a big component \d+"] - } - }])), - None, - Some(PathBuf::from(snap_path)), - ), + // ( + // fifty_eight_exports_snapshot.as_str(), + // Some(serde_json::json!([{ + // "allowedSnapshots": { + // another_snap_path.to_string(): [r"a big component \d+"] + // } + // }])), + // None, + // Some(PathBuf::from(snap_path)), + // ), // '/mock-component.jsx.snap' - ( - vec_to_str.as_str(), - Some(serde_json::json!([{ - "allowedSnapshots": { - snap_path.to_string(): [r"a big component \d+"], - }, - }])), - None, - Some(PathBuf::from(snap_path)), - ), + // ( + // vec_to_str.as_str(), + // Some(serde_json::json!([{ + // "allowedSnapshots": { + // snap_path.to_string(): [r"a big component \d+"], + // }, + // }])), + // None, + // Some(PathBuf::from(snap_path)), + // ), // '/mock-component.jsx.snap' - ( - vec_to_str.as_str(), - Some(serde_json::json!([{ - "allowedSnapshots": { - snap_path.to_string(): ["a big component 2"], - }, - }])), - None, - Some(PathBuf::from(snap_path)), - ), + // ( + // vec_to_str.as_str(), + // Some(serde_json::json!([{ + // "allowedSnapshots": { + // snap_path.to_string(): ["a big component 2"], + // }, + // }])), + // None, + // Some(PathBuf::from(snap_path)), + // ), ]; Tester::new(NoLargeSnapshots::NAME, pass, fail).with_jest_plugin(true).test_and_snapshot(); diff --git a/crates/oxc_linter/src/snapshots/no_large_snapshots.snap b/crates/oxc_linter/src/snapshots/no_large_snapshots.snap index a090287a83a61..f8b418836057f 100644 --- a/crates/oxc_linter/src/snapshots/no_large_snapshots.snap +++ b/crates/oxc_linter/src/snapshots/no_large_snapshots.snap @@ -173,487 +173,3 @@ expression: no_large_snapshots 52 │ ╰─▶ `); ╰──── help: Expected Jest snapshot to be smaller than 50 lines but was 51 lines long - - ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. - ╭─[no_large_snapshots.tsx:1:1] - 1 │ ╭─▶ exports[`a big component 1`] = ` - 2 │ │ line - 3 │ │ line - 4 │ │ line - 5 │ │ line - 6 │ │ line - 7 │ │ line - 8 │ │ line - 9 │ │ line - 10 │ │ line - 11 │ │ line - 12 │ │ line - 13 │ │ line - 14 │ │ line - 15 │ │ line - 16 │ │ line - 17 │ │ line - 18 │ │ line - 19 │ │ line - 20 │ │ line - 21 │ │ line - 22 │ │ line - 23 │ │ line - 24 │ │ line - 25 │ │ line - 26 │ │ line - 27 │ │ line - 28 │ │ line - 29 │ │ line - 30 │ │ line - 31 │ │ line - 32 │ │ line - 33 │ │ line - 34 │ │ line - 35 │ │ line - 36 │ │ line - 37 │ │ line - 38 │ │ line - 39 │ │ line - 40 │ │ line - 41 │ │ line - 42 │ │ line - 43 │ │ line - 44 │ │ line - 45 │ │ line - 46 │ │ line - 47 │ │ line - 48 │ │ line - 49 │ │ line - 50 │ │ line - 51 │ │ line - 52 │ │ line - 53 │ │ line - 54 │ │ line - 55 │ │ line - 56 │ │ line - 57 │ │ line - 58 │ │ line - 59 │ │ line - 60 │ ╰─▶ `; - ╰──── - help: Expected Jest snapshot to be smaller than 50 lines but was 59 lines long - - ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. - ╭─[no_large_snapshots.tsx:1:1] - 1 │ ╭─▶ exports[`a big component 1`] = ` - 2 │ │ line - 3 │ │ line - 4 │ │ line - 5 │ │ line - 6 │ │ line - 7 │ │ line - 8 │ │ line - 9 │ │ line - 10 │ │ line - 11 │ │ line - 12 │ │ line - 13 │ │ line - 14 │ │ line - 15 │ │ line - 16 │ │ line - 17 │ │ line - 18 │ │ line - 19 │ │ line - 20 │ │ line - 21 │ │ line - 22 │ │ line - 23 │ │ line - 24 │ │ line - 25 │ │ line - 26 │ │ line - 27 │ │ line - 28 │ │ line - 29 │ │ line - 30 │ │ line - 31 │ │ line - 32 │ │ line - 33 │ │ line - 34 │ │ line - 35 │ │ line - 36 │ │ line - 37 │ │ line - 38 │ │ line - 39 │ │ line - 40 │ │ line - 41 │ │ line - 42 │ │ line - 43 │ │ line - 44 │ │ line - 45 │ │ line - 46 │ │ line - 47 │ │ line - 48 │ │ line - 49 │ │ line - 50 │ │ line - 51 │ │ line - 52 │ │ line - 53 │ │ line - 54 │ │ line - 55 │ │ line - 56 │ │ line - 57 │ │ line - 58 │ │ line - 59 │ │ line - 60 │ │ line - 61 │ │ line - 62 │ │ line - 63 │ │ line - 64 │ │ line - 65 │ │ line - 66 │ │ line - 67 │ │ line - 68 │ │ line - 69 │ │ line - 70 │ │ line - 71 │ │ line - 72 │ │ line - 73 │ │ line - 74 │ │ line - 75 │ │ line - 76 │ │ line - 77 │ │ line - 78 │ │ line - 79 │ │ line - 80 │ │ line - 81 │ │ line - 82 │ │ line - 83 │ │ line - 84 │ │ line - 85 │ │ line - 86 │ │ line - 87 │ │ line - 88 │ │ line - 89 │ │ line - 90 │ │ line - 91 │ │ line - 92 │ │ line - 93 │ │ line - 94 │ │ line - 95 │ │ line - 96 │ │ line - 97 │ │ line - 98 │ │ line - 99 │ │ line - 100 │ │ line - 101 │ │ line - 102 │ ╰─▶ `; - ╰──── - help: Expected Jest snapshot to be smaller than 70 lines but was 101 lines long - - ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. - ╭─[no_large_snapshots.tsx:1:1] - 1 │ ╭─▶ exports[`a big component 1`] = ` - 2 │ │ line - 3 │ │ line - 4 │ │ line - 5 │ │ line - 6 │ │ line - 7 │ │ line - 8 │ │ line - 9 │ │ line - 10 │ │ line - 11 │ │ line - 12 │ │ line - 13 │ │ line - 14 │ │ line - 15 │ │ line - 16 │ │ line - 17 │ │ line - 18 │ │ line - 19 │ │ line - 20 │ │ line - 21 │ │ line - 22 │ │ line - 23 │ │ line - 24 │ │ line - 25 │ │ line - 26 │ │ line - 27 │ │ line - 28 │ │ line - 29 │ │ line - 30 │ │ line - 31 │ │ line - 32 │ │ line - 33 │ │ line - 34 │ │ line - 35 │ │ line - 36 │ │ line - 37 │ │ line - 38 │ │ line - 39 │ │ line - 40 │ │ line - 41 │ │ line - 42 │ │ line - 43 │ │ line - 44 │ │ line - 45 │ │ line - 46 │ │ line - 47 │ │ line - 48 │ │ line - 49 │ │ line - 50 │ │ line - 51 │ │ line - 52 │ │ line - 53 │ │ line - 54 │ │ line - 55 │ │ line - 56 │ │ line - 57 │ │ line - 58 │ │ line - 59 │ │ line - 60 │ │ line - 61 │ │ line - 62 │ │ line - 63 │ │ line - 64 │ │ line - 65 │ │ line - 66 │ │ line - 67 │ │ line - 68 │ │ line - 69 │ │ line - 70 │ │ line - 71 │ │ line - 72 │ │ line - 73 │ │ line - 74 │ │ line - 75 │ │ line - 76 │ │ line - 77 │ │ line - 78 │ │ line - 79 │ │ line - 80 │ │ line - 81 │ │ line - 82 │ │ line - 83 │ │ line - 84 │ │ line - 85 │ │ line - 86 │ │ line - 87 │ │ line - 88 │ │ line - 89 │ │ line - 90 │ │ line - 91 │ │ line - 92 │ │ line - 93 │ │ line - 94 │ │ line - 95 │ │ line - 96 │ │ line - 97 │ │ line - 98 │ │ line - 99 │ │ line - 100 │ │ line - 101 │ │ line - 102 │ ╰─▶ `; - ╰──── - help: Expected Jest snapshot to be smaller than 70 lines but was 101 lines long - - ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. - ╭─[no_large_snapshots.tsx:1:1] - 1 │ ╭─▶ exports[`a big component 1`] = ` - 2 │ │ line - 3 │ ╰─▶ `; - ╰──── - help: Expected Jest snapshot to be smaller than 0 lines but was 2 lines long - - ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. - ╭─[no_large_snapshots.tsx:1:1] - 1 │ ╭─▶ exports[`a big component 1`] = ` - 2 │ │ line - 3 │ │ line - 4 │ │ line - 5 │ │ line - 6 │ │ line - 7 │ │ line - 8 │ │ line - 9 │ │ line - 10 │ │ line - 11 │ │ line - 12 │ │ line - 13 │ │ line - 14 │ │ line - 15 │ │ line - 16 │ │ line - 17 │ │ line - 18 │ │ line - 19 │ │ line - 20 │ │ line - 21 │ │ line - 22 │ │ line - 23 │ │ line - 24 │ │ line - 25 │ │ line - 26 │ │ line - 27 │ │ line - 28 │ │ line - 29 │ │ line - 30 │ │ line - 31 │ │ line - 32 │ │ line - 33 │ │ line - 34 │ │ line - 35 │ │ line - 36 │ │ line - 37 │ │ line - 38 │ │ line - 39 │ │ line - 40 │ │ line - 41 │ │ line - 42 │ │ line - 43 │ │ line - 44 │ │ line - 45 │ │ line - 46 │ │ line - 47 │ │ line - 48 │ │ line - 49 │ │ line - 50 │ │ line - 51 │ │ line - 52 │ │ line - 53 │ │ line - 54 │ │ line - 55 │ │ line - 56 │ │ line - 57 │ │ line - 58 │ │ line - 59 │ │ line - 60 │ ╰─▶ `; - ╰──── - help: Expected Jest snapshot to be smaller than 50 lines but was 59 lines long - - ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. - ╭─[no_large_snapshots.tsx:1:1] - 1 │ ╭─▶ exports[`a big component w/ text`] = ` - 2 │ │ line - 3 │ │ line - 4 │ │ line - 5 │ │ line - 6 │ │ line - 7 │ │ line - 8 │ │ line - 9 │ │ line - 10 │ │ line - 11 │ │ line - 12 │ │ line - 13 │ │ line - 14 │ │ line - 15 │ │ line - 16 │ │ line - 17 │ │ line - 18 │ │ line - 19 │ │ line - 20 │ │ line - 21 │ │ line - 22 │ │ line - 23 │ │ line - 24 │ │ line - 25 │ │ line - 26 │ │ line - 27 │ │ line - 28 │ │ line - 29 │ │ line - 30 │ │ line - 31 │ │ line - 32 │ │ line - 33 │ │ line - 34 │ │ line - 35 │ │ line - 36 │ │ line - 37 │ │ line - 38 │ │ line - 39 │ │ line - 40 │ │ line - 41 │ │ line - 42 │ │ line - 43 │ │ line - 44 │ │ line - 45 │ │ line - 46 │ │ line - 47 │ │ line - 48 │ │ line - 49 │ │ line - 50 │ │ line - 51 │ │ line - 52 │ │ line - 53 │ │ line - 54 │ │ line - 55 │ │ line - 56 │ │ line - 57 │ │ line - 58 │ │ line - 59 │ │ line - 60 │ ╰─▶ `; - 61 │ - ╰──── - help: Expected Jest snapshot to be smaller than 50 lines but was 59 lines long - - ⚠ eslint-plugin-jest(no-large-snapshots): Disallow large snapshots. - ╭─[no_large_snapshots.tsx:1:1] - 1 │ ╭─▶ exports[`a big component w/ text`] = ` - 2 │ │ line - 3 │ │ line - 4 │ │ line - 5 │ │ line - 6 │ │ line - 7 │ │ line - 8 │ │ line - 9 │ │ line - 10 │ │ line - 11 │ │ line - 12 │ │ line - 13 │ │ line - 14 │ │ line - 15 │ │ line - 16 │ │ line - 17 │ │ line - 18 │ │ line - 19 │ │ line - 20 │ │ line - 21 │ │ line - 22 │ │ line - 23 │ │ line - 24 │ │ line - 25 │ │ line - 26 │ │ line - 27 │ │ line - 28 │ │ line - 29 │ │ line - 30 │ │ line - 31 │ │ line - 32 │ │ line - 33 │ │ line - 34 │ │ line - 35 │ │ line - 36 │ │ line - 37 │ │ line - 38 │ │ line - 39 │ │ line - 40 │ │ line - 41 │ │ line - 42 │ │ line - 43 │ │ line - 44 │ │ line - 45 │ │ line - 46 │ │ line - 47 │ │ line - 48 │ │ line - 49 │ │ line - 50 │ │ line - 51 │ │ line - 52 │ │ line - 53 │ │ line - 54 │ │ line - 55 │ │ line - 56 │ │ line - 57 │ │ line - 58 │ │ line - 59 │ │ line - 60 │ ╰─▶ `; - 61 │ - ╰──── - help: Expected Jest snapshot to be smaller than 50 lines but was 59 lines long diff --git a/crates/oxc_span/src/source_type.rs b/crates/oxc_span/src/source_type.rs index e6988ec36677a..65284e1cb2669 100644 --- a/crates/oxc_span/src/source_type.rs +++ b/crates/oxc_span/src/source_type.rs @@ -71,8 +71,7 @@ impl Default for SourceType { } /// Valid file extensions -pub const VALID_EXTENSIONS: [&str; 9] = - ["js", "mjs", "cjs", "jsx", "ts", "mts", "cts", "tsx", "snap"]; +pub const VALID_EXTENSIONS: [&str; 8] = ["js", "mjs", "cjs", "jsx", "ts", "mts", "cts", "tsx"]; impl SourceType { pub fn is_script(self) -> bool { @@ -189,7 +188,7 @@ impl SourceType { "mts" if file_name.ends_with(".d.mts") => Language::TypeScriptDefinition, "cts" if file_name.ends_with(".d.cts") => Language::TypeScriptDefinition, _ => { - debug_assert!(matches!(extension, "ts" | "mts" | "cts" | "tsx" | "snap")); + debug_assert!(matches!(extension, "ts" | "mts" | "cts" | "tsx")); Language::TypeScript } }; From 8e04a84f73db3a900dbc9027f23a3f61ffc313fb Mon Sep 17 00:00:00 2001 From: wenzhe Date: Sun, 2 Jun 2024 22:49:04 +0800 Subject: [PATCH 6/6] fix: update `get_line_count` method --- crates/oxc_linter/src/rules/jest/no_large_snapshots.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs index 56af1ba6ddf16..d977377eecc04 100644 --- a/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs +++ b/crates/oxc_linter/src/rules/jest/no_large_snapshots.rs @@ -272,12 +272,8 @@ impl NoLargeSnapshots { fn get_line_count(span: Span, ctx: &LintContext) -> usize { let start = span.start as usize; - let start = if start == 0 { 1 } else { start }; let end = span.end as usize; - let end = ctx.source_text()[start..end].lines().count(); - let start = ctx.source_text()[..start].lines().count(); - - end - start + ctx.source_text()[start..=end].lines().count() - 1 } #[allow(clippy::unnecessary_wraps)]