diff options
Diffstat (limited to 'servo/tests/unit/style/parsing')
-rw-r--r-- | servo/tests/unit/style/parsing/animation.rs | 21 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/background.rs | 233 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/border.rs | 219 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/box_.rs | 22 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/column.rs | 30 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/effects.rs | 99 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/image.rs | 154 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/inherited_text.rs | 46 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/mod.rs | 150 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/outline.rs | 26 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/position.rs | 145 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/selectors.rs | 35 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/supports.rs | 19 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/text_overflow.rs | 30 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/transition_duration.rs | 17 | ||||
-rw-r--r-- | servo/tests/unit/style/parsing/transition_timing_function.rs | 62 |
16 files changed, 1308 insertions, 0 deletions
diff --git a/servo/tests/unit/style/parsing/animation.rs b/servo/tests/unit/style/parsing/animation.rs new file mode 100644 index 0000000000..1b7481c4af --- /dev/null +++ b/servo/tests/unit/style/parsing/animation.rs @@ -0,0 +1,21 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use servo_atoms::Atom; +use style::parser::Parse; +use style::properties::longhands::animation_name; +use style::values::specified::AnimationIterationCount; +use style::values::{CustomIdent, KeyframesName}; +use style_traits::ToCss; + +#[test] +fn test_animation_iteration() { + assert_roundtrip_with_context!(AnimationIterationCount::parse, "0", "0"); + assert_roundtrip_with_context!(AnimationIterationCount::parse, "0.1", "0.1"); + assert_roundtrip_with_context!(AnimationIterationCount::parse, "infinite", "infinite"); + + // Negative numbers are invalid + assert!(parse(AnimationIterationCount::parse, "-1").is_err()); +} diff --git a/servo/tests/unit/style/parsing/background.rs b/servo/tests/unit/style/parsing/background.rs new file mode 100644 index 0000000000..55b1dbcd25 --- /dev/null +++ b/servo/tests/unit/style/parsing/background.rs @@ -0,0 +1,233 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use style::properties::longhands::background_size; +use style::properties::longhands::{ + background_attachment, background_clip, background_color, background_image, +}; +use style::properties::longhands::{ + background_origin, background_position_x, background_position_y, background_repeat, +}; +use style::properties::shorthands::background; + +#[test] +fn background_shorthand_should_parse_all_available_properties_when_specified() { + let input = "url(\"http://servo/test.png\") top center / 200px 200px repeat-x fixed padding-box content-box red"; + let result = parse(background::parse_value, input).unwrap(); + + assert_eq!( + result.background_image, + parse_longhand!(background_image, "url(\"http://servo/test.png\")") + ); + assert_eq!( + result.background_position_x, + parse_longhand!(background_position_x, "center") + ); + assert_eq!( + result.background_position_y, + parse_longhand!(background_position_y, "top") + ); + assert_eq!( + result.background_size, + parse_longhand!(background_size, "200px 200px") + ); + assert_eq!( + result.background_repeat, + parse_longhand!(background_repeat, "repeat-x") + ); + assert_eq!( + result.background_attachment, + parse_longhand!(background_attachment, "fixed") + ); + assert_eq!( + result.background_origin, + parse_longhand!(background_origin, "padding-box") + ); + assert_eq!( + result.background_clip, + parse_longhand!(background_clip, "content-box") + ); + assert_eq!( + result.background_color, + parse_longhand!(background_color, "red") + ); +} + +#[test] +fn background_shorthand_should_parse_when_some_fields_set() { + let result = parse(background::parse_value, "14px 40px repeat-y").unwrap(); + + assert_eq!( + result.background_position_x, + parse_longhand!(background_position_x, "14px") + ); + assert_eq!( + result.background_position_y, + parse_longhand!(background_position_y, "40px") + ); + assert_eq!( + result.background_repeat, + parse_longhand!(background_repeat, "repeat-y") + ); + + let result = parse( + background::parse_value, + "url(\"http://servo/test.png\") repeat blue", + ) + .unwrap(); + + assert_eq!( + result.background_image, + parse_longhand!(background_image, "url(\"http://servo/test.png\")") + ); + assert_eq!( + result.background_repeat, + parse_longhand!(background_repeat, "repeat") + ); + assert_eq!( + result.background_color, + parse_longhand!(background_color, "blue") + ); + + let result = parse(background::parse_value, "padding-box").unwrap(); + + assert_eq!( + result.background_origin, + parse_longhand!(background_origin, "padding-box") + ); + assert_eq!( + result.background_clip, + parse_longhand!(background_clip, "padding-box") + ); + + let result = parse(background::parse_value, "url(\"http://servo/test.png\")").unwrap(); + + assert_eq!( + result.background_image, + parse_longhand!(background_image, "url(\"http://servo/test.png\")") + ); +} + +#[test] +fn background_shorthand_should_parse_comma_separated_declarations() { + let input = + "url(\"http://servo/test.png\") top left no-repeat, url(\"http://servo/test.png\") \ + center / 100% 100% no-repeat, white"; + let result = parse(background::parse_value, input).unwrap(); + + assert_eq!( + result.background_image, + parse_longhand!( + background_image, + "url(\"http://servo/test.png\"), \ + url(\"http://servo/test.png\"), none" + ) + ); + assert_eq!( + result.background_position_x, + parse_longhand!(background_position_x, "left, center, 0%") + ); + assert_eq!( + result.background_position_y, + parse_longhand!(background_position_y, "top, center, 0%") + ); + assert_eq!( + result.background_repeat, + parse_longhand!(background_repeat, "no-repeat, no-repeat, repeat") + ); + assert_eq!( + result.background_clip, + parse_longhand!(background_clip, "border-box, border-box, border-box") + ); + assert_eq!( + result.background_origin, + parse_longhand!( + background_origin, + "padding-box, padding-box, \ + padding-box" + ) + ); + assert_eq!( + result.background_size, + parse_longhand!(background_size, "auto auto, 100% 100%, auto auto") + ); + assert_eq!( + result.background_attachment, + parse_longhand!(background_attachment, "scroll, scroll, scroll") + ); + assert_eq!( + result.background_color, + parse_longhand!(background_color, "white") + ); +} + +#[test] +fn background_shorthand_should_parse_position_and_size_correctly() { + let result = parse(background::parse_value, "7px 4px").unwrap(); + + assert_eq!( + result.background_position_x, + parse_longhand!(background_position_x, "7px") + ); + assert_eq!( + result.background_position_y, + parse_longhand!(background_position_y, "4px") + ); + + let result = parse(background::parse_value, "7px 4px / 30px 20px").unwrap(); + + assert_eq!( + result.background_position_x, + parse_longhand!(background_position_x, "7px") + ); + assert_eq!( + result.background_position_y, + parse_longhand!(background_position_y, "4px") + ); + assert_eq!( + result.background_size, + parse_longhand!(background_size, "30px 20px") + ); + + assert!(parse(background::parse_value, "/ 30px 20px").is_err()); + + assert!(parse(background::parse_value, "repeat-x / 30px 20px").is_err()); +} + +#[test] +fn background_shorthand_should_parse_origin_and_clip_correctly() { + let result = parse(background::parse_value, "padding-box content-box").unwrap(); + + assert_eq!( + result.background_origin, + parse_longhand!(background_origin, "padding-box") + ); + assert_eq!( + result.background_clip, + parse_longhand!(background_clip, "content-box") + ); + + let result = parse(background::parse_value, "padding-box padding-box").unwrap(); + + assert_eq!( + result.background_origin, + parse_longhand!(background_origin, "padding-box") + ); + assert_eq!( + result.background_clip, + parse_longhand!(background_clip, "padding-box") + ); + + let result = parse(background::parse_value, "padding-box").unwrap(); + + assert_eq!( + result.background_origin, + parse_longhand!(background_origin, "padding-box") + ); + assert_eq!( + result.background_clip, + parse_longhand!(background_clip, "padding-box") + ); +} diff --git a/servo/tests/unit/style/parsing/border.rs b/servo/tests/unit/style/parsing/border.rs new file mode 100644 index 0000000000..8e474ca542 --- /dev/null +++ b/servo/tests/unit/style/parsing/border.rs @@ -0,0 +1,219 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use style::parser::Parse; +use style::properties::longhands::{border_image_outset, border_image_repeat, border_image_slice}; +use style::properties::longhands::{border_image_source, border_image_width}; +use style::properties::shorthands::border_image; +use style::properties::MaybeBoxed; +use style::values::specified::BorderRadius; +use style_traits::ToCss; + +macro_rules! assert_longhand { + ($parsed_shorthand: expr, $prop: ident, $value_string: expr) => { + assert_eq!( + $parsed_shorthand.$prop, + parse_longhand!($prop, $value_string).maybe_boxed() + ) + }; +} + +macro_rules! assert_initial { + ($parsed_shorthand: expr, $prop: ident) => { + assert_eq!( + $parsed_shorthand.$prop, + $prop::get_initial_specified_value().maybe_boxed() + ) + }; +} + +macro_rules! assert_border_radius_values { + ($input:expr; $tlw:expr, $trw:expr, $brw:expr, $blw:expr ; + $tlh:expr, $trh:expr, $brh:expr, $blh:expr) => { + let input = parse(BorderRadius::parse, $input) + .expect(&format!("Failed parsing {} as border radius", $input)); + assert_eq!( + ::style_traits::ToCss::to_css_string(&input.top_left.0.width()), + $tlw + ); + assert_eq!( + ::style_traits::ToCss::to_css_string(&input.top_right.0.width()), + $trw + ); + assert_eq!( + ::style_traits::ToCss::to_css_string(&input.bottom_right.0.width()), + $brw + ); + assert_eq!( + ::style_traits::ToCss::to_css_string(&input.bottom_left.0.width()), + $blw + ); + assert_eq!( + ::style_traits::ToCss::to_css_string(&input.top_left.0.height()), + $tlh + ); + assert_eq!( + ::style_traits::ToCss::to_css_string(&input.top_right.0.height()), + $trh + ); + assert_eq!( + ::style_traits::ToCss::to_css_string(&input.bottom_right.0.height()), + $brh + ); + assert_eq!( + ::style_traits::ToCss::to_css_string(&input.bottom_left.0.height()), + $blh + ); + }; +} + +#[test] +fn test_border_radius() { + assert_border_radius_values!("10px"; + "10px", "10px", "10px", "10px" ; + "10px", "10px", "10px", "10px"); + assert_border_radius_values!("10px 20px"; + "10px", "20px", "10px", "20px" ; + "10px", "20px", "10px", "20px"); + assert_border_radius_values!("10px 20px 30px"; + "10px", "20px", "30px", "20px" ; + "10px", "20px", "30px", "20px"); + assert_border_radius_values!("10px 20px 30px 40px"; + "10px", "20px", "30px", "40px" ; + "10px", "20px", "30px", "40px"); + assert_border_radius_values!("10% / 20px"; + "10%", "10%", "10%", "10%" ; + "20px", "20px", "20px", "20px"); + assert_border_radius_values!("10px / 20px 30px"; + "10px", "10px", "10px", "10px" ; + "20px", "30px", "20px", "30px"); + assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px"; + "10px", "20px", "30px", "40px" ; + "1px", "2px", "3px", "4px"); + assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px"; + "10px", "20px", "30px", "40px" ; + "1px", "2px", "3px", "4px"); + assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px"; + "10px", "20px", "30px", "40px" ; + "1px", "2px", "3px", "4px"); + assert_border_radius_values!("10px -20px 30px 40px"; + "10px", "10px", "10px", "10px"; + "10px", "10px", "10px", "10px"); + assert_border_radius_values!("10px 20px -30px 40px"; + "10px", "20px", "10px", "20px"; + "10px", "20px", "10px", "20px"); + assert_border_radius_values!("10px 20px 30px -40px"; + "10px", "20px", "30px", "20px"; + "10px", "20px", "30px", "20px"); + assert!(parse(BorderRadius::parse, "-10px 20px 30px 40px").is_err()); +} + +#[test] +fn border_image_shorthand_should_parse_when_all_properties_specified() { + let input = "linear-gradient(red, blue) 30 30% 45 fill / 20px 40px / 10px round stretch"; + let result = parse(border_image::parse_value, input).unwrap(); + + assert_longhand!(result, border_image_source, "linear-gradient(red, blue)"); + assert_longhand!(result, border_image_slice, "30 30% 45 fill"); + assert_longhand!(result, border_image_width, "20px 40px"); + assert_longhand!(result, border_image_outset, "10px"); + assert_longhand!(result, border_image_repeat, "round stretch"); +} + +#[test] +fn border_image_shorthand_should_parse_without_width() { + let input = "linear-gradient(red, blue) 30 30% 45 fill / / 10px round stretch"; + let result = parse(border_image::parse_value, input).unwrap(); + + assert_longhand!(result, border_image_source, "linear-gradient(red, blue)"); + assert_longhand!(result, border_image_slice, "30 30% 45 fill"); + assert_longhand!(result, border_image_outset, "10px"); + assert_longhand!(result, border_image_repeat, "round stretch"); + assert_initial!(result, border_image_width); +} + +#[test] +fn border_image_shorthand_should_parse_without_outset() { + let input = "linear-gradient(red, blue) 30 30% 45 fill / 20px 40px round"; + let result = parse(border_image::parse_value, input).unwrap(); + + assert_longhand!(result, border_image_source, "linear-gradient(red, blue)"); + assert_longhand!(result, border_image_slice, "30 30% 45 fill"); + assert_longhand!(result, border_image_width, "20px 40px"); + assert_longhand!(result, border_image_repeat, "round"); + assert_initial!(result, border_image_outset); +} + +#[test] +fn border_image_shorthand_should_parse_without_width_or_outset() { + let input = "linear-gradient(red, blue) 30 30% 45 fill round"; + let result = parse(border_image::parse_value, input).unwrap(); + + assert_longhand!(result, border_image_source, "linear-gradient(red, blue)"); + assert_longhand!(result, border_image_slice, "30 30% 45 fill"); + assert_longhand!(result, border_image_repeat, "round"); + assert_initial!(result, border_image_width); + assert_initial!(result, border_image_outset); +} + +#[test] +fn border_image_shorthand_should_parse_with_just_source() { + let result = parse(border_image::parse_value, "linear-gradient(red, blue)").unwrap(); + + assert_longhand!(result, border_image_source, "linear-gradient(red, blue)"); + assert_initial!(result, border_image_slice); + assert_initial!(result, border_image_width); + assert_initial!(result, border_image_outset); + assert_initial!(result, border_image_repeat); +} + +#[test] +fn border_image_outset_should_error_on_negative_length() { + let result = parse(border_image_outset::parse, "-1em"); + assert!(result.is_err()); +} + +#[test] +fn border_image_outset_should_error_on_negative_number() { + let result = parse(border_image_outset::parse, "-15"); + assert!(result.is_err()); +} + +#[test] +fn border_image_outset_should_return_number_on_plain_zero() { + let result = parse(border_image_outset::parse, "0"); + assert_eq!(result.unwrap(), parse_longhand!(border_image_outset, "0")); +} + +#[test] +fn border_image_outset_should_return_length_on_length_zero() { + let result = parse(border_image_outset::parse, "0em"); + assert_eq!(result.unwrap(), parse_longhand!(border_image_outset, "0em")); +} + +#[test] +fn test_border_style() { + use style::values::specified::BorderStyle; + + assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"none"#); + assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"hidden"#); + assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"solid"#); + assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"double"#); + assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"dotted"#); + assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"dashed"#); + assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"groove"#); + assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"ridge"#); + assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"inset"#); + assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"outset"#); +} + +#[test] +fn test_border_spacing() { + use style::properties::longhands::border_spacing; + + assert_parser_exhausted!(border_spacing::parse, "1px rubbish", false); + assert_parser_exhausted!(border_spacing::parse, "1px", true); + assert_parser_exhausted!(border_spacing::parse, "1px 2px", true); +} diff --git a/servo/tests/unit/style/parsing/box_.rs b/servo/tests/unit/style/parsing/box_.rs new file mode 100644 index 0000000000..cec950c3cd --- /dev/null +++ b/servo/tests/unit/style/parsing/box_.rs @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use style_traits::ToCss; + +#[test] +fn test_transform_translate() { + use style::properties::longhands::transform; + assert_roundtrip_with_context!(transform::parse, "translate(2px)"); + assert_roundtrip_with_context!(transform::parse, "translate(2px, 5px)"); + assert!(parse(transform::parse, "translate(2px foo)").is_err()); + assert!(parse(transform::parse, "perspective(-10px)").is_err()); +} + +#[test] +fn test_unexhausted_transform() { + use style::properties::longhands::transform; + assert_parser_exhausted!(transform::parse, "rotate(70deg)foo", false); + assert_parser_exhausted!(transform::parse, "rotate(70deg) foo", false); +} diff --git a/servo/tests/unit/style/parsing/column.rs b/servo/tests/unit/style/parsing/column.rs new file mode 100644 index 0000000000..6e0e86182a --- /dev/null +++ b/servo/tests/unit/style/parsing/column.rs @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use style_traits::ToCss; + +#[test] +fn test_column_width() { + use style::properties::longhands::column_width; + + assert_roundtrip_with_context!(column_width::parse, "auto"); + assert_roundtrip_with_context!(column_width::parse, "6px"); + assert_roundtrip_with_context!(column_width::parse, "2.5em"); + assert_roundtrip_with_context!(column_width::parse, "0.3vw"); + + assert!(parse(column_width::parse, "-6px").is_err()); +} + +#[test] +fn test_column_gap() { + use style::properties::longhands::column_gap; + + assert_roundtrip_with_context!(column_gap::parse, "normal"); + assert_roundtrip_with_context!(column_gap::parse, "6px"); + assert_roundtrip_with_context!(column_gap::parse, "2.5em"); + assert_roundtrip_with_context!(column_gap::parse, "0.3vw"); + + assert!(parse(column_gap::parse, "-6px").is_err()); +} diff --git a/servo/tests/unit/style/parsing/effects.rs b/servo/tests/unit/style/parsing/effects.rs new file mode 100644 index 0000000000..1b377aca54 --- /dev/null +++ b/servo/tests/unit/style/parsing/effects.rs @@ -0,0 +1,99 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use style::properties::longhands::{perspective_origin, transform_origin}; +use style_traits::ToCss; + +#[test] +fn test_clip() { + use style::properties::longhands::clip; + + assert_roundtrip_with_context!(clip::parse, "auto"); + assert_roundtrip_with_context!(clip::parse, "rect(1px, 2px, 3px, 4px)"); + assert_roundtrip_with_context!(clip::parse, "rect(1px, auto, auto, 4px)"); + assert_roundtrip_with_context!(clip::parse, "rect(auto, auto, auto, auto)"); + + // Non-standard syntax + assert_roundtrip_with_context!( + clip::parse, + "rect(1px 2px 3px 4px)", + "rect(1px, 2px, 3px, 4px)" + ); + assert_roundtrip_with_context!( + clip::parse, + "rect(auto 2px 3px auto)", + "rect(auto, 2px, 3px, auto)" + ); + assert_roundtrip_with_context!( + clip::parse, + "rect(1px auto auto 4px)", + "rect(1px, auto, auto, 4px)" + ); + assert_roundtrip_with_context!( + clip::parse, + "rect(auto auto auto auto)", + "rect(auto, auto, auto, auto)" + ); +} + +#[test] +fn test_effects_parser_exhaustion() { + assert_parser_exhausted!(perspective_origin::parse, "1px 1px", true); + assert_parser_exhausted!(transform_origin::parse, "1px 1px", true); + + assert_parser_exhausted!(perspective_origin::parse, "1px some-rubbish", false); + assert_parser_exhausted!(transform_origin::parse, "1px some-rubbish", false); +} + +#[test] +fn test_parse_factor() { + use parsing::parse; + use style::properties::longhands::filter; + + assert!(parse(filter::parse, "brightness(0)").is_ok()); + assert!(parse(filter::parse, "brightness(55)").is_ok()); + assert!(parse(filter::parse, "brightness(100)").is_ok()); + + assert!(parse(filter::parse, "contrast(0)").is_ok()); + assert!(parse(filter::parse, "contrast(55)").is_ok()); + assert!(parse(filter::parse, "contrast(100)").is_ok()); + + assert!(parse(filter::parse, "grayscale(0)").is_ok()); + assert!(parse(filter::parse, "grayscale(55)").is_ok()); + assert!(parse(filter::parse, "grayscale(100)").is_ok()); + + assert!(parse(filter::parse, "invert(0)").is_ok()); + assert!(parse(filter::parse, "invert(55)").is_ok()); + assert!(parse(filter::parse, "invert(100)").is_ok()); + + assert!(parse(filter::parse, "opacity(0)").is_ok()); + assert!(parse(filter::parse, "opacity(55)").is_ok()); + assert!(parse(filter::parse, "opacity(100)").is_ok()); + + assert!(parse(filter::parse, "sepia(0)").is_ok()); + assert!(parse(filter::parse, "sepia(55)").is_ok()); + assert!(parse(filter::parse, "sepia(100)").is_ok()); + + assert!(parse(filter::parse, "saturate(0)").is_ok()); + assert!(parse(filter::parse, "saturate(55)").is_ok()); + assert!(parse(filter::parse, "saturate(100)").is_ok()); + + // Negative numbers are invalid for certain filters + assert!(parse(filter::parse, "brightness(-1)").is_err()); + assert!(parse(filter::parse, "contrast(-1)").is_err()); + assert!(parse(filter::parse, "grayscale(-1)").is_err()); + assert!(parse(filter::parse, "invert(-1)").is_err()); + assert!(parse(filter::parse, "opacity(-1)").is_err()); + assert!(parse(filter::parse, "sepia(-1)").is_err()); + assert!(parse(filter::parse, "saturate(-1)").is_err()); +} + +#[test] +fn blur_radius_should_not_accept_negavite_values() { + use style::properties::longhands::box_shadow; + assert!(parse(box_shadow::parse, "1px 1px -1px").is_err()); // for -ve values + assert!(parse(box_shadow::parse, "1px 1px 0").is_ok()); // for zero + assert!(parse(box_shadow::parse, "1px 1px 1px").is_ok()); // for +ve value +} diff --git a/servo/tests/unit/style/parsing/image.rs b/servo/tests/unit/style/parsing/image.rs new file mode 100644 index 0000000000..33ccb88cb0 --- /dev/null +++ b/servo/tests/unit/style/parsing/image.rs @@ -0,0 +1,154 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use style::parser::Parse; +use style::values::specified::image::*; +use style_traits::ToCss; + +#[test] +fn test_linear_gradient() { + // Parsing from the right + assert_roundtrip_with_context!(Image::parse, "linear-gradient(to left, red, green)"); + + // Parsing from the left + assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right, red, green)"); + + // Parsing with two values for <side-or-corner> + assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right top, red, green)"); + + // Parsing with <angle> + assert_roundtrip_with_context!(Image::parse, "linear-gradient(45deg, red, green)"); + + // Parsing with more than two entries in <color-stop-list> + assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, yellow, green)"); + + // Parsing with percentage in the <color-stop-list> + assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green, yellow 50%)"); + + // Parsing without <angle> and <side-or-corner> + assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green)"); +} + +#[test] +fn test_radial_gradient() { + // Parsing with all values + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(circle closest-side at 20px 30px, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(ellipse closest-side at 20px 30px, red, green)", + "radial-gradient(closest-side at 20px 30px, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(closest-side circle at 20px 30px, red, green)", + "radial-gradient(circle closest-side at 20px 30px, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(closest-side ellipse at 20px 30px, red, green)", + "radial-gradient(closest-side at 20px 30px, red, green)" + ); + + // Parsing with <shape-keyword> and <size> reversed + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(closest-side circle at 20px 30px, red, green)", + "radial-gradient(circle closest-side at 20px 30px, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(closest-corner ellipse at 20px 30px, red, green)", + "radial-gradient(closest-corner at 20px 30px, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(30px circle, red, green)", + "radial-gradient(30px at center center, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(30px 40px ellipse, red, green)", + "radial-gradient(30px 40px at center center, red, green)" + ); + + // Parsing without <size> + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(circle, red, green)", + "radial-gradient(circle at center center, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(ellipse, red, green)", + "radial-gradient(at center center, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(circle at 20px 30px, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(ellipse at 20px 30px, red, green)", + "radial-gradient(at 20px 30px, red, green)" + ); + + // Parsing without <shape-keyword> + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(20px at 20px 30px, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(20px 30px at left center, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(closest-side at center, red, green)", + "radial-gradient(closest-side at center center, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(20px, red, green)", + "radial-gradient(20px at center center, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(20px 30px, red, green)", + "radial-gradient(20px 30px at center center, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(closest-side, red, green)", + "radial-gradient(closest-side at center center, red, green)" + ); + + // Parsing without <shape-keyword> and <size> + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(at center, red, green)", + "radial-gradient(at center center, red, green)" + ); + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(at center bottom, red, green)" + ); + assert_roundtrip_with_context!(Image::parse, "radial-gradient(at 40px 50px, red, green)"); + + // Parsing with just color stops + assert_roundtrip_with_context!( + Image::parse, + "radial-gradient(red, green)", + "radial-gradient(at center center, red, green)" + ); + + // Parsing repeating radial gradient + assert_roundtrip_with_context!( + Image::parse, + "repeating-radial-gradient(red, green)", + "repeating-radial-gradient(at center center, red, green)" + ); +} diff --git a/servo/tests/unit/style/parsing/inherited_text.rs b/servo/tests/unit/style/parsing/inherited_text.rs new file mode 100644 index 0000000000..90ec16f7b0 --- /dev/null +++ b/servo/tests/unit/style/parsing/inherited_text.rs @@ -0,0 +1,46 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use style::values::generics::text::Spacing; + +#[test] +fn negative_letter_spacing_should_parse_properly() { + use style::properties::longhands::letter_spacing; + use style::values::specified::length::{FontRelativeLength, Length, NoCalcLength}; + + let negative_value = parse_longhand!(letter_spacing, "-0.5em"); + let expected = Spacing::Value(Length::NoCalc(NoCalcLength::FontRelative( + FontRelativeLength::Em(-0.5), + ))); + assert_eq!(negative_value, expected); +} + +#[test] +fn negative_word_spacing_should_parse_properly() { + use style::properties::longhands::word_spacing; + use style::values::specified::length::{FontRelativeLength, LengthPercentage, NoCalcLength}; + + let negative_value = parse_longhand!(word_spacing, "-0.5em"); + let expected = Spacing::Value(LengthPercentage::Length(NoCalcLength::FontRelative( + FontRelativeLength::Em(-0.5), + ))); + assert_eq!(negative_value, expected); +} + +#[test] +fn line_height_should_return_number_on_plain_zero() { + use style::properties::longhands::line_height; + + let result = parse(line_height::parse, "0").unwrap(); + assert_eq!(result, parse_longhand!(line_height, "0")); +} + +#[test] +fn line_height_should_return_length_on_length_zero() { + use style::properties::longhands::line_height; + + let result = parse(line_height::parse, "0px").unwrap(); + assert_eq!(result, parse_longhand!(line_height, "0px")); +} diff --git a/servo/tests/unit/style/parsing/mod.rs b/servo/tests/unit/style/parsing/mod.rs new file mode 100644 index 0000000000..095f74c960 --- /dev/null +++ b/servo/tests/unit/style/parsing/mod.rs @@ -0,0 +1,150 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! Tests for parsing and serialization of values/properties + +use cssparser::{Parser, ParserInput}; +use style::context::QuirksMode; +use style::parser::ParserContext; +use style::stylesheets::{CssRuleType, Origin}; +use style_traits::{ParseError, ParsingMode}; + +fn parse<T, F>(f: F, s: &'static str) -> Result<T, ParseError<'static>> +where + F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result<T, ParseError<'static>>, +{ + let mut input = ParserInput::new(s); + parse_input(f, &mut input) +} + +fn parse_input<'i: 't, 't, T, F>(f: F, input: &'t mut ParserInput<'i>) -> Result<T, ParseError<'i>> +where + F: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>, +{ + let url = ::servo_url::ServoUrl::parse("http://localhost").unwrap(); + let context = ParserContext::new( + Origin::Author, + &url, + Some(CssRuleType::Style), + ParsingMode::DEFAULT, + QuirksMode::NoQuirks, + None, + None, + ); + let mut parser = Parser::new(input); + f(&context, &mut parser) +} + +fn parse_entirely<T, F>(f: F, s: &'static str) -> Result<T, ParseError<'static>> +where + F: for<'t> Fn(&ParserContext, &mut Parser<'static, 't>) -> Result<T, ParseError<'static>>, +{ + let mut input = ParserInput::new(s); + parse_entirely_input(f, &mut input) +} + +fn parse_entirely_input<'i: 't, 't, T, F>( + f: F, + input: &'t mut ParserInput<'i>, +) -> Result<T, ParseError<'i>> +where + F: Fn(&ParserContext, &mut Parser<'i, 't>) -> Result<T, ParseError<'i>>, +{ + parse_input( + |context, parser| parser.parse_entirely(|p| f(context, p)), + input, + ) +} + +// This is a macro so that the file/line information +// is preserved in the panic +macro_rules! assert_roundtrip_with_context { + ($fun:expr, $string:expr) => { + assert_roundtrip_with_context!($fun, $string, $string); + }; + ($fun:expr, $input:expr, $output:expr) => {{ + let mut input = ::cssparser::ParserInput::new($input); + let serialized = super::parse_input( + |context, i| { + let parsed = $fun(context, i).expect(&format!("Failed to parse {}", $input)); + let serialized = ToCss::to_css_string(&parsed); + assert_eq!(serialized, $output); + Ok(serialized) + }, + &mut input, + ) + .unwrap(); + + let mut input = ::cssparser::ParserInput::new(&serialized); + let unwrapped = super::parse_input( + |context, i| { + let re_parsed = + $fun(context, i).expect(&format!("Failed to parse serialization {}", $input)); + let re_serialized = ToCss::to_css_string(&re_parsed); + assert_eq!(serialized, re_serialized); + Ok(()) + }, + &mut input, + ) + .unwrap(); + unwrapped + }}; +} + +macro_rules! assert_roundtrip { + ($fun:expr, $string:expr) => { + assert_roundtrip!($fun, $string, $string); + }; + ($fun:expr, $input:expr, $output:expr) => { + let mut input = ParserInput::new($input); + let mut parser = Parser::new(&mut input); + let parsed = $fun(&mut parser).expect(&format!("Failed to parse {}", $input)); + let serialized = ToCss::to_css_string(&parsed); + assert_eq!(serialized, $output); + + let mut input = ParserInput::new(&serialized); + let mut parser = Parser::new(&mut input); + let re_parsed = + $fun(&mut parser).expect(&format!("Failed to parse serialization {}", $input)); + let re_serialized = ToCss::to_css_string(&re_parsed); + assert_eq!(serialized, re_serialized) + }; +} + +macro_rules! assert_parser_exhausted { + ($fun:expr, $string:expr, $should_exhausted:expr) => {{ + parse( + |context, input| { + let parsed = $fun(context, input); + assert_eq!(parsed.is_ok(), true); + assert_eq!(input.is_exhausted(), $should_exhausted); + Ok(()) + }, + $string, + ) + .unwrap() + }}; +} + +macro_rules! parse_longhand { + ($name:ident, $s:expr) => { + parse($name::parse, $s).unwrap() + }; +} + +mod animation; +mod background; +mod border; +mod box_; +mod column; +mod effects; +mod image; +mod inherited_text; +mod outline; +mod position; +mod selectors; +mod supports; +mod text_overflow; +mod transition_duration; +mod transition_timing_function; diff --git a/servo/tests/unit/style/parsing/outline.rs b/servo/tests/unit/style/parsing/outline.rs new file mode 100644 index 0000000000..6d909d9bc5 --- /dev/null +++ b/servo/tests/unit/style/parsing/outline.rs @@ -0,0 +1,26 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use style_traits::ToCss; + +#[test] +fn test_outline_style() { + use style::properties::longhands::outline_style; + + assert_roundtrip_with_context!(outline_style::parse, r#"auto"#); + assert_roundtrip_with_context!(outline_style::parse, r#"none"#); + assert_roundtrip_with_context!(outline_style::parse, r#"solid"#); + assert_roundtrip_with_context!(outline_style::parse, r#"double"#); + assert_roundtrip_with_context!(outline_style::parse, r#"dotted"#); + assert_roundtrip_with_context!(outline_style::parse, r#"dashed"#); + assert_roundtrip_with_context!(outline_style::parse, r#"groove"#); + assert_roundtrip_with_context!(outline_style::parse, r#"ridge"#); + assert_roundtrip_with_context!(outline_style::parse, r#"inset"#); + assert_roundtrip_with_context!(outline_style::parse, r#"outset"#); + + // The outline-style property accepts the same values as border-style, + // except that 'hidden' is not a legal outline style. + assert!(parse(outline_style::parse, r#"hidden"#).is_err()); +} diff --git a/servo/tests/unit/style/parsing/position.rs b/servo/tests/unit/style/parsing/position.rs new file mode 100644 index 0000000000..ce73c7a0d2 --- /dev/null +++ b/servo/tests/unit/style/parsing/position.rs @@ -0,0 +1,145 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::{parse, parse_entirely}; +use style::parser::Parse; +use style::values::specified::position::*; +use style_traits::ToCss; + +#[test] +fn test_position() { + // Serialization is not actually specced + // though these are the values expected by basic-shape + // https://github.com/w3c/csswg-drafts/issues/368 + assert_roundtrip_with_context!(Position::parse, "center", "center center"); + assert_roundtrip_with_context!(Position::parse, "top left", "left top"); + assert_roundtrip_with_context!(Position::parse, "left top", "left top"); + assert_roundtrip_with_context!(Position::parse, "top right", "right top"); + assert_roundtrip_with_context!(Position::parse, "right top", "right top"); + assert_roundtrip_with_context!(Position::parse, "bottom left", "left bottom"); + assert_roundtrip_with_context!(Position::parse, "left bottom", "left bottom"); + assert_roundtrip_with_context!(Position::parse, "left center", "left center"); + assert_roundtrip_with_context!(Position::parse, "right center", "right center"); + assert_roundtrip_with_context!(Position::parse, "center top", "center top"); + assert_roundtrip_with_context!(Position::parse, "center bottom", "center bottom"); + assert_roundtrip_with_context!(Position::parse, "center 10px", "center 10px"); + assert_roundtrip_with_context!(Position::parse, "center 10%", "center 10%"); + assert_roundtrip_with_context!(Position::parse, "right 10%", "right 10%"); + + // Only keywords can be reordered + assert!(parse_entirely(Position::parse, "top 40%").is_err()); + assert!(parse_entirely(Position::parse, "40% left").is_err()); + + // 3 and 4 value serialization + assert_roundtrip_with_context!(Position::parse, "left 10px top 15px", "left 10px top 15px"); + assert_roundtrip_with_context!(Position::parse, "top 15px left 10px", "left 10px top 15px"); + assert_roundtrip_with_context!(Position::parse, "left 10% top 15px", "left 10% top 15px"); + assert_roundtrip_with_context!(Position::parse, "top 15px left 10%", "left 10% top 15px"); + assert_roundtrip_with_context!(Position::parse, "left top 15px", "left top 15px"); + assert_roundtrip_with_context!(Position::parse, "top 15px left", "left top 15px"); + assert_roundtrip_with_context!(Position::parse, "left 10px top", "left 10px top"); + assert_roundtrip_with_context!(Position::parse, "top left 10px", "left 10px top"); + assert_roundtrip_with_context!(Position::parse, "right 10px bottom", "right 10px bottom"); + assert_roundtrip_with_context!(Position::parse, "bottom right 10px", "right 10px bottom"); + assert_roundtrip_with_context!(Position::parse, "center right 10px", "right 10px center"); + assert_roundtrip_with_context!(Position::parse, "center bottom 10px", "center bottom 10px"); + + // Invalid 3 value positions + assert!(parse_entirely(Position::parse, "20px 30px 20px").is_err()); + assert!(parse_entirely(Position::parse, "top 30px 20px").is_err()); + assert!(parse_entirely(Position::parse, "50% bottom 20%").is_err()); + + // Only horizontal and vertical keywords can have positions + assert!(parse_entirely(Position::parse, "center 10px left 15px").is_err()); + assert!(parse_entirely(Position::parse, "center 10px 15px").is_err()); + assert!(parse_entirely(Position::parse, "center 10px bottom").is_err()); + + // "Horizontal Horizontal" or "Vertical Vertical" positions cause error + assert!(parse_entirely(Position::parse, "left right").is_err()); + assert!(parse_entirely(Position::parse, "left 10px right").is_err()); + assert!(parse_entirely(Position::parse, "left 10px right 15%").is_err()); + assert!(parse_entirely(Position::parse, "top bottom").is_err()); + assert!(parse_entirely(Position::parse, "top 10px bottom").is_err()); + assert!(parse_entirely(Position::parse, "top 10px bottom 15%").is_err()); + + // Logical keywords are not supported in Position yet. + assert!(parse(Position::parse, "x-start").is_err()); + assert!(parse(Position::parse, "y-end").is_err()); + assert!(parse(Position::parse, "x-start y-end").is_err()); + assert!(parse(Position::parse, "x-end 10px").is_err()); + assert!(parse(Position::parse, "y-start 20px").is_err()); + assert!(parse(Position::parse, "x-start bottom 10%").is_err()); + assert!(parse_entirely(Position::parse, "left y-start 10%").is_err()); + assert!(parse(Position::parse, "x-start 20px y-end 10%").is_err()); +} + +#[test] +fn test_horizontal_position() { + // One value serializations. + assert_roundtrip_with_context!(HorizontalPosition::parse, "20px", "20px"); + assert_roundtrip_with_context!(HorizontalPosition::parse, "25%", "25%"); + assert_roundtrip_with_context!(HorizontalPosition::parse, "center", "center"); + assert_roundtrip_with_context!(HorizontalPosition::parse, "left", "left"); + assert_roundtrip_with_context!(HorizontalPosition::parse, "right", "right"); + + // Two value serializations. + assert_roundtrip_with_context!(HorizontalPosition::parse, "right 10px", "right 10px"); + + // Invalid horizontal positions. + assert!(parse(HorizontalPosition::parse, "top").is_err()); + assert!(parse(HorizontalPosition::parse, "bottom").is_err()); + assert!(parse(HorizontalPosition::parse, "y-start").is_err()); + assert!(parse(HorizontalPosition::parse, "y-end").is_err()); + assert!(parse(HorizontalPosition::parse, "y-end 20px ").is_err()); + assert!(parse(HorizontalPosition::parse, "bottom 20px").is_err()); + assert!(parse(HorizontalPosition::parse, "bottom top").is_err()); + assert!(parse_entirely(HorizontalPosition::parse, "20px y-end").is_err()); + assert!(parse_entirely(HorizontalPosition::parse, "20px top").is_err()); + assert!(parse_entirely(HorizontalPosition::parse, "left center").is_err()); + assert!(parse_entirely(HorizontalPosition::parse, "left top").is_err()); + assert!(parse_entirely(HorizontalPosition::parse, "left right").is_err()); + assert!(parse_entirely(HorizontalPosition::parse, "20px 30px").is_err()); + assert!(parse_entirely(HorizontalPosition::parse, "10px left").is_err()); + assert!(parse_entirely(HorizontalPosition::parse, "x-end 20%").is_err()); + assert!(parse_entirely(HorizontalPosition::parse, "20px x-start").is_err()); + + // Logical keywords are not supported in Position yet. + assert!(parse(HorizontalPosition::parse, "x-start").is_err()); + assert!(parse(HorizontalPosition::parse, "x-end").is_err()); +} + +#[test] +fn test_vertical_position() { + // One value serializations. + assert_roundtrip_with_context!(VerticalPosition::parse, "20px", "20px"); + assert_roundtrip_with_context!(VerticalPosition::parse, "25%", "25%"); + assert_roundtrip_with_context!(VerticalPosition::parse, "center", "center"); + assert_roundtrip_with_context!(VerticalPosition::parse, "top", "top"); + assert_roundtrip_with_context!(VerticalPosition::parse, "bottom", "bottom"); + + // Two value serializations. + assert_roundtrip_with_context!(VerticalPosition::parse, "bottom 10px", "bottom 10px"); + + // Invalid vertical positions. + assert!(parse(VerticalPosition::parse, "left").is_err()); + assert!(parse(VerticalPosition::parse, "right").is_err()); + assert!(parse(VerticalPosition::parse, "x-start").is_err()); + assert!(parse(VerticalPosition::parse, "x-end").is_err()); + assert!(parse(VerticalPosition::parse, "x-end 20px").is_err()); + assert!(parse(VerticalPosition::parse, "left 20px").is_err()); + assert!(parse(VerticalPosition::parse, "left center").is_err()); + assert!(parse(VerticalPosition::parse, "left top").is_err()); + assert!(parse(VerticalPosition::parse, "left right").is_err()); + assert!(parse_entirely(VerticalPosition::parse, "20px x-end").is_err()); + assert!(parse_entirely(VerticalPosition::parse, "20px right").is_err()); + assert!(parse_entirely(VerticalPosition::parse, "bottom top").is_err()); + assert!(parse_entirely(VerticalPosition::parse, "20px 30px").is_err()); + assert!(parse_entirely(VerticalPosition::parse, "10px top").is_err()); + assert!(parse_entirely(VerticalPosition::parse, "y-end 20%").is_err()); + assert!(parse_entirely(VerticalPosition::parse, "20px y-start").is_err()); + + // Logical keywords are not supported in Position yet. + assert!(parse(VerticalPosition::parse, "y-start").is_err()); + assert!(parse(VerticalPosition::parse, "y-end").is_err()); +} diff --git a/servo/tests/unit/style/parsing/selectors.rs b/servo/tests/unit/style/parsing/selectors.rs new file mode 100644 index 0000000000..1ce7498caa --- /dev/null +++ b/servo/tests/unit/style/parsing/selectors.rs @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use cssparser::{Parser, ParserInput, ToCss}; +use selectors::parser::SelectorList; +use style::selector_parser::{SelectorImpl, SelectorParser}; +use style::stylesheets::{Namespaces, Origin}; +use style_traits::ParseError; + +fn parse_selector<'i, 't>( + input: &mut Parser<'i, 't>, +) -> Result<SelectorList<SelectorImpl>, ParseError<'i>> { + let mut ns = Namespaces::default(); + ns.prefixes.insert("svg".into(), ns!(svg)); + let parser = SelectorParser { + stylesheet_origin: Origin::UserAgent, + namespaces: &ns, + url_data: None, + }; + SelectorList::parse(&parser, input) +} + +#[test] +fn test_selectors() { + assert_roundtrip!(parse_selector, "div"); + assert_roundtrip!(parse_selector, "svg|circle"); + assert_roundtrip!(parse_selector, "p:before", "p::before"); + assert_roundtrip!( + parse_selector, + "[border=\"0\"]:-servo-nonzero-border ~ ::-servo-details-summary" + ); + assert_roundtrip!(parse_selector, "* > *"); + assert_roundtrip!(parse_selector, "*|* + *", "* + *"); +} diff --git a/servo/tests/unit/style/parsing/supports.rs b/servo/tests/unit/style/parsing/supports.rs new file mode 100644 index 0000000000..f54ee48bab --- /dev/null +++ b/servo/tests/unit/style/parsing/supports.rs @@ -0,0 +1,19 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use cssparser::{Parser, ParserInput}; +use style::stylesheets::supports_rule::SupportsCondition; +use style_traits::ToCss; + +#[test] +fn test_supports_condition() { + assert_roundtrip!(SupportsCondition::parse, "(margin: 1px)"); + assert_roundtrip!(SupportsCondition::parse, "not (--be: to be)"); + assert_roundtrip!( + SupportsCondition::parse, + "(color: blue) and future-extension(4)" + ); + assert_roundtrip!(SupportsCondition::parse, "future-\\1 extension(4)"); + assert_roundtrip!(SupportsCondition::parse, "((test))"); +} diff --git a/servo/tests/unit/style/parsing/text_overflow.rs b/servo/tests/unit/style/parsing/text_overflow.rs new file mode 100644 index 0000000000..505e6ffb8c --- /dev/null +++ b/servo/tests/unit/style/parsing/text_overflow.rs @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use style_traits::ToCss; + +#[test] +fn test_text_overflow() { + use style::properties::longhands::text_overflow; + + assert_roundtrip_with_context!(text_overflow::parse, r#"clip"#); + assert_roundtrip_with_context!(text_overflow::parse, r#"ellipsis"#); + assert_roundtrip_with_context!(text_overflow::parse, r#"clip ellipsis"#); + assert_roundtrip_with_context!(text_overflow::parse, r#""x""#); + assert_roundtrip_with_context!(text_overflow::parse, r#"'x'"#, r#""x""#); + assert_roundtrip_with_context!(text_overflow::parse, r#"clip "x""#); + assert_roundtrip_with_context!(text_overflow::parse, r#""x" clip"#); + assert_roundtrip_with_context!(text_overflow::parse, r#""x" "y""#); +} + +#[test] +fn test_text_overflow_parser_exhaustion() { + use style::properties::longhands::text_overflow; + + assert_parser_exhausted!(text_overflow::parse, r#"clip rubbish"#, false); + assert_parser_exhausted!(text_overflow::parse, r#"clip"#, true); + assert_parser_exhausted!(text_overflow::parse, r#"ellipsis"#, true); + assert_parser_exhausted!(text_overflow::parse, r#"clip ellipsis"#, true); +} diff --git a/servo/tests/unit/style/parsing/transition_duration.rs b/servo/tests/unit/style/parsing/transition_duration.rs new file mode 100644 index 0000000000..c771a58944 --- /dev/null +++ b/servo/tests/unit/style/parsing/transition_duration.rs @@ -0,0 +1,17 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use style::properties::longhands::transition_duration; + +#[test] +fn test_positive_transition_duration() { + assert!(parse(transition_duration::parse, "5s").is_ok()); + assert!(parse(transition_duration::parse, "0s").is_ok()); +} + +#[test] +fn test_negative_transition_duration() { + assert!(parse(transition_duration::parse, "-5s").is_err()); +} diff --git a/servo/tests/unit/style/parsing/transition_timing_function.rs b/servo/tests/unit/style/parsing/transition_timing_function.rs new file mode 100644 index 0000000000..5fbb89709e --- /dev/null +++ b/servo/tests/unit/style/parsing/transition_timing_function.rs @@ -0,0 +1,62 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use parsing::parse; +use style::properties::longhands::transition_timing_function; +use style_traits::ToCss; + +#[test] +fn test_cubic_bezier() { + assert_roundtrip_with_context!( + transition_timing_function::parse, + "cubic-bezier(0, 0, 0, 0)" + ); + assert_roundtrip_with_context!( + transition_timing_function::parse, + "cubic-bezier(0.25, 0, 0.5, 0)" + ); + assert_roundtrip_with_context!( + transition_timing_function::parse, + "cubic-bezier(1, 1, 1, 1)" + ); + + // p1x and p2x values must be in range [0, 1] + assert!(parse( + transition_timing_function::parse, + "cubic-bezier(-1, 0, 0, 0" + ) + .is_err()); + assert!(parse( + transition_timing_function::parse, + "cubic-bezier(0, 0, -1, 0" + ) + .is_err()); + assert!(parse( + transition_timing_function::parse, + "cubic-bezier(-1, 0, -1, 0" + ) + .is_err()); + + assert!(parse(transition_timing_function::parse, "cubic-bezier(2, 0, 0, 0").is_err()); + assert!(parse(transition_timing_function::parse, "cubic-bezier(0, 0, 2, 0").is_err()); + assert!(parse(transition_timing_function::parse, "cubic-bezier(2, 0, 2, 0").is_err()); +} + +#[test] +fn test_steps() { + assert_roundtrip_with_context!(transition_timing_function::parse, "steps(1)"); + assert_roundtrip_with_context!(transition_timing_function::parse, "steps( 1)", "steps(1)"); + assert_roundtrip_with_context!(transition_timing_function::parse, "steps(1, start)"); + assert_roundtrip_with_context!( + transition_timing_function::parse, + "steps(2, end) ", + "steps(2)" + ); + + // Step interval value must be an integer greater than 0 + assert!(parse(transition_timing_function::parse, "steps(0)").is_err()); + assert!(parse(transition_timing_function::parse, "steps(0.5)").is_err()); + assert!(parse(transition_timing_function::parse, "steps(-1)").is_err()); + assert!(parse(transition_timing_function::parse, "steps(1, middle)").is_err()); +} |