From 23abe152bda3db20ec3896807a445f3a75ac230f Mon Sep 17 00:00:00 2001 From: connorskees Date: Wed, 18 Jan 2023 01:37:59 +0000 Subject: [PATCH] increase code coverage --- .../src/builtin/functions/color/hsl.rs | 2 - .../src/builtin/functions/color/opacity.rs | 1 - crates/compiler/src/builtin/functions/list.rs | 7 +- crates/compiler/src/evaluate/env.rs | 2 +- crates/compiler/src/evaluate/visitor.rs | 32 +++---- crates/compiler/src/lib.rs | 2 +- crates/compiler/src/value/number.rs | 9 +- crates/lib/src/lib.rs | 2 +- crates/lib/tests/color.rs | 68 +++++++++++++++ crates/lib/tests/color_hsl.rs | 83 ++++++++++++++++++- crates/lib/tests/color_hwb.rs | 26 ++++++ crates/lib/tests/debug.rs | 7 ++ crates/lib/tests/forward.rs | 17 ++++ crates/lib/tests/imports.rs | 35 ++++++++ crates/lib/tests/list.rs | 25 ++++++ crates/lib/tests/macros.rs | 13 +++ crates/lib/tests/math.rs | 28 +++++++ crates/lib/tests/meta.rs | 29 +++++++ crates/lib/tests/modulo.rs | 5 ++ crates/lib/tests/plain-css-fn.rs | 10 +++ crates/lib/tests/special-functions.rs | 10 +++ crates/lib/tests/strings.rs | 45 ++++++++++ crates/lib/tests/supports.rs | 20 ++++- crates/lib/tests/use.rs | 62 ++++++++++++++ crates/lib/tests/warn.rs | 7 ++ 25 files changed, 505 insertions(+), 42 deletions(-) diff --git a/crates/compiler/src/builtin/functions/color/hsl.rs b/crates/compiler/src/builtin/functions/color/hsl.rs index d383325..0bed050 100644 --- a/crates/compiler/src/builtin/functions/color/hsl.rs +++ b/crates/compiler/src/builtin/functions/color/hsl.rs @@ -165,8 +165,6 @@ pub(crate) fn adjust_hue(mut args: ArgumentResult, visitor: &mut Visitor) -> Sas .assert_color_with_name("color", args.span())?; let degrees = angle_value(args.get_err(1, "degrees")?, "degrees", args.span())?; - dbg!(degrees); - Ok(Value::Color(Arc::new(color.adjust_hue(degrees)))) } diff --git a/crates/compiler/src/builtin/functions/color/opacity.rs b/crates/compiler/src/builtin/functions/color/opacity.rs index 4e7c79c..9f05ff6 100644 --- a/crates/compiler/src/builtin/functions/color/opacity.rs +++ b/crates/compiler/src/builtin/functions/color/opacity.rs @@ -67,7 +67,6 @@ pub(crate) fn alpha(mut args: ArgumentResult, visitor: &mut Visitor) -> SassResu pub(crate) fn opacity(mut args: ArgumentResult, visitor: &mut Visitor) -> SassResult { args.max_args(1)?; match args.get_err(0, "color")? { - Value::Dimension(SassNumber { num: n, .. }) if n.is_nan() => todo!(), Value::Color(c) => Ok(Value::Dimension(SassNumber::new_unitless(c.alpha()))), Value::Dimension(SassNumber { num, diff --git a/crates/compiler/src/builtin/functions/list.rs b/crates/compiler/src/builtin/functions/list.rs index 2306b20..b10fd6a 100644 --- a/crates/compiler/src/builtin/functions/list.rs +++ b/crates/compiler/src/builtin/functions/list.rs @@ -56,12 +56,7 @@ pub(crate) fn nth(mut args: ArgumentResult, visitor: &mut Visitor) -> SassResult pub(crate) fn list_separator(mut args: ArgumentResult, visitor: &mut Visitor) -> SassResult { args.max_args(1)?; Ok(Value::String( - match args.get_err(0, "list")? { - Value::List(_, sep, ..) => sep.name(), - Value::Map(..) | Value::ArgList(..) => ListSeparator::Comma.name(), - _ => ListSeparator::Space.name(), - } - .to_owned(), + args.get_err(0, "list")?.separator().name().to_owned(), QuoteKind::None, )) } diff --git a/crates/compiler/src/evaluate/env.rs b/crates/compiler/src/evaluate/env.rs index 97e3bb2..d5fbe68 100644 --- a/crates/compiler/src/evaluate/env.rs +++ b/crates/compiler/src/evaluate/env.rs @@ -263,7 +263,7 @@ impl Environment { for name in (*self.scopes.global_variables()).borrow().keys() { if (*module).borrow().var_exists(*name) { return Err(( - format!("This module and the new module both define a variable named \"{name}\".", name = name) + format!("This module and the new module both define a variable named \"${name}\".", name = name) , span).into()); } } diff --git a/crates/compiler/src/evaluate/visitor.rs b/crates/compiler/src/evaluate/visitor.rs index 6d1bb72..48683ff 100644 --- a/crates/compiler/src/evaluate/visitor.rs +++ b/crates/compiler/src/evaluate/visitor.rs @@ -829,13 +829,7 @@ impl<'a> Visitor<'a> { span: Span, ) -> SassResult { if let Some(name) = self.find_import(url.as_ref()) { - // assumption: most users use regular file paths for their imports. - // we do support importing syntactically invalid paths and paths that - // do not exist through the `Options::fs` API, so we fallback to the - // original name if necessary - let canonical = std::fs::canonicalize(&name).unwrap_or_else(|_| name.to_path_buf()); - - if let Some(style_sheet) = self.import_cache.get(&canonical) { + if let Some(style_sheet) = self.import_cache.get(&name) { return Ok(style_sheet.clone()); } @@ -853,10 +847,10 @@ impl<'a> Visitor<'a> { self.flags .set(ContextFlags::IS_USE_ALLOWED, old_is_use_allowed); - if self.files_seen.contains(&canonical) { - self.import_cache.insert(canonical, style_sheet.clone()); + if self.files_seen.contains(&name) { + self.import_cache.insert(name, style_sheet.clone()); } else { - self.files_seen.insert(canonical); + self.files_seen.insert(name); } return Ok(style_sheet); @@ -2079,16 +2073,14 @@ impl<'a> Visitor<'a> { touched: BTreeSet::new(), }) } - v => { - return Err(( - format!( - "Variable keyword arguments must be a map (was {}).", - v.inspect(arguments.span)? - ), - arguments.span, - ) - .into()); - } + v => Err(( + format!( + "Variable keyword arguments must be a map (was {}).", + v.inspect(arguments.span)? + ), + arguments.span, + ) + .into()), } } diff --git a/crates/compiler/src/lib.rs b/crates/compiler/src/lib.rs index 2b44808..f9278b5 100644 --- a/crates/compiler/src/lib.rs +++ b/crates/compiler/src/lib.rs @@ -32,7 +32,7 @@ grass input.scss ``` */ -#![warn(clippy::all, clippy::cargo)] +#![warn(clippy::all, clippy::cargo, clippy::dbg_macro)] #![deny(missing_debug_implementations)] #![allow( clippy::use_self, diff --git a/crates/compiler/src/value/number.rs b/crates/compiler/src/value/number.rs index 6dee36a..637f27b 100644 --- a/crates/compiler/src/value/number.rs +++ b/crates/compiler/src/value/number.rs @@ -2,8 +2,7 @@ use std::{ convert::From, fmt, mem, ops::{ - Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, - SubAssign, + Add, AddAssign, Deref, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign, }, }; @@ -231,12 +230,6 @@ impl Deref for Number { } } -impl DerefMut for Number { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - macro_rules! from_integer { ($ty:ty) => { impl From<$ty> for Number { diff --git a/crates/lib/src/lib.rs b/crates/lib/src/lib.rs index b0df988..c3a42f9 100644 --- a/crates/lib/src/lib.rs +++ b/crates/lib/src/lib.rs @@ -32,7 +32,7 @@ grass input.scss */ #![cfg_attr(doc, feature(doc_cfg))] -#![warn(clippy::all, clippy::cargo)] +#![warn(clippy::all, clippy::cargo, clippy::dbg_macro)] #![deny(missing_debug_implementations)] #![allow( clippy::use_self, diff --git a/crates/lib/tests/color.rs b/crates/lib/tests/color.rs index fe0c722..4e8bfbc 100644 --- a/crates/lib/tests/color.rs +++ b/crates/lib/tests/color.rs @@ -690,7 +690,75 @@ test!( "a {\n color: #0000z;\n}\n", "a {\n color: rgba(0, 0, 0, 0) z;\n}\n" ); +test!( + opacity_nan, + "a {\n color: opacity(0/0);\n}\n", + "a {\n color: opacity(NaN);\n}\n" +); +test!( + change_color_no_change, + "a {\n color: change-color(red);\n}\n", + "a {\n color: red;\n}\n" +); +test!( + change_color_hwb_hue, + "a {\n color: change-color(red, $whiteness: 50%, $hue: 230);\n}\n", + "a {\n color: #8095ff;\n}\n" +); error!( hex_color_starts_with_number_non_hex_digit_at_position_6, "a {\n color: #00000z;\n}\n", "Error: Expected hex digit." ); +error!( + opacity_arg_not_color_or_number, + "a {\n color: opacity(a);\n}\n", "Error: $color: a is not a color." +); +error!( + ie_hex_str_no_args, + "a {\n color: ie-hex-str();\n}\n", "Error: Missing argument $color." +); +error!( + opacify_no_args, + "a {\n color: opacify();\n}\n", "Error: Missing argument $color." +); +error!( + opacify_one_arg, + "a {\n color: opacify(red);\n}\n", "Error: Missing argument $amount." +); +error!( + transparentize_no_args, + "a {\n color: transparentize();\n}\n", "Error: Missing argument $color." +); +error!( + transparentize_one_arg, + "a {\n color: transparentize(red);\n}\n", "Error: Missing argument $amount." +); +error!( + adjust_color_sl_and_wb, + "a {\n color: adjust-color(red, $saturation: 50%, $whiteness: 50%);\n}\n", + "Error: HSL parameters may not be passed along with HWB parameters." +); +error!( + adjust_color_rgb_and_sl, + "a {\n color: adjust-color(red, $red: 50%, $saturation: 50%);\n}\n", + "Error: RGB parameters may not be passed along with HSL parameters." +); +error!( + adjust_color_rgb_and_wb, + "a {\n color: adjust-color(red, $red: 50%, $whiteness: 50%);\n}\n", + "Error: RGB parameters may not be passed along with HWB parameters." +); +error!( + adjust_color_two_unknown_named_args, + "a {\n color: adjust-color(red, $foo: 50%, $bar: 50%);\n}\n", + "Error: No arguments named $foo or $bar." +); +error!( + adjust_color_two_positional_args, + "a {\n color: adjust-color(red, 50%);\n}\n", + "Error: Only one positional argument is allowed. All other arguments must be passed by name." +); +error!( + adjust_color_no_args, + "a {\n color: adjust-color();\n}\n", "Error: Missing argument $color." +); diff --git a/crates/lib/tests/color_hsl.rs b/crates/lib/tests/color_hsl.rs index f88275f..ac36370 100644 --- a/crates/lib/tests/color_hsl.rs +++ b/crates/lib/tests/color_hsl.rs @@ -203,7 +203,7 @@ test!( "a {\n color: 100%;\n}\n" ); test!( - saturate_one_arg, + saturate_one_named_arg, "a {\n color: saturate($amount: 50%);\n}\n", "a {\n color: saturate(50%);\n}\n" ); @@ -356,3 +356,84 @@ test!( "a {\n color: hsl(60rad, 100%, 50%);\n}\n", "a {\n color: hsl(197.7467707849deg, 100%, 50%);\n}\n" ); +error!( + hsl_one_arg_bracketed, + "a {\n color: hsl([1, 2, 3]);\n}\n", + "Error: $channels must be an unbracketed, space-separated list." +); +error!( + hue_arg_not_color, + "a {\n color: hue(1);\n}\n", "Error: $color: 1 is not a color." +); +error!( + saturation_arg_not_color, + "a {\n color: saturation(1);\n}\n", "Error: $color: 1 is not a color." +); +error!( + lightness_arg_not_color, + "a {\n color: lightness(1);\n}\n", "Error: $color: 1 is not a color." +); +error!( + adjust_hue_first_arg_not_color, + "a {\n color: adjust-hue(1, 5deg);\n}\n", "Error: $color: 1 is not a color." +); +error!( + hue_no_args, + "a {\n color: hue();\n}\n", "Error: Missing argument $color." +); +error!( + saturation_no_args, + "a {\n color: saturation();\n}\n", "Error: Missing argument $color." +); +error!( + lightness_no_args, + "a {\n color: lightness();\n}\n", "Error: Missing argument $color." +); +error!( + adjust_hue_no_args, + "a {\n color: adjust-hue();\n}\n", "Error: Missing argument $color." +); +error!( + adjust_hue_one_arg, + "a {\n color: adjust-hue(red);\n}\n", "Error: Missing argument $degrees." +); +error!( + lighten_no_args, + "a {\n color: lighten();\n}\n", "Error: Missing argument $color." +); +error!( + lighten_one_arg, + "a {\n color: lighten(red);\n}\n", "Error: Missing argument $amount." +); +error!( + darken_no_args, + "a {\n color: darken();\n}\n", "Error: Missing argument $color." +); +error!( + darken_one_arg, + "a {\n color: darken(red);\n}\n", "Error: Missing argument $amount." +); +error!( + saturate_single_named_arg_not_amount, + "a {\n color: saturate($a: red);\n}\n", "Error: Missing argument $amount." +); +error!( + saturate_no_args, + "a {\n color: saturate();\n}\n", "Error: Missing argument $amount." +); +error!( + saturate_one_arg, + "a {\n color: saturate(red);\n}\n", "Error: $amount: red is not a number." +); +error!( + desaturate_no_args, + "a {\n color: desaturate();\n}\n", "Error: Missing argument $color." +); +error!( + desaturate_one_arg, + "a {\n color: desaturate(red);\n}\n", "Error: Missing argument $amount." +); +error!( + complement_no_args, + "a {\n color: complement();\n}\n", "Error: Missing argument $color." +); diff --git a/crates/lib/tests/color_hwb.rs b/crates/lib/tests/color_hwb.rs index 10297a8..5928a48 100644 --- a/crates/lib/tests/color_hwb.rs +++ b/crates/lib/tests/color_hwb.rs @@ -11,6 +11,17 @@ test!( "@use \"sass:color\";\na {\n color: color.blackness(white);\n}\n", "a {\n color: 0%;\n}\n" ); + +test!( + whiteness_black, + "@use \"sass:color\";\na {\n color: color.whiteness(black);\n}\n", + "a {\n color: 0%;\n}\n" +); +test!( + whiteness_white, + "@use \"sass:color\";\na {\n color: color.whiteness(white);\n}\n", + "a {\n color: 100%;\n}\n" +); test!( blackness_approx_50_pct, "@use \"sass:color\";\na {\n color: color.blackness(color.hwb(0, 0%, 50%));\n}\n", @@ -111,3 +122,18 @@ error!( "@use \"sass:color\";\na {\n color: color.hwb(0, 30%, 101%, 0.5);\n}\n", "Error: $blackness: Expected 101% to be within 0% and 100%." ); +error!( + blackness_no_args, + "@use \"sass:color\";\na {\n color: color.blackness();\n}\n", + "Error: Missing argument $color." +); +error!( + whiteness_no_args, + "@use \"sass:color\";\na {\n color: color.whiteness();\n}\n", + "Error: Missing argument $color." +); +error!( + hwb_var_channels, + "@use \"sass:color\";\na {\n color: color.hwb(var(--foo));\n}\n", + "Error: Expected numeric channels, got \"hwb(var(--foo))\"." +); diff --git a/crates/lib/tests/debug.rs b/crates/lib/tests/debug.rs index 883bbf9..545667a 100644 --- a/crates/lib/tests/debug.rs +++ b/crates/lib/tests/debug.rs @@ -3,3 +3,10 @@ mod macros; test!(simple_debug, "@debug 2", ""); test!(simple_debug_with_semicolon, "@debug 2;", ""); +test!( + // todo: test stdout + debug_while_quiet, + "@debug 2;", + "", + grass::Options::default().quiet(true) +); diff --git a/crates/lib/tests/forward.rs b/crates/lib/tests/forward.rs index 71bcb9f..86ac00c 100644 --- a/crates/lib/tests/forward.rs +++ b/crates/lib/tests/forward.rs @@ -317,6 +317,23 @@ fn member_as_variable_assignment_toplevel() { ); } +#[test] +fn forward_module_with_error() { + let mut fs = TestFs::new(); + + fs.add_file("_error.scss", r#"a { color: 1 + red; }"#); + + let input = r#" + @forward "error"; + "#; + + assert_err!( + input, + r#"Error: Undefined operation "1 + red"."#, + grass::Options::default().fs(&fs) + ); +} + error!( after_style_rule, r#" diff --git a/crates/lib/tests/imports.rs b/crates/lib/tests/imports.rs index 1a5eedf..67c45c0 100644 --- a/crates/lib/tests/imports.rs +++ b/crates/lib/tests/imports.rs @@ -315,6 +315,41 @@ fn imports_absolute_scss() { ); } +#[test] +fn imports_same_file_twice() { + let mut fs = TestFs::new(); + + fs.add_file("a.scss", r#"a { color: red; }"#); + + let input = r#" + @import "a"; + @import "a"; + "#; + + assert_eq!( + "a {\n color: red;\n}\n\na {\n color: red;\n}\n", + &grass::from_string(input.to_string(), &grass::Options::default().fs(&fs)).expect(input) + ); +} + +#[test] +fn imports_same_file_thrice() { + let mut fs = TestFs::new(); + + fs.add_file("a.scss", r#"a { color: red; }"#); + + let input = r#" + @import "a"; + @import "a"; + @import "a"; + "#; + + assert_eq!( + "a {\n color: red;\n}\n\na {\n color: red;\n}\n\na {\n color: red;\n}\n", + &grass::from_string(input.to_string(), &grass::Options::default().fs(&fs)).expect(input) + ); +} + #[test] fn imports_explicit_file_extension() { let mut fs = TestFs::new(); diff --git a/crates/lib/tests/list.rs b/crates/lib/tests/list.rs index dba507d..7c5a9e1 100644 --- a/crates/lib/tests/list.rs +++ b/crates/lib/tests/list.rs @@ -437,6 +437,31 @@ test!( "a {\n color: a, A, \"Noto Color Emoji\";\n}\n", "a {\n color: a, A, \"Noto Color Emoji\";\n}\n" ); +test!( + list_separator_of_map, + "a {\n color: list-separator((a: b, c: d));\n}\n", + "a {\n color: comma;\n}\n" +); +test!( + list_separator_of_empty_parens, + "a {\n color: list-separator(());\n}\n", + "a {\n color: space;\n}\n" +); +test!( + list_separator_of_unquoted_string, + "a {\n color: list-separator(a);\n}\n", + "a {\n color: space;\n}\n" +); +test!( + list_separator_of_arglist, + "@function foo($a...) { + @return list-separator($a); + } + a { + color: foo(); + }", + "a {\n color: comma;\n}\n" +); test!( list_separator_of_empty_list_after_join, "a { diff --git a/crates/lib/tests/macros.rs b/crates/lib/tests/macros.rs index 1319d4f..105227a 100644 --- a/crates/lib/tests/macros.rs +++ b/crates/lib/tests/macros.rs @@ -112,6 +112,19 @@ macro_rules! assert_err { ), } }; + ($input:expr, $err:expr, $options:expr) => { + match grass::from_string($input.to_string(), &$options) { + Ok(..) => panic!("did not fail"), + Err(e) => assert_eq!( + $err, + e.to_string() + .chars() + .take_while(|c| *c != '\n') + .collect::() + .as_str() + ), + } + }; } /// Suitable for simple import tests. Does not properly implement path resolution -- diff --git a/crates/lib/tests/math.rs b/crates/lib/tests/math.rs index fb0e525..90e23c4 100644 --- a/crates/lib/tests/math.rs +++ b/crates/lib/tests/math.rs @@ -158,3 +158,31 @@ error!( comparable_non_number_arg_last, "a {\n color: comparable(1, b);\n}\n", "Error: $number2: b is not a number." ); +error!( + percentage_no_args, + "a {\n color: percentage();\n}\n", "Error: Missing argument $number." +); +error!( + round_no_args, + "a {\n color: round();\n}\n", "Error: Missing argument $number." +); +error!( + ceil_no_args, + "a {\n color: ceil();\n}\n", "Error: Missing argument $number." +); +error!( + floor_no_args, + "a {\n color: floor();\n}\n", "Error: Missing argument $number." +); +error!( + abs_no_args, + "a {\n color: abs();\n}\n", "Error: Missing argument $number." +); +error!( + comparable_no_args, + "a {\n color: comparable();\n}\n", "Error: Missing argument $number1." +); +error!( + comparable_one_arg, + "a {\n color: comparable(1);\n}\n", "Error: Missing argument $number2." +); diff --git a/crates/lib/tests/meta.rs b/crates/lib/tests/meta.rs index bf9a676..48f16da 100644 --- a/crates/lib/tests/meta.rs +++ b/crates/lib/tests/meta.rs @@ -26,6 +26,23 @@ test!( "a {\n color: if(false, 1, 2);\n}\n", "a {\n color: 2;\n}\n" ); +test!( + if_is_global_fn, + "a { + $a: get-function(if); + color: call($a, true, 2, 3); + color: call($a, false, 2, 3); + }", + "a {\n color: 2;\n color: 3;\n}\n" +); +error!( + if_inside_call_does_not_lazily_eval_args, + "a { + $a: get-function(if); + color: call($a, true, 2, red % 5); + }", + "Error: Undefined operation \"red % 5\"." +); test!( feature_exists_dbl_quoted, "a {\n color: feature-exists(\"at-error\")\n}\n", @@ -359,5 +376,17 @@ test!( }", "a {\n color: get-function(\"empty\");\n}\n" ); +error!( + feature_exists_no_args, + "a {\n color: feature-exists();\n}\n", "Error: Missing argument $feature." +); +error!( + unit_no_args, + "a {\n color: unit();\n}\n", "Error: Missing argument $number." +); +error!( + unitless_no_args, + "a {\n color: unitless();\n}\n", "Error: Missing argument $number." +); // todo: if() with different combinations of named and positional args diff --git a/crates/lib/tests/modulo.rs b/crates/lib/tests/modulo.rs index 55f92a3..3c42530 100644 --- a/crates/lib/tests/modulo.rs +++ b/crates/lib/tests/modulo.rs @@ -175,6 +175,11 @@ test!( "a {\n color: -5 % (-1/0);\n}\n", "a {\n color: NaN;\n}\n" ); +test!( + zero_mod_negative, + "a {\n color: 0 % -5;\n}\n", + "a {\n color: 0;\n}\n" +); error!( calculation_mod_calculation, "a {\n color: calc(1rem + 1px) % calc(1rem + 1px);\n}\n", diff --git a/crates/lib/tests/plain-css-fn.rs b/crates/lib/tests/plain-css-fn.rs index 437ac06..351f1d8 100644 --- a/crates/lib/tests/plain-css-fn.rs +++ b/crates/lib/tests/plain-css-fn.rs @@ -81,6 +81,16 @@ test!( "a {\n color: or(foo);\n}\n", "a {\n color: or(foo);\n}\n" ); +test!( + rest_arg, + "a { + color: foo(red...); + color: foo(a, red...); + color: f#{o}o(red...); + color: f#{o}o(a, red...); + }", + "a {\n color: foo(red);\n color: foo(a, red);\n color: foo(red);\n color: foo(a, red);\n}\n" +); error!( denies_keyword_arguments_to_interpolated_function, "a {\n color: f#{o}o($a: red);\n}\n", diff --git a/crates/lib/tests/special-functions.rs b/crates/lib/tests/special-functions.rs index a7db4cf..e6a0159 100644 --- a/crates/lib/tests/special-functions.rs +++ b/crates/lib/tests/special-functions.rs @@ -251,6 +251,16 @@ test!( "a {\n color: calc(1% + 3px - 2px);\n}\n", "a {\n color: calc(1% + 3px - 2px);\n}\n" ); +test!( + inspect_calc, + "a {\n color: inspect(calc(1% + 3px - 2px));\n}\n", + "a {\n color: calc(1% + 3px - 2px);\n}\n" +); +test!( + calc_ne_number, + "a {\n color: calc(1% + 3px - 2px) == 1px;\n}\n", + "a {\n color: false;\n}\n" +); test!( calc_num_plus_interpolation, "a {\n color: calc(1 + #{c});\n}\n", diff --git a/crates/lib/tests/strings.rs b/crates/lib/tests/strings.rs index bdc00ee..259cb0b 100644 --- a/crates/lib/tests/strings.rs +++ b/crates/lib/tests/strings.rs @@ -254,3 +254,48 @@ test!( "a {\n color: str-index(\"c\\0308 a\", \"a\");\n}\n", "a {\n color: 3;\n}\n" ); +error!( + to_lower_case_no_args, + "a {\n color: to_lower_case();\n}\n", "Error: Missing argument $string." +); +error!( + str_length_no_args, + "a {\n color: str_length();\n}\n", "Error: Missing argument $string." +); +error!( + quote_no_args, + "a {\n color: quote();\n}\n", "Error: Missing argument $string." +); +error!( + unquote_no_args, + "a {\n color: unquote();\n}\n", "Error: Missing argument $string." +); +error!( + str_slice_no_args, + "a {\n color: str_slice();\n}\n", "Error: Missing argument $string." +); +error!( + str_index_no_args, + "a {\n color: str_index();\n}\n", "Error: Missing argument $string." +); +error!( + str_insert_no_args, + "a {\n color: str_insert();\n}\n", "Error: Missing argument $string." +); +test!( + unique_id_is_unique, + "$init: unique-id(); + @for $_ from 0 to 100 { + @if $init == unique-id() { + @error 'got duplicate unique id: #{$init}'; + } + }", + "" +); +test!( + unique_id_is_valid_identifier, + "@for $_ from 0 to 100 { + #{unique-id()} {} + }", + "" +); diff --git a/crates/lib/tests/supports.rs b/crates/lib/tests/supports.rs index 44072f6..a97b5e9 100644 --- a/crates/lib/tests/supports.rs +++ b/crates/lib/tests/supports.rs @@ -138,7 +138,7 @@ test!( ); test!(supports_empty_body, "@supports (a: b) {}", ""); test!( - does_not_simplify_calculation_in_args, + calculation_not_in_declaration, "@supports (calc(1 + 1)) { a { color: red; @@ -146,6 +146,24 @@ test!( }", "@supports (calc(1 + 1)) {\n a {\n color: red;\n }\n}\n" ); +test!( + ident_addition_on_rhs_of_declaration, + "@supports (a: a + b) { + a { + color: red; + } + }", + "@supports (a: ab) {\n a {\n color: red;\n }\n}\n" +); +test!( + calculation_on_rhs_of_declaration, + "@supports (a: calc(1px + 1px)) { + a { + color: red; + } + }", + "@supports (a: calc(1px + 1px)) {\n a {\n color: red;\n }\n}\n" +); error!( supports_inside_declaration_body, "@mixin foo() { diff --git a/crates/lib/tests/use.rs b/crates/lib/tests/use.rs index f40d96c..6b26b8d 100644 --- a/crates/lib/tests/use.rs +++ b/crates/lib/tests/use.rs @@ -640,4 +640,66 @@ fn module_functions_through_forward() { ); } +#[test] +fn use_variable_declared_in_this_and_other_module() { + let mut fs = TestFs::new(); + + fs.add_file( + "_a.scss", + r#" + $a: blue; + "#, + ); + + let input = r#" + $a: red; + @use "a" as *; + + a { + color: $a; + } + "#; + + assert_err!( + input, + "Error: This module and the new module both define a variable named \"$a\".", + grass::Options::default().fs(&fs) + ); +} + +#[test] +#[ignore = "we don't check for this"] +fn use_variable_declared_in_two_modules() { + let mut fs = TestFs::new(); + + fs.add_file( + "_a.scss", + r#" + $a: blue; + "#, + ); + + fs.add_file( + "_b.scss", + r#" + $a: red; + "#, + ); + + let input = r#" + @use "a" as *; + @use "b" as *; + + a { + color: $a; + } + "#; + + assert_err!( + input, + "Error: This variable is available from multiple global modules.", + grass::Options::default().fs(&fs) + ); +} + // todo: refactor these tests to use testfs where possible diff --git a/crates/lib/tests/warn.rs b/crates/lib/tests/warn.rs index 973fb96..41b4254 100644 --- a/crates/lib/tests/warn.rs +++ b/crates/lib/tests/warn.rs @@ -2,3 +2,10 @@ mod macros; test!(simple_warn, "@warn 2", ""); +test!( + // todo: test stdout + warn_while_quiet, + "@warn 2;", + "", + grass::Options::default().quiet(true) +);