increase code coverage
This commit is contained in:
parent
ef7d188062
commit
23abe152bd
@ -165,8 +165,6 @@ pub(crate) fn adjust_hue(mut args: ArgumentResult, visitor: &mut Visitor) -> Sas
|
|||||||
.assert_color_with_name("color", args.span())?;
|
.assert_color_with_name("color", args.span())?;
|
||||||
let degrees = angle_value(args.get_err(1, "degrees")?, "degrees", 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))))
|
Ok(Value::Color(Arc::new(color.adjust_hue(degrees))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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<Value> {
|
pub(crate) fn opacity(mut args: ArgumentResult, visitor: &mut Visitor) -> SassResult<Value> {
|
||||||
args.max_args(1)?;
|
args.max_args(1)?;
|
||||||
match args.get_err(0, "color")? {
|
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::Color(c) => Ok(Value::Dimension(SassNumber::new_unitless(c.alpha()))),
|
||||||
Value::Dimension(SassNumber {
|
Value::Dimension(SassNumber {
|
||||||
num,
|
num,
|
||||||
|
@ -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<Value> {
|
pub(crate) fn list_separator(mut args: ArgumentResult, visitor: &mut Visitor) -> SassResult<Value> {
|
||||||
args.max_args(1)?;
|
args.max_args(1)?;
|
||||||
Ok(Value::String(
|
Ok(Value::String(
|
||||||
match args.get_err(0, "list")? {
|
args.get_err(0, "list")?.separator().name().to_owned(),
|
||||||
Value::List(_, sep, ..) => sep.name(),
|
|
||||||
Value::Map(..) | Value::ArgList(..) => ListSeparator::Comma.name(),
|
|
||||||
_ => ListSeparator::Space.name(),
|
|
||||||
}
|
|
||||||
.to_owned(),
|
|
||||||
QuoteKind::None,
|
QuoteKind::None,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,7 @@ impl Environment {
|
|||||||
for name in (*self.scopes.global_variables()).borrow().keys() {
|
for name in (*self.scopes.global_variables()).borrow().keys() {
|
||||||
if (*module).borrow().var_exists(*name) {
|
if (*module).borrow().var_exists(*name) {
|
||||||
return Err((
|
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());
|
, span).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -829,13 +829,7 @@ impl<'a> Visitor<'a> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> SassResult<StyleSheet> {
|
) -> SassResult<StyleSheet> {
|
||||||
if let Some(name) = self.find_import(url.as_ref()) {
|
if let Some(name) = self.find_import(url.as_ref()) {
|
||||||
// assumption: most users use regular file paths for their imports.
|
if let Some(style_sheet) = self.import_cache.get(&name) {
|
||||||
// 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) {
|
|
||||||
return Ok(style_sheet.clone());
|
return Ok(style_sheet.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -853,10 +847,10 @@ impl<'a> Visitor<'a> {
|
|||||||
self.flags
|
self.flags
|
||||||
.set(ContextFlags::IS_USE_ALLOWED, old_is_use_allowed);
|
.set(ContextFlags::IS_USE_ALLOWED, old_is_use_allowed);
|
||||||
|
|
||||||
if self.files_seen.contains(&canonical) {
|
if self.files_seen.contains(&name) {
|
||||||
self.import_cache.insert(canonical, style_sheet.clone());
|
self.import_cache.insert(name, style_sheet.clone());
|
||||||
} else {
|
} else {
|
||||||
self.files_seen.insert(canonical);
|
self.files_seen.insert(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(style_sheet);
|
return Ok(style_sheet);
|
||||||
@ -2079,16 +2073,14 @@ impl<'a> Visitor<'a> {
|
|||||||
touched: BTreeSet::new(),
|
touched: BTreeSet::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
v => {
|
v => Err((
|
||||||
return Err((
|
|
||||||
format!(
|
format!(
|
||||||
"Variable keyword arguments must be a map (was {}).",
|
"Variable keyword arguments must be a map (was {}).",
|
||||||
v.inspect(arguments.span)?
|
v.inspect(arguments.span)?
|
||||||
),
|
),
|
||||||
arguments.span,
|
arguments.span,
|
||||||
)
|
)
|
||||||
.into());
|
.into()),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ grass input.scss
|
|||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#![warn(clippy::all, clippy::cargo)]
|
#![warn(clippy::all, clippy::cargo, clippy::dbg_macro)]
|
||||||
#![deny(missing_debug_implementations)]
|
#![deny(missing_debug_implementations)]
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::use_self,
|
clippy::use_self,
|
||||||
|
@ -2,8 +2,7 @@ use std::{
|
|||||||
convert::From,
|
convert::From,
|
||||||
fmt, mem,
|
fmt, mem,
|
||||||
ops::{
|
ops::{
|
||||||
Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub,
|
Add, AddAssign, Deref, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
|
||||||
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 {
|
macro_rules! from_integer {
|
||||||
($ty:ty) => {
|
($ty:ty) => {
|
||||||
impl From<$ty> for Number {
|
impl From<$ty> for Number {
|
||||||
|
@ -32,7 +32,7 @@ grass input.scss
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#![cfg_attr(doc, feature(doc_cfg))]
|
#![cfg_attr(doc, feature(doc_cfg))]
|
||||||
#![warn(clippy::all, clippy::cargo)]
|
#![warn(clippy::all, clippy::cargo, clippy::dbg_macro)]
|
||||||
#![deny(missing_debug_implementations)]
|
#![deny(missing_debug_implementations)]
|
||||||
#![allow(
|
#![allow(
|
||||||
clippy::use_self,
|
clippy::use_self,
|
||||||
|
@ -690,7 +690,75 @@ test!(
|
|||||||
"a {\n color: #0000z;\n}\n",
|
"a {\n color: #0000z;\n}\n",
|
||||||
"a {\n color: rgba(0, 0, 0, 0) z;\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!(
|
error!(
|
||||||
hex_color_starts_with_number_non_hex_digit_at_position_6,
|
hex_color_starts_with_number_non_hex_digit_at_position_6,
|
||||||
"a {\n color: #00000z;\n}\n", "Error: Expected hex digit."
|
"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."
|
||||||
|
);
|
||||||
|
@ -203,7 +203,7 @@ test!(
|
|||||||
"a {\n color: 100%;\n}\n"
|
"a {\n color: 100%;\n}\n"
|
||||||
);
|
);
|
||||||
test!(
|
test!(
|
||||||
saturate_one_arg,
|
saturate_one_named_arg,
|
||||||
"a {\n color: saturate($amount: 50%);\n}\n",
|
"a {\n color: saturate($amount: 50%);\n}\n",
|
||||||
"a {\n color: saturate(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(60rad, 100%, 50%);\n}\n",
|
||||||
"a {\n color: hsl(197.7467707849deg, 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."
|
||||||
|
);
|
||||||
|
@ -11,6 +11,17 @@ test!(
|
|||||||
"@use \"sass:color\";\na {\n color: color.blackness(white);\n}\n",
|
"@use \"sass:color\";\na {\n color: color.blackness(white);\n}\n",
|
||||||
"a {\n color: 0%;\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!(
|
test!(
|
||||||
blackness_approx_50_pct,
|
blackness_approx_50_pct,
|
||||||
"@use \"sass:color\";\na {\n color: color.blackness(color.hwb(0, 0%, 50%));\n}\n",
|
"@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",
|
"@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: 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))\"."
|
||||||
|
);
|
||||||
|
@ -3,3 +3,10 @@ mod macros;
|
|||||||
|
|
||||||
test!(simple_debug, "@debug 2", "");
|
test!(simple_debug, "@debug 2", "");
|
||||||
test!(simple_debug_with_semicolon, "@debug 2;", "");
|
test!(simple_debug_with_semicolon, "@debug 2;", "");
|
||||||
|
test!(
|
||||||
|
// todo: test stdout
|
||||||
|
debug_while_quiet,
|
||||||
|
"@debug 2;",
|
||||||
|
"",
|
||||||
|
grass::Options::default().quiet(true)
|
||||||
|
);
|
||||||
|
@ -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!(
|
error!(
|
||||||
after_style_rule,
|
after_style_rule,
|
||||||
r#"
|
r#"
|
||||||
|
@ -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]
|
#[test]
|
||||||
fn imports_explicit_file_extension() {
|
fn imports_explicit_file_extension() {
|
||||||
let mut fs = TestFs::new();
|
let mut fs = TestFs::new();
|
||||||
|
@ -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",
|
||||||
"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!(
|
test!(
|
||||||
list_separator_of_empty_list_after_join,
|
list_separator_of_empty_list_after_join,
|
||||||
"a {
|
"a {
|
||||||
|
@ -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::<String>()
|
||||||
|
.as_str()
|
||||||
|
),
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Suitable for simple import tests. Does not properly implement path resolution --
|
/// Suitable for simple import tests. Does not properly implement path resolution --
|
||||||
|
@ -158,3 +158,31 @@ error!(
|
|||||||
comparable_non_number_arg_last,
|
comparable_non_number_arg_last,
|
||||||
"a {\n color: comparable(1, b);\n}\n", "Error: $number2: b is not a number."
|
"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."
|
||||||
|
);
|
||||||
|
@ -26,6 +26,23 @@ test!(
|
|||||||
"a {\n color: if(false, 1, 2);\n}\n",
|
"a {\n color: if(false, 1, 2);\n}\n",
|
||||||
"a {\n color: 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!(
|
test!(
|
||||||
feature_exists_dbl_quoted,
|
feature_exists_dbl_quoted,
|
||||||
"a {\n color: feature-exists(\"at-error\")\n}\n",
|
"a {\n color: feature-exists(\"at-error\")\n}\n",
|
||||||
@ -359,5 +376,17 @@ test!(
|
|||||||
}",
|
}",
|
||||||
"a {\n color: get-function(\"empty\");\n}\n"
|
"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
|
// todo: if() with different combinations of named and positional args
|
||||||
|
@ -175,6 +175,11 @@ test!(
|
|||||||
"a {\n color: -5 % (-1/0);\n}\n",
|
"a {\n color: -5 % (-1/0);\n}\n",
|
||||||
"a {\n color: NaN;\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!(
|
error!(
|
||||||
calculation_mod_calculation,
|
calculation_mod_calculation,
|
||||||
"a {\n color: calc(1rem + 1px) % calc(1rem + 1px);\n}\n",
|
"a {\n color: calc(1rem + 1px) % calc(1rem + 1px);\n}\n",
|
||||||
|
@ -81,6 +81,16 @@ test!(
|
|||||||
"a {\n color: or(foo);\n}\n",
|
"a {\n color: or(foo);\n}\n",
|
||||||
"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!(
|
error!(
|
||||||
denies_keyword_arguments_to_interpolated_function,
|
denies_keyword_arguments_to_interpolated_function,
|
||||||
"a {\n color: f#{o}o($a: red);\n}\n",
|
"a {\n color: f#{o}o($a: red);\n}\n",
|
||||||
|
@ -251,6 +251,16 @@ test!(
|
|||||||
"a {\n color: calc(1% + 3px - 2px);\n}\n",
|
"a {\n color: calc(1% + 3px - 2px);\n}\n",
|
||||||
"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!(
|
test!(
|
||||||
calc_num_plus_interpolation,
|
calc_num_plus_interpolation,
|
||||||
"a {\n color: calc(1 + #{c});\n}\n",
|
"a {\n color: calc(1 + #{c});\n}\n",
|
||||||
|
@ -254,3 +254,48 @@ test!(
|
|||||||
"a {\n color: str-index(\"c\\0308 a\", \"a\");\n}\n",
|
"a {\n color: str-index(\"c\\0308 a\", \"a\");\n}\n",
|
||||||
"a {\n color: 3;\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()} {}
|
||||||
|
}",
|
||||||
|
""
|
||||||
|
);
|
||||||
|
@ -138,7 +138,7 @@ test!(
|
|||||||
);
|
);
|
||||||
test!(supports_empty_body, "@supports (a: b) {}", "");
|
test!(supports_empty_body, "@supports (a: b) {}", "");
|
||||||
test!(
|
test!(
|
||||||
does_not_simplify_calculation_in_args,
|
calculation_not_in_declaration,
|
||||||
"@supports (calc(1 + 1)) {
|
"@supports (calc(1 + 1)) {
|
||||||
a {
|
a {
|
||||||
color: red;
|
color: red;
|
||||||
@ -146,6 +146,24 @@ test!(
|
|||||||
}",
|
}",
|
||||||
"@supports (calc(1 + 1)) {\n a {\n color: red;\n }\n}\n"
|
"@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!(
|
error!(
|
||||||
supports_inside_declaration_body,
|
supports_inside_declaration_body,
|
||||||
"@mixin foo() {
|
"@mixin foo() {
|
||||||
|
@ -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
|
// todo: refactor these tests to use testfs where possible
|
||||||
|
@ -2,3 +2,10 @@
|
|||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
test!(simple_warn, "@warn 2", "");
|
test!(simple_warn, "@warn 2", "");
|
||||||
|
test!(
|
||||||
|
// todo: test stdout
|
||||||
|
warn_while_quiet,
|
||||||
|
"@warn 2;",
|
||||||
|
"",
|
||||||
|
grass::Options::default().quiet(true)
|
||||||
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user