From b8bacbde8b2ea612bbd79f0621e6847acf731846 Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Sat, 1 Feb 2020 23:09:22 -0500 Subject: [PATCH] Refactor tests into separate files --- tests/comments.rs | 55 +++ tests/functions.rs | 30 ++ tests/imports.rs | 31 ++ tests/interpolation.rs | 15 + tests/macros.rs | 33 ++ tests/main.rs | 876 ----------------------------------------- tests/misc.rs | 30 ++ tests/mixins.rs | 166 ++++++++ tests/selectors.rs | 234 +++++++++++ tests/styles.rs | 127 ++++++ tests/units.rs | 11 + tests/values.rs | 51 +++ tests/variables.rs | 100 +++++ 13 files changed, 883 insertions(+), 876 deletions(-) create mode 100644 tests/comments.rs create mode 100644 tests/functions.rs create mode 100644 tests/imports.rs create mode 100644 tests/interpolation.rs create mode 100644 tests/macros.rs delete mode 100644 tests/main.rs create mode 100644 tests/misc.rs create mode 100644 tests/mixins.rs create mode 100644 tests/selectors.rs create mode 100644 tests/styles.rs create mode 100644 tests/units.rs create mode 100644 tests/values.rs create mode 100644 tests/variables.rs diff --git a/tests/comments.rs b/tests/comments.rs new file mode 100644 index 0000000..f09729a --- /dev/null +++ b/tests/comments.rs @@ -0,0 +1,55 @@ +#![cfg(test)] + +#[macro_use] +mod macros; + +test!( + removes_inner_comments, + "a {\n color: red/* hi */;\n}\n", + "a {\n color: red;\n}\n" +); +test!( + removes_inner_comments_whitespace, + "a {\n color: red /* hi */;\n}\n", + "a {\n color: red;\n}\n" +); +test!( + preserves_outer_comments_before, + "a {\n /* hi */\n color: red;\n}\n" +); +test!( + preserves_outer_comments_after, + "a {\n color: red;\n /* hi */\n}\n" +); +test!( + preserves_outer_comments_two, + "a {\n /* foo */\n /* bar */\n color: red;\n}\n" +); +test!( + preserves_toplevel_comment_before, + "/* foo */\na {\n color: red;\n}\n" +); +test!( + preserves_toplevel_comment_after, + "a {\n color: red;\n}\n/* foo */\n" +); +test!( + removes_single_line_comment, + "// a { color: red }\na {\n height: 1 1px;\n}\n", + "a {\n height: 1 1px;\n}\n" +); +test!( + converts_form_feed_in_comment, + "a {\n /* \x0C*/ color: red;\n}\n", + "a {\n /* \n*/\n color: red;\n}\n" +); +test!( + converts_crlf_in_comment, + "a {\n /* \r\n*/ color: red;\n}\n", + "a {\n /* \n*/\n color: red;\n}\n" +); +test!( + converts_cr_in_comment, + "a {\n /* \r*/ color: red;\n}\n", + "a {\n /* \n*/\n color: red;\n}\n" +); diff --git a/tests/functions.rs b/tests/functions.rs new file mode 100644 index 0000000..8b713b4 --- /dev/null +++ b/tests/functions.rs @@ -0,0 +1,30 @@ +#![cfg(test)] + +#[macro_use] +mod macros; + +test!( + return_num, + "@function a() {\n @return 1;\n}\n\nb {\ncolor: a();\n}\n", + "b {\n color: 1;\n}\n" +); +test!( + return_spaced_list, + "@function a() {\n @return a b;\n}\n\nb {\ncolor: a();\n}\n", + "b {\n color: a b;\n}\n" +); +test!( + single_arg, + "@function a($c) {\n @return $c;\n}\n\nb {\ncolor: a(1);\n}\n", + "b {\n color: 1;\n}\n" +); +test!( + return_variable, + "@function a($a) {\n @return $a;\n}\n\nb {\ncolor: a(1);\n}\n", + "b {\n color: 1;\n}\n" +); +// test!( +// return_no_semicolon, +// "@function a() {\n @return 1\n}\n\nb {\ncolor: a();\n}\n", +// "b {\n color: 1;\n}\n" +// ); diff --git a/tests/imports.rs b/tests/imports.rs new file mode 100644 index 0000000..0778abc --- /dev/null +++ b/tests/imports.rs @@ -0,0 +1,31 @@ +use std::io::Write; +use tempfile::Builder; + +use grass::StyleSheet; + +macro_rules! test_import { + ($func:ident, $input:literal => $output:literal | $( $name:literal($content:literal) ),*) => { + #[test] + fn $func() { + $( + let mut f = Builder::new().rand_bytes(0).prefix("").suffix($name).tempfile_in("").unwrap(); + write!(f, $content).unwrap(); + )* + let mut buf = Vec::new(); + StyleSheet::new($input) + .expect(concat!("failed to parse in ")) + .print_as_css(&mut buf) + .expect(concat!("failed to pretty print on ", $input)); + assert_eq!( + String::from($output), + String::from_utf8(buf).expect("produced invalid utf8") + ); + } + } +} + +// we have to use test name as filename because tests are run multithreaded in the same directory, so some names may conflict +test_import!(imports_variable, "@import \"imports_variable\";\na {\n color: $a;\n}" => "a {\n color: red;\n}\n" | "imports_variable"("$a: red;")); +test_import!(single_quotes_import, "@import 'single_quotes_import';\na {\n color: $a;\n}" => "a {\n color: red;\n}\n" | "single_quotes_import"("$a: red;")); +test_import!(finds_name_scss, "@import \"finds_name_scss\";\na {\n color: $a;\n}" => "a {\n color: red;\n}\n" | "finds_name_scss.scss"("$a: red;")); +test_import!(finds_underscore_name_scss, "@import \"finds_underscore_name_scss\";\na {\n color: $a;\n}" => "a {\n color: red;\n}\n" | "_finds_underscore_name_scss.scss"("$a: red;")); diff --git a/tests/interpolation.rs b/tests/interpolation.rs new file mode 100644 index 0000000..b172e26 --- /dev/null +++ b/tests/interpolation.rs @@ -0,0 +1,15 @@ +#![cfg(test)] + +#[macro_use] +mod macros; + +test!( + removes_double_quotes, + "a {\n color: #{\"red\"};\n}\n", + "a {\n color: red;\n}\n" +); +test!( + removes_single_quotes, + "a {\n color: #{'red'};\n}\n", + "a {\n color: red;\n}\n" +); diff --git a/tests/macros.rs b/tests/macros.rs new file mode 100644 index 0000000..54c6b43 --- /dev/null +++ b/tests/macros.rs @@ -0,0 +1,33 @@ +#![cfg(test)] + +#[allow(unused_macros)] +macro_rules! test { + ($func:ident, $input:literal) => { + #[test] + fn $func() { + let mut buf = Vec::new(); + grass::StyleSheet::new($input) + .expect(concat!("failed to parse on ", $input)) + .print_as_css(&mut buf) + .expect(concat!("failed to pretty print on ", $input)); + assert_eq!( + String::from($input), + String::from_utf8(buf).expect("produced invalid utf8") + ); + } + }; + ($func:ident, $input:literal, $output:literal) => { + #[test] + fn $func() { + let mut buf = Vec::new(); + grass::StyleSheet::new($input) + .expect(concat!("failed to parse on ", $input)) + .print_as_css(&mut buf) + .expect(concat!("failed to pretty print on ", $input)); + assert_eq!( + String::from($output), + String::from_utf8(buf).expect("produced invalid utf8") + ); + } + }; +} \ No newline at end of file diff --git a/tests/main.rs b/tests/main.rs deleted file mode 100644 index 28c896b..0000000 --- a/tests/main.rs +++ /dev/null @@ -1,876 +0,0 @@ -#![cfg(test)] - -use grass::StyleSheet; - -macro_rules! test { - ($func:ident, $input:literal) => { - #[test] - fn $func() { - let mut buf = Vec::new(); - StyleSheet::new($input) - .expect(concat!("failed to parse on ", $input)) - .print_as_css(&mut buf) - .expect(concat!("failed to pretty print on ", $input)); - assert_eq!( - String::from($input), - String::from_utf8(buf).expect("produced invalid utf8") - ); - } - }; - ($func:ident, $input:literal, $output:literal) => { - #[test] - fn $func() { - let mut buf = Vec::new(); - StyleSheet::new($input) - .expect(concat!("failed to parse on ", $input)) - .print_as_css(&mut buf) - .expect(concat!("failed to pretty print on ", $input)); - assert_eq!( - String::from($output), - String::from_utf8(buf).expect("produced invalid utf8") - ); - } - }; -} - -mod test_variables { - use super::*; - test!( - basic_variable, - "$height: 1px;\na {\n height: $height;\n}\n", - "a {\n height: 1px;\n}\n" - ); - test!( - variable_redeclaration, - "$a: 1px;\n$a: 2px;\na {\n height: $a;\n}\n", - "a {\n height: 2px;\n}\n" - ); - test!( - variable_shadowing, - "$a: 1px;\n$b: $a;\na {\n height: $b;\n}\n", - "a {\n height: 1px;\n}\n" - ); - test!( - variable_shadowing_val_does_not_change, - "$a: 1px;\n$b: $a; $a: 2px;\na {\n height: $b;\n}\n", - "a {\n height: 1px;\n}\n" - ); - test!( - variable_shadowing_val_does_not_change_complex, - "a {\n color: red;\n}\n$y: before;\n$x: 1 2 $y;\n$y: after;\nfoo {\n a: $x;\n}", - "a {\n color: red;\n}\n\nfoo {\n a: 1 2 before;\n}\n" - ); - test!( - variable_whitespace, - "$a : 1px ;\na {\n height: $a;\n}\n", - "a {\n height: 1px;\n}\n" - ); - test!( - style_after_variable, - "$a: 1px;\na {\n height: $a;\n color: red;\n}\n", - "a {\n height: 1px;\n color: red;\n}\n" - ); - test!( - literal_and_variable_as_val, - "$a: 1px;\na {\n height: 1 $a;\n}\n", - "a {\n height: 1 1px;\n}\n" - ); - test!( - literal_and_variable_as_var, - "$a: 1px;\n$b: 1 $a;\na {\n height: $b;\n}\n", - "a {\n height: 1 1px;\n}\n" - ); - test!( - eats_whitespace_after_variable_value, - "a {\n b {\n $c: red;\n }\n color: red;\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - variable_changes_through_new_ruleset, - "a {\n $c: red;\nb {\n $c: blue;\n }\n color: $c;\n}\n", - "a {\n color: blue;\n}\n" - ); - test!( - nested_interpolation, - "$a: red; a {\n color: #{#{$a}};\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - numbers_in_variable, - "$var1: red; a {\n color: $var1;\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - default_var_after, - "$a: red;\n$a: blue !default;\na {\n color: $a;\n}", - "a {\n color: red;\n}\n" - ); - test!( - default_var_before, - "$a: red !default;\n$a: blue;\na {\n color: $a;\n}", - "a {\n color: blue;\n}\n" - ); - test!( - default_var_whitespace, - "$a: red !default ;\na {\n color: $a;\n}", - "a {\n color: red;\n}\n" - ); - test!( - default_var_inside_rule, - "a {\n $a: red;\n $a: blue !default;\n color: $a;\n}", - "a {\n color: red;\n}\n" - ); - test!( - interpolation_in_variable, - "$a: #{red};\na {\n color: $a\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - variable_decl_doesnt_end_in_semicolon, - "a {\n $a: red\n}\n\nb {\n color: blue;\n}\n", - "b {\n color: blue;\n}\n" - ); -} - -mod test_selectors { - use super::StyleSheet; - test!( - selector_nesting_el_mul_el, - "a, b {\n a, b {\n color: red\n}\n}\n", - "a a, a b, b a, b b {\n color: red;\n}\n" - ); - test!(selector_element, "a {\n color: red;\n}\n"); - test!(selector_id, "#id {\n color: red;\n}\n"); - test!(selector_class, ".class {\n color: red;\n}\n"); - test!(selector_el_descendant, "a a {\n color: red;\n}\n"); - test!(selector_universal, "* {\n color: red;\n}\n"); - test!(selector_el_class_and, "a.class {\n color: red;\n}\n"); - test!(selector_el_id_and, "a#class {\n color: red;\n}\n"); - test!( - selector_el_class_descendant, - "a .class {\n color: red;\n}\n" - ); - test!(selector_el_id_descendant, "a #class {\n color: red;\n}\n"); - test!( - selector_el_universal_descendant, - "a * {\n color: red;\n}\n" - ); - test!( - selector_universal_el_descendant, - "* a {\n color: red;\n}\n" - ); - - test!(selector_attribute_any, "[attr] {\n color: red;\n}\n"); - test!( - selector_attribute_any_lower_case_insensitive, - "[attr=val i] {\n color: red;\n}\n" - ); - test!( - selector_attribute_any_upper_case_insensitive, - "[attr=val I] {\n color: red;\n}\n" - ); - test!( - selector_attribute_arbitrary_modifier, - "[attr=val c] {\n color: red;\n}\n" - ); - test!( - selector_attribute_i_in_attr, - "[atitr=val] {\n color: red;\n}\n" - ); - test!( - selector_attribute_i_in_val, - "[attr=vail] {\n color: red;\n}\n" - ); - test!( - selector_attribute_whitespace, - "[attr *= val ] {\n color: red;\n}\n", - "[attr*=val] {\n color: red;\n}\n" - ); - test!( - selector_attribute_equals, - "[attr=val] {\n color: red;\n}\n" - ); - test!( - selector_attribute_single_quotes, - "[attr='val'] {\n color: red;\n}\n" - ); - test!( - selector_attribute_double_quotes, - "[attr=\"val\"] {\n color: red;\n}\n" - ); - test!(selector_attribute_in, "[attr~=val] {\n color: red;\n}\n"); - test!( - selector_attribute_begins_hyphen_or_exact, - "[attr|=val] {\n color: red;\n}\n" - ); - test!( - selector_attribute_starts_with, - "[attr^=val] {\n color: red;\n}\n" - ); - test!( - selector_attribute_ends_with, - "[attr$=val] {\n color: red;\n}\n" - ); - test!( - selector_attribute_contains, - "[attr*=val] {\n color: red;\n}\n" - ); - test!(selector_el_attribute_and, "a[attr] {\n color: red;\n}\n"); - test!( - selector_el_attribute_descendant, - "a [attr] {\n color: red;\n}\n" - ); - test!(selector_el_mul_el, "a, b {\n color: red;\n}\n"); - test!( - selector_el_immediate_child_el, - "a > b {\n color: red;\n}\n" - ); - test!(selector_el_following_el, "a + b {\n color: red;\n}\n"); - test!(selector_el_preceding_el, "a ~ b {\n color: red;\n}\n"); - test!(selector_pseudo, ":pseudo {\n color: red;\n}\n"); - test!(selector_el_and_pseudo, "a:pseudo {\n color: red;\n}\n"); - test!( - selector_el_pseudo_descendant, - "a :pseudo {\n color: red;\n}\n" - ); - test!( - selector_pseudo_el_descendant, - ":pseudo a {\n color: red;\n}\n" - ); - test!( - selector_pseudo_paren_comma, - ":pseudo(a, b, c) {\n color: red;\n}\n" - ); - test!( - selector_pseudo_paren_space, - ":pseudo(a b c) {\n color: red;\n}\n" - ); - test!( - selector_el_pseudo_paren_and, - "a:pseudo(a, b, c) {\n color: red;\n}\n" - ); - test!( - selector_el_pseudo_paren_descendant, - "a :pseudo(a, b, c) {\n color: red;\n}\n" - ); - test!( - selector_pseudo_paren_el_descendant, - ":pseudo(a, b, c) a {\n color: red;\n}\n" - ); - test!( - selector_pseudo_paren_el_nested, - "a {\n :pseudo(a, b, c) {\n color: red;\n }\n}\n", - "a :pseudo(a, b, c) {\n color: red;\n}\n" - ); - test!(selector_mul, "a, b {\n color: red;\n}\n"); - test!( - outer_ampersand, - "a, b {\n& c {\n color: red;\n}\n}\n", - "a c, b c {\n color: red;\n}\n" - ); - test!( - inner_ampersand, - "a, b {\na & c {\n color: red;\n}\n}\n", - "a a c, a b c {\n color: red;\n}\n" - ); - test!( - ampersand_multiple_whitespace, - " a , b {\n&c {\n color: red;\n}\n}\n", - "ac, bc {\n color: red;\n}\n" - ); - test!( - ampersand_alone, - "a, b {\n& {\n color: red;\n}\n}\n", - "a, b {\n color: red;\n}\n" - ); - test!( - bem_dash_dash_selector, - "a {\n&--b {\n color: red;\n}\n}\n", - "a--b {\n color: red;\n}\n" - ); - // test!( - // bem_underscore_selector, - // "a {\n&__b {\n color: red;\n}\n}\n", - // "a__b {\n color: red;\n}\n" - // ); - test!( - selector_interpolation_start, - "#{a}bc {\n color: red;\n}\n", - "abc {\n color: red;\n}\n" - ); - test!( - selector_interpolation_middle, - "a#{b}c {\n color: red;\n}\n", - "abc {\n color: red;\n}\n" - ); - test!( - selector_interpolation_end, - "ab#{c} {\n color: red;\n}\n", - "abc {\n color: red;\n}\n" - ); - test!( - selector_interpolation_variable, - "$a: foo;\nab#{$a} {\n color: red;\n}\n", - "abfoo {\n color: red;\n}\n" - ); - test!( - selector_interpolation_super_selector, - "a {\nb #{&} { color: red; }}", - "a b a {\n color: red;\n}\n" - ); - test!( - selector_interpolation_super_selector_root_postfix, - "a#{&} {\nb { color: red; }}", - "a b {\n color: red;\n}\n" - ); - test!( - selector_interpolation_super_selector_root_prefix, - "#{&}a {\nb { color: red; }}", - "a b {\n color: red;\n}\n" - ); - test!( - selector_whitespace, - " a > b , c ~ d e .f #g :h i.j [ k ] { color: red }", - "a > b, c ~ d e .f #g :h i.j [k] {\n color: red;\n}\n" - ); - test!( - comment_between_selectors, - "a /* foo */ b {\n color: red;\n}\n", - "a b {\n color: red;\n}\n" - ); - test!( - interpolates_comma, - "$x: oo, ba;\nf#{$x}r {\n baz {\n color: red;\n }\n}\n", - "foo baz, bar baz {\n color: red;\n}\n" - ); - test!( - extra_commas, - "div,, , span, ,, {\n color: red;\n}\n", - "div, span {\n color: red;\n}\n" - ); - test!( - combinator_following, - "a + {\n b {\n color: red;\n }\n}\n", - "a + b {\n color: red;\n}\n" - ); - test!( - combinator_preceding, - "a {\n + b {\n color: red;\n }\n}\n", - "a + b {\n color: red;\n}\n" - ); - test!( - combinator_alone, - "a {\n + {\n b {\n color: red;\n }\n}\n", - "a + b {\n color: red;\n}\n" - ); -} - -mod test_units { - use super::StyleSheet; - test!(unit_none, "a {\n height: 1;\n}\n"); - test!(unit_not_attached, "a {\n height: 1 px;\n}\n"); - test!(unit_px, "a {\n height: 1px;\n}\n"); - test!(unit_em, "a {\n height: 1em;\n}\n"); - test!(unit_rem, "a {\n height: 1rem;\n}\n"); - test!(unit_percent, "a {\n height: 1%;\n}\n"); -} - -mod test_comments { - use super::StyleSheet; - test!( - removes_inner_comments, - "a {\n color: red/* hi */;\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - removes_inner_comments_whitespace, - "a {\n color: red /* hi */;\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - preserves_outer_comments_before, - "a {\n /* hi */\n color: red;\n}\n" - ); - test!( - preserves_outer_comments_after, - "a {\n color: red;\n /* hi */\n}\n" - ); - test!( - preserves_outer_comments_two, - "a {\n /* foo */\n /* bar */\n color: red;\n}\n" - ); - test!( - preserves_toplevel_comment_before, - "/* foo */\na {\n color: red;\n}\n" - ); - test!( - preserves_toplevel_comment_after, - "a {\n color: red;\n}\n/* foo */\n" - ); - test!( - removes_single_line_comment, - "// a { color: red }\na {\n height: 1 1px;\n}\n", - "a {\n height: 1 1px;\n}\n" - ); - test!( - converts_form_feed_in_comment, - "a {\n /* \x0C*/ color: red;\n}\n", - "a {\n /* \n*/\n color: red;\n}\n" - ); - test!( - converts_crlf_in_comment, - "a {\n /* \r\n*/ color: red;\n}\n", - "a {\n /* \n*/\n color: red;\n}\n" - ); - test!( - converts_cr_in_comment, - "a {\n /* \r*/ color: red;\n}\n", - "a {\n /* \n*/\n color: red;\n}\n" - ); -} - -mod test_styles { - use super::StyleSheet; - test!(basic_style, "a {\n color: red;\n}\n"); - test!(two_styles, "a {\n color: red;\n color: blue;\n}\n"); - test!( - two_inner_rulesets, - "a {\n b {\n color: red;\n}\n c {\n color: white;\n}\n}\n", - "a b {\n color: red;\n}\na c {\n color: white;\n}\n" - ); - test!( - two_rulesets, - "a {\n color: red;\n}\n\nc {\n color: white;\n}\n" - ); - test!( - two_rulesets_first_no_semicolon, - "a {\n color: red\n}\nc {\n color: white;\n}\n", - "a {\n color: red;\n}\n\nc {\n color: white;\n}\n" - ); - test!( - two_inner_outer_rulesets, - "a {\n b {\n color: red;\n}\n c {\n color: white;\n}\n}\na {\n b {\n color: red;\n}\n c {\n color: white;\n}\n}\n", - "a b {\n color: red;\n}\na c {\n color: white;\n}\n\na b {\n color: red;\n}\na c {\n color: white;\n}\n" - ); - test!( - removes_empty_outer_styles, - "a {\n b {\n color: red;\n }\n", - "a b {\n color: red;\n}\n" - ); - test!(removes_empty_styles, "a {}\n", ""); - test!( - doesnt_eat_style_after_ruleset, - "a {\n b {\n color: red;\n}\n color: blue;\n}\n", - "a {\n color: blue;\n}\na b {\n color: red;\n}\n" - ); - test!( - multiline_style, - "a {\n color: red\n blue;\n}\n", - "a {\n color: red blue;\n}\n" - ); - test!(hyphenated_style_property, "a {\n font-family: Arial;\n}\n"); - test!(hyphenated_style_value, "a {\n color: Open-Sans;\n}\n"); - test!( - space_separated_style_value, - "a {\n border: solid red;\n}\n" - ); - test!(single_quoted_style_value, "a {\n font: 'Open-Sans';\n}\n"); - test!( - double_quoted_style_value, - "a {\n font: \"Open-Sans\";\n}\n" - ); - test!( - comma_style_value, - "a {\n font: Open-Sans, sans-serif;\n}\n" - ); - test!( - style_interpolation_start, - "a {\n #{c}olor: red;\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - style_interpolation_middle, - "a {\n co#{l}or: red;\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - style_interpolation_end, - "a {\n colo#{r}: red;\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - style_interpolation_variable, - "$a: foo;\na {\n co#{$a}lor: red;\n}\n", - "a {\n cofoolor: red;\n}\n" - ); - test!( - style_val_interpolation_start, - "a {\n color: #{r}ed;\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - style_val_interpolation_middle, - "a {\n color: r#{e}d;\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - style_val_interpolation_end, - "a {\n color: re#{d};\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - style_val_interpolation_variable, - "$a: foo;\na {\n color: r#{$a}ed;\n}\n", - "a {\n color: rfooed;\n}\n" - ); - test!( - style_whitespace, - "a {\n color : red ; \n}\n", - "a {\n color: red;\n}\n" - ); - test!( - triple_nested_preceding_ruleset, - "a {\n b {\n foo: bar;\n c {}\n }\n}\n", - "a b {\n foo: bar;\n}\n" - ); - test!( - triple_nested_following_ruleset, - "a {\n b {\n c {}\n foo: bar;\n }\n}\n", - "a b {\n foo: bar;\n}\n" - ); - test!( - single_nested_styles, - "a {\n webkit: {\n color: red;\n color: orange\n }\n}\n", - "a {\n webkit-color: red;\n webkit-color: orange;\n}\n" - ); - test!( - multiple_nested_styles, - "a {\n webkit: {\n webkit: {\n color: red;\n }\n }\n}\n", - "a {\n webkit-webkit-color: red;\n}\n" - ); - test!( - no_space_between_colon, - "a {\n color:red;\n}\n", - "a {\n color: red;\n}\n" - ); -} - -mod test_misc { - use super::*; - // test!( - // combines_hyphens, - // "a {\n foo: bar - baz;\n}\n", - // "a {\n foo: bar-baz;\n}\n" - // ); - test!(does_not_combine_hyphens, "a {\n foo: bar -baz;\n}\n"); - test!( - ident_starts_with_hyphen, - "a {\n foo: -webkit-bar-baz;\n}\n" - ); - test!(ident_with_num, "el1 {\n a: b;\n}\n"); - test!(keyword_important, "a {\n height: 1 !important;\n}\n"); - test!( - keyword_important_uppercase, - "a {\n height: 1 !IMPORTANT;\n}\n", - "a {\n height: 1 !important;\n}\n" - ); - test!( - keyword_important_not_at_end, - "a {\n height: !important 1;\n}\n" - ); - test!( - double_newline_between_unrelated_styles, - "a {\n color: red;\n}\n\nb {\n color: blue;\n}\n" - ); -} - -mod test_interpolation { - use super::*; - test!( - removes_double_quotes, - "a {\n color: #{\"red\"};\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - removes_single_quotes, - "a {\n color: #{'red'};\n}\n", - "a {\n color: red;\n}\n" - ); -} - -mod test_mixins { - use super::*; - test!( - basic_mixin, - "@mixin a {\n color: red;\n}\n\nb {\n @include a;\n}\n", - "b {\n color: red;\n}\n" - ); - test!(empty_mixin, "@mixin a {}\n\nb {\n @include a;\n}\n", ""); - test!( - mixin_two_styles, - "@mixin a {\n color: red;\n color: blue;\n}\n\nb {\n @include a;\n}\n", - "b {\n color: red;\n color: blue;\n}\n" - ); - test!( - mixin_ruleset, - "@mixin a {\n b {\n color: red;\n }\n}\nb {\n @include a;\n}\n", - "b b {\n color: red;\n}\n" - ); - test!( - mixin_two_rulesets, - "@mixin a {\n b {\n color: red;\n }\n c {\n color: blue;\n }\n}\nd {\n @include a;\n}\n", - "d b {\n color: red;\n}\nd c {\n color: blue;\n}\n" - ); - test!( - mixin_ruleset_and_style, - "@mixin a {\n b {\n color: red;\n }\n color: blue;\n}\nd {\n @include a;\n}\n", - "d {\n color: blue;\n}\nd b {\n color: red;\n}\n" - ); - test!( - mixin_style_and_ruleset, - "@mixin a {\n color: blue;\n b {\n color: red;\n}\n}\nd {\n @include a;\n}\n", - "d {\n color: blue;\n}\nd b {\n color: red;\n}\n" - ); - test!( - mixin_nested_rulesets, - "@mixin a {\n b {\n c {\n color: red;\n}\n}\n}\nd {\n @include a;\n}\n", - "d b c {\n color: red;\n}\n" - ); - test!( - mixin_removes_empty_ruleset, - "@mixin a {\n color: red; b {\n}\n}\nd {\n @include a;\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - mixin_variable_scope_one_ruleset, - "@mixin a {\n $a: blue;\nb {\n $a: red;\n} color: $a\n}\nd {\n @include a;\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - mixin_no_args, - "@mixin a {\n color: red;\n}\nd {\n @include a();\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - mixin_single_arg, - "@mixin a($b) {\n color: $b;\n}\nd {\n @include a(red);\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - mixin_two_args, - "@mixin a($b, $c) {\n color: $b;\n color: $c\n}\nd {\n @include a(red, blue);\n}\n", - "d {\n color: red;\n color: blue;\n}\n" - ); - test!( - mixin_arg_trailing_comma, - "@mixin a($b, $c,) {\n color: $b;\n color: $c\n}\nd {\n @include a(red, blue);\n}\n", - "d {\n color: red;\n color: blue;\n}\n" - ); - test!( - mixin_property_interpolation, - "@mixin a($b) {\n #{$b}: red;\n}\nd {\n @include a(color);\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - mixin_style_interpolation, - "@mixin a($b) {\n color: #{$b};\n}\nd {\n @include a(red);\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - mixin_simple_default_value, - "@mixin a($b: red) {\n color: $b;\n}\nd {\n @include a;\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - mixin_second_value_default, - "@mixin a($a, $b: blue) {\n color: $a $b;\n}\nd {\n @include a(red);\n}\n", - "d {\n color: red blue;\n}\n" - ); - test!( - mixin_two_default_values, - "@mixin a($a: red, $b: blue) {\n color: $a $b;\n}\nd {\n @include a;\n}\n", - "d {\n color: red blue;\n}\n" - ); - test!( - mixin_override_default_value_positionally, - "@mixin a($a: red) {\n color: $a;\n}\nd {\n @include a(blue);\n}\n", - "d {\n color: blue;\n}\n" - ); - test!( - mixin_keyword_arg, - "@mixin a($a) {\n color: $a;\n}\nd {\n @include a($a: blue);\n}\n", - "d {\n color: blue;\n}\n" - ); - test!( - mixin_keyword_arg_override_default, - "@mixin a($a: red) {\n color: $a;\n}\nd {\n @include a($a: blue);\n}\n", - "d {\n color: blue;\n}\n" - ); - test!( - mixin_keyword_applies_to_second_arg, - "@mixin a($a: red, $b) {\n color: $a $b;\n}\nd {\n @include a($b: blue);\n}\n", - "d {\n color: red blue;\n}\n" - ); - test!( - mixin_two_keywords, - "@mixin a($a, $b) {\n color: $a $b;\n}\nd {\n @include a($a: red, $b: blue);\n}\n", - "d {\n color: red blue;\n}\n" - ); - test!( - mixin_two_keywords_wrong_direction, - "@mixin a($a, $b) {\n color: $a $b;\n}\nd {\n @include a($b: blue, $a: red);\n}\n", - "d {\n color: red blue;\n}\n" - ); - test!( - variable_in_call_args, - "@mixin a($a) {\n color: $a;\n}\nd {\n $c: red;\n @include a($c);\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - comment_before_positional_call_arg, - "@mixin a($a) {\n color: $a;\n}\nd {\n @include a(/*foo*/red);\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - comment_after_positional_call_arg, - "@mixin a($a) {\n color: $a;\n}\nd {\n @include a(red/*foo*/);\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - comment_before_keyword_call_arg_val, - "@mixin a($a) {\n color: $a;\n}\nd {\n @include a($a: /*foo*/red);\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - comment_after_keyword_call_arg_val, - "@mixin a($a) {\n color: $a;\n}\nd {\n @include a($a: red/*foo*/);\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - comment_before_keyword_call_arg_name, - "@mixin a($a) {\n color: $a;\n}\nd {\n @include a(/*foo*/$a: red);\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - comment_after_keyword_call_arg_name, - "@mixin a($a) {\n color: $a;\n}\nd {\n @include a($a/*foo*/: red);\n}\n", - "d {\n color: red;\n}\n" - ); - test!( - toplevel_include, - "@mixin a {\n a {\n color: red;\n }\n}\n\n@include a;\n", - "a {\n color: red;\n}\n" - ); -} - -mod test_imports { - use super::*; - use std::io::Write; - use tempfile::Builder; - - macro_rules! test_import { - ($func:ident, $input:literal => $output:literal | $( $name:literal($content:literal) ),*) => { - #[test] - fn $func() { - $( - let mut f = Builder::new().rand_bytes(0).prefix("").suffix($name).tempfile_in("").unwrap(); - write!(f, $content).unwrap(); - )* - let mut buf = Vec::new(); - StyleSheet::new($input) - .expect(concat!("failed to parse in ")) - .print_as_css(&mut buf) - .expect(concat!("failed to pretty print on ", $input)); - assert_eq!( - String::from($output), - String::from_utf8(buf).expect("produced invalid utf8") - ); - } - } - } - - // we have to use test name as filename because tests are run multithreaded in the same directory, so some names may conflict - test_import!(imports_variable, "@import \"imports_variable\";\na {\n color: $a;\n}" => "a {\n color: red;\n}\n" | "imports_variable"("$a: red;")); - test_import!(single_quotes_import, "@import 'single_quotes_import';\na {\n color: $a;\n}" => "a {\n color: red;\n}\n" | "single_quotes_import"("$a: red;")); - test_import!(finds_name_scss, "@import \"finds_name_scss\";\na {\n color: $a;\n}" => "a {\n color: red;\n}\n" | "finds_name_scss.scss"("$a: red;")); - test_import!(finds_underscore_name_scss, "@import \"finds_underscore_name_scss\";\na {\n color: $a;\n}" => "a {\n color: red;\n}\n" | "_finds_underscore_name_scss.scss"("$a: red;")); -} - -mod test_values { - use super::*; - test!(comma_list_ident, "a {\n color: red, white, blue;\n}\n"); - test!(space_list_ident, "a {\n color: red white blue;\n}\n"); - test!(comma_list_number, "a {\n color: 1, 2, 3;\n}\n"); - test!(space_list_number, "a {\n color: 1 2 3;\n}\n"); - test!(comma_space_list_number, "a {\n color: 1 1, 2 2, 3 3;\n}\n"); - test!(preserves_keyword_true, "a {\n color: true;\n}\n"); - test!(preserves_keyword_false, "a {\n color: false;\n}\n"); - test!(preserves_keyword_null, "a {\n color: null;\n}\n"); - test!(preserves_keyword_auto, "a {\n color: auto;\n}\n"); - test!(preserves_keyword_initial, "a {\n color: initial;\n}\n"); - test!(preserves_keyword_infinity, "a {\n color: infinity;\n}\n"); - test!(preserves_keyword_not, "a {\n color: not;\n}\n"); - test!(preserves_keyword_and, "a {\n color: and;\n}\n"); - test!(preserves_keyword_or, "a {\n color: or;\n}\n"); - test!(preserves_keyword_unset, "a {\n color: unset;\n}\n"); - test!(preserves_keyword_nan, "a {\n color: NaN;\n}\n"); - test!( - preserves_quotes, - "a {\n color: \"'red' \\\"blue\\\"\";\n}\n" - ); - test!( - whitespace_space_list_number, - "a {\n color: 1 2 3 ;\n}\n", - "a {\n color: 1 2 3;\n}\n" - ); - test!( - whitespace_comma_list_number, - "a {\n color: 1 , 2 , 3 ;\n}\n", - "a {\n color: 1, 2, 3;\n}\n" - ); - test!(number, "a {\n color: 1;\n}\n"); - test!( - removes_paren_around_single_value, - "a {\n color: (red);\n}\n", - "a {\n color: red;\n}\n" - ); - test!( - removes_paren_around_space_list, - "a {\n color: (red blue);\n}\n", - "a {\n color: red blue;\n}\n" - ); - test!( - removes_paren_around_item_in_list, - "a {\n color: 1 (red blue);\n}\n", - "a {\n color: 1 red blue;\n}\n" - ); -} - -mod test_functions { - use super::*; - test!( - return_num, - "@function a() {\n @return 1;\n}\n\nb {\ncolor: a();\n}\n", - "b {\n color: 1;\n}\n" - ); - test!( - return_spaced_list, - "@function a() {\n @return a b;\n}\n\nb {\ncolor: a();\n}\n", - "b {\n color: a b;\n}\n" - ); - test!( - single_arg, - "@function a($c) {\n @return $c;\n}\n\nb {\ncolor: a(1);\n}\n", - "b {\n color: 1;\n}\n" - ); - test!( - return_variable, - "@function a($a) {\n @return $a;\n}\n\nb {\ncolor: a(1);\n}\n", - "b {\n color: 1;\n}\n" - ); - // test!( - // return_no_semicolon, - // "@function a() {\n @return 1\n}\n\nb {\ncolor: a();\n}\n", - // "b {\n color: 1;\n}\n" - // ); -} diff --git a/tests/misc.rs b/tests/misc.rs new file mode 100644 index 0000000..7c80b86 --- /dev/null +++ b/tests/misc.rs @@ -0,0 +1,30 @@ +#![cfg(test)] + +#[macro_use] +mod macros; + +// test!( +// combines_hyphens, +// "a {\n foo: bar - baz;\n}\n", +// "a {\n foo: bar-baz;\n}\n" +// ); +test!(does_not_combine_hyphens, "a {\n foo: bar -baz;\n}\n"); +test!( + ident_starts_with_hyphen, + "a {\n foo: -webkit-bar-baz;\n}\n" +); +test!(ident_with_num, "el1 {\n a: b;\n}\n"); +test!(keyword_important, "a {\n height: 1 !important;\n}\n"); +test!( + keyword_important_uppercase, + "a {\n height: 1 !IMPORTANT;\n}\n", + "a {\n height: 1 !important;\n}\n" +); +test!( + keyword_important_not_at_end, + "a {\n height: !important 1;\n}\n" +); +test!( + double_newline_between_unrelated_styles, + "a {\n color: red;\n}\n\nb {\n color: blue;\n}\n" +); diff --git a/tests/mixins.rs b/tests/mixins.rs new file mode 100644 index 0000000..47936fc --- /dev/null +++ b/tests/mixins.rs @@ -0,0 +1,166 @@ +#![cfg(test)] + +#[macro_use] +mod macros; + +test!( + basic_mixin, + "@mixin a {\n color: red;\n}\n\nb {\n @include a;\n}\n", + "b {\n color: red;\n}\n" +); +test!(empty_mixin, "@mixin a {}\n\nb {\n @include a;\n}\n", ""); +test!( + mixin_two_styles, + "@mixin a {\n color: red;\n color: blue;\n}\n\nb {\n @include a;\n}\n", + "b {\n color: red;\n color: blue;\n}\n" +); +test!( + mixin_ruleset, + "@mixin a {\n b {\n color: red;\n }\n}\nb {\n @include a;\n}\n", + "b b {\n color: red;\n}\n" +); +test!( + mixin_two_rulesets, + "@mixin a {\n b {\n color: red;\n }\n c {\n color: blue;\n }\n}\nd {\n @include a;\n}\n", + "d b {\n color: red;\n}\nd c {\n color: blue;\n}\n" +); +test!( + mixin_ruleset_and_style, + "@mixin a {\n b {\n color: red;\n }\n color: blue;\n}\nd {\n @include a;\n}\n", + "d {\n color: blue;\n}\nd b {\n color: red;\n}\n" +); +test!( + mixin_style_and_ruleset, + "@mixin a {\n color: blue;\n b {\n color: red;\n}\n}\nd {\n @include a;\n}\n", + "d {\n color: blue;\n}\nd b {\n color: red;\n}\n" +); +test!( + mixin_nested_rulesets, + "@mixin a {\n b {\n c {\n color: red;\n}\n}\n}\nd {\n @include a;\n}\n", + "d b c {\n color: red;\n}\n" +); +test!( + mixin_removes_empty_ruleset, + "@mixin a {\n color: red; b {\n}\n}\nd {\n @include a;\n}\n", + "d {\n color: red;\n}\n" +); +test!( + mixin_variable_scope_one_ruleset, + "@mixin a {\n $a: blue;\nb {\n $a: red;\n} color: $a\n}\nd {\n @include a;\n}\n", + "d {\n color: red;\n}\n" +); +test!( + mixin_no_args, + "@mixin a {\n color: red;\n}\nd {\n @include a();\n}\n", + "d {\n color: red;\n}\n" +); +test!( + mixin_single_arg, + "@mixin a($b) {\n color: $b;\n}\nd {\n @include a(red);\n}\n", + "d {\n color: red;\n}\n" +); +test!( + mixin_two_args, + "@mixin a($b, $c) {\n color: $b;\n color: $c\n}\nd {\n @include a(red, blue);\n}\n", + "d {\n color: red;\n color: blue;\n}\n" +); +test!( + mixin_arg_trailing_comma, + "@mixin a($b, $c,) {\n color: $b;\n color: $c\n}\nd {\n @include a(red, blue);\n}\n", + "d {\n color: red;\n color: blue;\n}\n" +); +test!( + mixin_property_interpolation, + "@mixin a($b) {\n #{$b}: red;\n}\nd {\n @include a(color);\n}\n", + "d {\n color: red;\n}\n" +); +test!( + mixin_style_interpolation, + "@mixin a($b) {\n color: #{$b};\n}\nd {\n @include a(red);\n}\n", + "d {\n color: red;\n}\n" +); +test!( + mixin_simple_default_value, + "@mixin a($b: red) {\n color: $b;\n}\nd {\n @include a;\n}\n", + "d {\n color: red;\n}\n" +); +test!( + mixin_second_value_default, + "@mixin a($a, $b: blue) {\n color: $a $b;\n}\nd {\n @include a(red);\n}\n", + "d {\n color: red blue;\n}\n" +); +test!( + mixin_two_default_values, + "@mixin a($a: red, $b: blue) {\n color: $a $b;\n}\nd {\n @include a;\n}\n", + "d {\n color: red blue;\n}\n" +); +test!( + mixin_override_default_value_positionally, + "@mixin a($a: red) {\n color: $a;\n}\nd {\n @include a(blue);\n}\n", + "d {\n color: blue;\n}\n" +); +test!( + mixin_keyword_arg, + "@mixin a($a) {\n color: $a;\n}\nd {\n @include a($a: blue);\n}\n", + "d {\n color: blue;\n}\n" +); +test!( + mixin_keyword_arg_override_default, + "@mixin a($a: red) {\n color: $a;\n}\nd {\n @include a($a: blue);\n}\n", + "d {\n color: blue;\n}\n" +); +test!( + mixin_keyword_applies_to_second_arg, + "@mixin a($a: red, $b) {\n color: $a $b;\n}\nd {\n @include a($b: blue);\n}\n", + "d {\n color: red blue;\n}\n" +); +test!( + mixin_two_keywords, + "@mixin a($a, $b) {\n color: $a $b;\n}\nd {\n @include a($a: red, $b: blue);\n}\n", + "d {\n color: red blue;\n}\n" +); +test!( + mixin_two_keywords_wrong_direction, + "@mixin a($a, $b) {\n color: $a $b;\n}\nd {\n @include a($b: blue, $a: red);\n}\n", + "d {\n color: red blue;\n}\n" +); +test!( + variable_in_call_args, + "@mixin a($a) {\n color: $a;\n}\nd {\n $c: red;\n @include a($c);\n}\n", + "d {\n color: red;\n}\n" +); +test!( + comment_before_positional_call_arg, + "@mixin a($a) {\n color: $a;\n}\nd {\n @include a(/*foo*/red);\n}\n", + "d {\n color: red;\n}\n" +); +test!( + comment_after_positional_call_arg, + "@mixin a($a) {\n color: $a;\n}\nd {\n @include a(red/*foo*/);\n}\n", + "d {\n color: red;\n}\n" +); +test!( + comment_before_keyword_call_arg_val, + "@mixin a($a) {\n color: $a;\n}\nd {\n @include a($a: /*foo*/red);\n}\n", + "d {\n color: red;\n}\n" +); +test!( + comment_after_keyword_call_arg_val, + "@mixin a($a) {\n color: $a;\n}\nd {\n @include a($a: red/*foo*/);\n}\n", + "d {\n color: red;\n}\n" +); +test!( + comment_before_keyword_call_arg_name, + "@mixin a($a) {\n color: $a;\n}\nd {\n @include a(/*foo*/$a: red);\n}\n", + "d {\n color: red;\n}\n" +); +test!( + comment_after_keyword_call_arg_name, + "@mixin a($a) {\n color: $a;\n}\nd {\n @include a($a/*foo*/: red);\n}\n", + "d {\n color: red;\n}\n" +); +test!( + toplevel_include, + "@mixin a {\n a {\n color: red;\n }\n}\n\n@include a;\n", + "a {\n color: red;\n}\n" +); diff --git a/tests/selectors.rs b/tests/selectors.rs new file mode 100644 index 0000000..e174111 --- /dev/null +++ b/tests/selectors.rs @@ -0,0 +1,234 @@ +#![cfg(test)] + +#[macro_use] +mod macros; + +test!( + selector_nesting_el_mul_el, + "a, b {\n a, b {\n color: red\n}\n}\n", + "a a, a b, b a, b b {\n color: red;\n}\n" +); +test!(selector_element, "a {\n color: red;\n}\n"); +test!(selector_id, "#id {\n color: red;\n}\n"); +test!(selector_class, ".class {\n color: red;\n}\n"); +test!(selector_el_descendant, "a a {\n color: red;\n}\n"); +test!(selector_universal, "* {\n color: red;\n}\n"); +test!(selector_el_class_and, "a.class {\n color: red;\n}\n"); +test!(selector_el_id_and, "a#class {\n color: red;\n}\n"); +test!( + selector_el_class_descendant, + "a .class {\n color: red;\n}\n" +); +test!(selector_el_id_descendant, "a #class {\n color: red;\n}\n"); +test!( + selector_el_universal_descendant, + "a * {\n color: red;\n}\n" +); +test!( + selector_universal_el_descendant, + "* a {\n color: red;\n}\n" +); + +test!(selector_attribute_any, "[attr] {\n color: red;\n}\n"); +test!( + selector_attribute_any_lower_case_insensitive, + "[attr=val i] {\n color: red;\n}\n" +); +test!( + selector_attribute_any_upper_case_insensitive, + "[attr=val I] {\n color: red;\n}\n" +); +test!( + selector_attribute_arbitrary_modifier, + "[attr=val c] {\n color: red;\n}\n" +); +test!( + selector_attribute_i_in_attr, + "[atitr=val] {\n color: red;\n}\n" +); +test!( + selector_attribute_i_in_val, + "[attr=vail] {\n color: red;\n}\n" +); +test!( + selector_attribute_whitespace, + "[attr *= val ] {\n color: red;\n}\n", + "[attr*=val] {\n color: red;\n}\n" +); +test!( + selector_attribute_equals, + "[attr=val] {\n color: red;\n}\n" +); +test!( + selector_attribute_single_quotes, + "[attr='val'] {\n color: red;\n}\n" +); +test!( + selector_attribute_double_quotes, + "[attr=\"val\"] {\n color: red;\n}\n" +); +test!(selector_attribute_in, "[attr~=val] {\n color: red;\n}\n"); +test!( + selector_attribute_begins_hyphen_or_exact, + "[attr|=val] {\n color: red;\n}\n" +); +test!( + selector_attribute_starts_with, + "[attr^=val] {\n color: red;\n}\n" +); +test!( + selector_attribute_ends_with, + "[attr$=val] {\n color: red;\n}\n" +); +test!( + selector_attribute_contains, + "[attr*=val] {\n color: red;\n}\n" +); +test!(selector_el_attribute_and, "a[attr] {\n color: red;\n}\n"); +test!( + selector_el_attribute_descendant, + "a [attr] {\n color: red;\n}\n" +); +test!(selector_el_mul_el, "a, b {\n color: red;\n}\n"); +test!( + selector_el_immediate_child_el, + "a > b {\n color: red;\n}\n" +); +test!(selector_el_following_el, "a + b {\n color: red;\n}\n"); +test!(selector_el_preceding_el, "a ~ b {\n color: red;\n}\n"); +test!(selector_pseudo, ":pseudo {\n color: red;\n}\n"); +test!(selector_el_and_pseudo, "a:pseudo {\n color: red;\n}\n"); +test!( + selector_el_pseudo_descendant, + "a :pseudo {\n color: red;\n}\n" +); +test!( + selector_pseudo_el_descendant, + ":pseudo a {\n color: red;\n}\n" +); +test!( + selector_pseudo_paren_comma, + ":pseudo(a, b, c) {\n color: red;\n}\n" +); +test!( + selector_pseudo_paren_space, + ":pseudo(a b c) {\n color: red;\n}\n" +); +test!( + selector_el_pseudo_paren_and, + "a:pseudo(a, b, c) {\n color: red;\n}\n" +); +test!( + selector_el_pseudo_paren_descendant, + "a :pseudo(a, b, c) {\n color: red;\n}\n" +); +test!( + selector_pseudo_paren_el_descendant, + ":pseudo(a, b, c) a {\n color: red;\n}\n" +); +test!( + selector_pseudo_paren_el_nested, + "a {\n :pseudo(a, b, c) {\n color: red;\n }\n}\n", + "a :pseudo(a, b, c) {\n color: red;\n}\n" +); +test!(selector_mul, "a, b {\n color: red;\n}\n"); +test!( + outer_ampersand, + "a, b {\n& c {\n color: red;\n}\n}\n", + "a c, b c {\n color: red;\n}\n" +); +test!( + inner_ampersand, + "a, b {\na & c {\n color: red;\n}\n}\n", + "a a c, a b c {\n color: red;\n}\n" +); +test!( + ampersand_multiple_whitespace, + " a , b {\n&c {\n color: red;\n}\n}\n", + "ac, bc {\n color: red;\n}\n" +); +test!( + ampersand_alone, + "a, b {\n& {\n color: red;\n}\n}\n", + "a, b {\n color: red;\n}\n" +); +test!( + bem_dash_dash_selector, + "a {\n&--b {\n color: red;\n}\n}\n", + "a--b {\n color: red;\n}\n" +); +// test!( +// bem_underscore_selector, +// "a {\n&__b {\n color: red;\n}\n}\n", +// "a__b {\n color: red;\n}\n" +// ); +test!( + selector_interpolation_start, + "#{a}bc {\n color: red;\n}\n", + "abc {\n color: red;\n}\n" +); +test!( + selector_interpolation_middle, + "a#{b}c {\n color: red;\n}\n", + "abc {\n color: red;\n}\n" +); +test!( + selector_interpolation_end, + "ab#{c} {\n color: red;\n}\n", + "abc {\n color: red;\n}\n" +); +test!( + selector_interpolation_variable, + "$a: foo;\nab#{$a} {\n color: red;\n}\n", + "abfoo {\n color: red;\n}\n" +); +test!( + selector_interpolation_super_selector, + "a {\nb #{&} { color: red; }}", + "a b a {\n color: red;\n}\n" +); +test!( + selector_interpolation_super_selector_root_postfix, + "a#{&} {\nb { color: red; }}", + "a b {\n color: red;\n}\n" +); +test!( + selector_interpolation_super_selector_root_prefix, + "#{&}a {\nb { color: red; }}", + "a b {\n color: red;\n}\n" +); +test!( + selector_whitespace, + " a > b , c ~ d e .f #g :h i.j [ k ] { color: red }", + "a > b, c ~ d e .f #g :h i.j [k] {\n color: red;\n}\n" +); +test!( + comment_between_selectors, + "a /* foo */ b {\n color: red;\n}\n", + "a b {\n color: red;\n}\n" +); +test!( + interpolates_comma, + "$x: oo, ba;\nf#{$x}r {\n baz {\n color: red;\n }\n}\n", + "foo baz, bar baz {\n color: red;\n}\n" +); +test!( + extra_commas, + "div,, , span, ,, {\n color: red;\n}\n", + "div, span {\n color: red;\n}\n" +); +test!( + combinator_following, + "a + {\n b {\n color: red;\n }\n}\n", + "a + b {\n color: red;\n}\n" +); +test!( + combinator_preceding, + "a {\n + b {\n color: red;\n }\n}\n", + "a + b {\n color: red;\n}\n" +); +test!( + combinator_alone, + "a {\n + {\n b {\n color: red;\n }\n}\n", + "a + b {\n color: red;\n}\n" +); diff --git a/tests/styles.rs b/tests/styles.rs new file mode 100644 index 0000000..abae804 --- /dev/null +++ b/tests/styles.rs @@ -0,0 +1,127 @@ +#![cfg(test)] + +#[macro_use] +mod macros; + +test!(basic_style, "a {\n color: red;\n}\n"); +test!(two_styles, "a {\n color: red;\n color: blue;\n}\n"); +test!( + two_inner_rulesets, + "a {\n b {\n color: red;\n}\n c {\n color: white;\n}\n}\n", + "a b {\n color: red;\n}\na c {\n color: white;\n}\n" +); +test!( + two_rulesets, + "a {\n color: red;\n}\n\nc {\n color: white;\n}\n" +); +test!( + two_rulesets_first_no_semicolon, + "a {\n color: red\n}\nc {\n color: white;\n}\n", + "a {\n color: red;\n}\n\nc {\n color: white;\n}\n" +); +test!( + two_inner_outer_rulesets, + "a {\n b {\n color: red;\n}\n c {\n color: white;\n}\n}\na {\n b {\n color: red;\n}\n c {\n color: white;\n}\n}\n", + "a b {\n color: red;\n}\na c {\n color: white;\n}\n\na b {\n color: red;\n}\na c {\n color: white;\n}\n" +); +test!( + removes_empty_outer_styles, + "a {\n b {\n color: red;\n }\n", + "a b {\n color: red;\n}\n" +); +test!(removes_empty_styles, "a {}\n", ""); +test!( + doesnt_eat_style_after_ruleset, + "a {\n b {\n color: red;\n}\n color: blue;\n}\n", + "a {\n color: blue;\n}\na b {\n color: red;\n}\n" +); +test!( + multiline_style, + "a {\n color: red\n blue;\n}\n", + "a {\n color: red blue;\n}\n" +); +test!(hyphenated_style_property, "a {\n font-family: Arial;\n}\n"); +test!(hyphenated_style_value, "a {\n color: Open-Sans;\n}\n"); +test!( + space_separated_style_value, + "a {\n border: solid red;\n}\n" +); +test!(single_quoted_style_value, "a {\n font: 'Open-Sans';\n}\n"); +test!( + double_quoted_style_value, + "a {\n font: \"Open-Sans\";\n}\n" +); +test!( + comma_style_value, + "a {\n font: Open-Sans, sans-serif;\n}\n" +); +test!( + style_interpolation_start, + "a {\n #{c}olor: red;\n}\n", + "a {\n color: red;\n}\n" +); +test!( + style_interpolation_middle, + "a {\n co#{l}or: red;\n}\n", + "a {\n color: red;\n}\n" +); +test!( + style_interpolation_end, + "a {\n colo#{r}: red;\n}\n", + "a {\n color: red;\n}\n" +); +test!( + style_interpolation_variable, + "$a: foo;\na {\n co#{$a}lor: red;\n}\n", + "a {\n cofoolor: red;\n}\n" +); +test!( + style_val_interpolation_start, + "a {\n color: #{r}ed;\n}\n", + "a {\n color: red;\n}\n" +); +test!( + style_val_interpolation_middle, + "a {\n color: r#{e}d;\n}\n", + "a {\n color: red;\n}\n" +); +test!( + style_val_interpolation_end, + "a {\n color: re#{d};\n}\n", + "a {\n color: red;\n}\n" +); +test!( + style_val_interpolation_variable, + "$a: foo;\na {\n color: r#{$a}ed;\n}\n", + "a {\n color: rfooed;\n}\n" +); +test!( + style_whitespace, + "a {\n color : red ; \n}\n", + "a {\n color: red;\n}\n" +); +test!( + triple_nested_preceding_ruleset, + "a {\n b {\n foo: bar;\n c {}\n }\n}\n", + "a b {\n foo: bar;\n}\n" +); +test!( + triple_nested_following_ruleset, + "a {\n b {\n c {}\n foo: bar;\n }\n}\n", + "a b {\n foo: bar;\n}\n" +); +test!( + single_nested_styles, + "a {\n webkit: {\n color: red;\n color: orange\n }\n}\n", + "a {\n webkit-color: red;\n webkit-color: orange;\n}\n" +); +test!( + multiple_nested_styles, + "a {\n webkit: {\n webkit: {\n color: red;\n }\n }\n}\n", + "a {\n webkit-webkit-color: red;\n}\n" +); +test!( + no_space_between_colon, + "a {\n color:red;\n}\n", + "a {\n color: red;\n}\n" +); diff --git a/tests/units.rs b/tests/units.rs new file mode 100644 index 0000000..5b70eea --- /dev/null +++ b/tests/units.rs @@ -0,0 +1,11 @@ +#![cfg(test)] + +#[macro_use] +mod macros; + +test!(unit_none, "a {\n height: 1;\n}\n"); +test!(unit_not_attached, "a {\n height: 1 px;\n}\n"); +test!(unit_px, "a {\n height: 1px;\n}\n"); +test!(unit_em, "a {\n height: 1em;\n}\n"); +test!(unit_rem, "a {\n height: 1rem;\n}\n"); +test!(unit_percent, "a {\n height: 1%;\n}\n"); diff --git a/tests/values.rs b/tests/values.rs new file mode 100644 index 0000000..ae2800b --- /dev/null +++ b/tests/values.rs @@ -0,0 +1,51 @@ +#![cfg(test)] + +#[macro_use] +mod macros; + +test!(comma_list_ident, "a {\n color: red, white, blue;\n}\n"); +test!(space_list_ident, "a {\n color: red white blue;\n}\n"); +test!(comma_list_number, "a {\n color: 1, 2, 3;\n}\n"); +test!(space_list_number, "a {\n color: 1 2 3;\n}\n"); +test!(comma_space_list_number, "a {\n color: 1 1, 2 2, 3 3;\n}\n"); +test!(preserves_keyword_true, "a {\n color: true;\n}\n"); +test!(preserves_keyword_false, "a {\n color: false;\n}\n"); +test!(preserves_keyword_null, "a {\n color: null;\n}\n"); +test!(preserves_keyword_auto, "a {\n color: auto;\n}\n"); +test!(preserves_keyword_initial, "a {\n color: initial;\n}\n"); +test!(preserves_keyword_infinity, "a {\n color: infinity;\n}\n"); +test!(preserves_keyword_not, "a {\n color: not;\n}\n"); +test!(preserves_keyword_and, "a {\n color: and;\n}\n"); +test!(preserves_keyword_or, "a {\n color: or;\n}\n"); +test!(preserves_keyword_unset, "a {\n color: unset;\n}\n"); +test!(preserves_keyword_nan, "a {\n color: NaN;\n}\n"); +test!( + preserves_quotes, + "a {\n color: \"'red' \\\"blue\\\"\";\n}\n" +); +test!( + whitespace_space_list_number, + "a {\n color: 1 2 3 ;\n}\n", + "a {\n color: 1 2 3;\n}\n" +); +test!( + whitespace_comma_list_number, + "a {\n color: 1 , 2 , 3 ;\n}\n", + "a {\n color: 1, 2, 3;\n}\n" +); +test!(number, "a {\n color: 1;\n}\n"); +test!( + removes_paren_around_single_value, + "a {\n color: (red);\n}\n", + "a {\n color: red;\n}\n" +); +test!( + removes_paren_around_space_list, + "a {\n color: (red blue);\n}\n", + "a {\n color: red blue;\n}\n" +); +test!( + removes_paren_around_item_in_list, + "a {\n color: 1 (red blue);\n}\n", + "a {\n color: 1 red blue;\n}\n" +); diff --git a/tests/variables.rs b/tests/variables.rs new file mode 100644 index 0000000..dededf0 --- /dev/null +++ b/tests/variables.rs @@ -0,0 +1,100 @@ +#![cfg(test)] + +#[macro_use] +mod macros; + +test!( + basic_variable, + "$height: 1px;\na {\n height: $height;\n}\n", + "a {\n height: 1px;\n}\n" +); +test!( + variable_redeclaration, + "$a: 1px;\n$a: 2px;\na {\n height: $a;\n}\n", + "a {\n height: 2px;\n}\n" +); +test!( + variable_shadowing, + "$a: 1px;\n$b: $a;\na {\n height: $b;\n}\n", + "a {\n height: 1px;\n}\n" +); +test!( + variable_shadowing_val_does_not_change, + "$a: 1px;\n$b: $a; $a: 2px;\na {\n height: $b;\n}\n", + "a {\n height: 1px;\n}\n" +); +test!( + variable_shadowing_val_does_not_change_complex, + "a {\n color: red;\n}\n$y: before;\n$x: 1 2 $y;\n$y: after;\nfoo {\n a: $x;\n}", + "a {\n color: red;\n}\n\nfoo {\n a: 1 2 before;\n}\n" +); +test!( + variable_whitespace, + "$a : 1px ;\na {\n height: $a;\n}\n", + "a {\n height: 1px;\n}\n" +); +test!( + style_after_variable, + "$a: 1px;\na {\n height: $a;\n color: red;\n}\n", + "a {\n height: 1px;\n color: red;\n}\n" +); +test!( + literal_and_variable_as_val, + "$a: 1px;\na {\n height: 1 $a;\n}\n", + "a {\n height: 1 1px;\n}\n" +); +test!( + literal_and_variable_as_var, + "$a: 1px;\n$b: 1 $a;\na {\n height: $b;\n}\n", + "a {\n height: 1 1px;\n}\n" +); +test!( + eats_whitespace_after_variable_value, + "a {\n b {\n $c: red;\n }\n color: red;\n}\n", + "a {\n color: red;\n}\n" +); +test!( + variable_changes_through_new_ruleset, + "a {\n $c: red;\nb {\n $c: blue;\n }\n color: $c;\n}\n", + "a {\n color: blue;\n}\n" +); +test!( + nested_interpolation, + "$a: red; a {\n color: #{#{$a}};\n}\n", + "a {\n color: red;\n}\n" +); +test!( + numbers_in_variable, + "$var1: red; a {\n color: $var1;\n}\n", + "a {\n color: red;\n}\n" +); +test!( + default_var_after, + "$a: red;\n$a: blue !default;\na {\n color: $a;\n}", + "a {\n color: red;\n}\n" +); +test!( + default_var_before, + "$a: red !default;\n$a: blue;\na {\n color: $a;\n}", + "a {\n color: blue;\n}\n" +); +test!( + default_var_whitespace, + "$a: red !default ;\na {\n color: $a;\n}", + "a {\n color: red;\n}\n" +); +test!( + default_var_inside_rule, + "a {\n $a: red;\n $a: blue !default;\n color: $a;\n}", + "a {\n color: red;\n}\n" +); +test!( + interpolation_in_variable, + "$a: #{red};\na {\n color: $a\n}\n", + "a {\n color: red;\n}\n" +); +test!( + variable_decl_doesnt_end_in_semicolon, + "a {\n $a: red\n}\n\nb {\n color: blue;\n}\n", + "b {\n color: blue;\n}\n" +);