1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4 
5 use parsing::parse;
6 use style::parser::Parse;
7 use style::properties::MaybeBoxed;
8 use style::properties::longhands::{border_image_outset, border_image_repeat, border_image_slice};
9 use style::properties::longhands::{border_image_source, border_image_width};
10 use style::properties::shorthands::border_image;
11 use style::values::specified::BorderRadius;
12 use style_traits::ToCss;
13 
14 macro_rules! assert_longhand {
15     ($parsed_shorthand: expr, $prop: ident, $value_string: expr) => {
16         assert_eq!($parsed_shorthand.$prop, parse_longhand!($prop, $value_string).maybe_boxed())
17     }
18 }
19 
20 macro_rules! assert_initial {
21     ($parsed_shorthand: expr, $prop: ident) => {
22         assert_eq!($parsed_shorthand.$prop, $prop::get_initial_specified_value().maybe_boxed())
23     }
24 }
25 
26 macro_rules! assert_border_radius_values {
27     ($input:expr; $tlw:expr, $trw:expr, $brw:expr, $blw:expr ;
28                   $tlh:expr, $trh:expr, $brh:expr, $blh:expr) => {
29         let input = parse(BorderRadius::parse, $input)
30                           .expect(&format!("Failed parsing {} as border radius",
31                                   $input));
32         assert_eq!(::style_traits::ToCss::to_css_string(&input.top_left.0.width()), $tlw);
33         assert_eq!(::style_traits::ToCss::to_css_string(&input.top_right.0.width()), $trw);
34         assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_right.0.width()), $brw);
35         assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_left.0.width()), $blw);
36         assert_eq!(::style_traits::ToCss::to_css_string(&input.top_left.0.height()), $tlh);
37         assert_eq!(::style_traits::ToCss::to_css_string(&input.top_right.0.height()), $trh);
38         assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_right.0.height()), $brh);
39         assert_eq!(::style_traits::ToCss::to_css_string(&input.bottom_left.0.height()), $blh);
40     }
41 }
42 
43 #[test]
test_border_radius()44 fn test_border_radius() {
45     assert_border_radius_values!("10px";
46                                  "10px", "10px", "10px", "10px" ;
47                                  "10px", "10px", "10px", "10px");
48     assert_border_radius_values!("10px 20px";
49                                  "10px", "20px", "10px", "20px" ;
50                                  "10px", "20px", "10px", "20px");
51     assert_border_radius_values!("10px 20px 30px";
52                                  "10px", "20px", "30px", "20px" ;
53                                  "10px", "20px", "30px", "20px");
54     assert_border_radius_values!("10px 20px 30px 40px";
55                                  "10px", "20px", "30px", "40px" ;
56                                  "10px", "20px", "30px", "40px");
57     assert_border_radius_values!("10% / 20px";
58                                  "10%", "10%", "10%", "10%" ;
59                                  "20px", "20px", "20px", "20px");
60     assert_border_radius_values!("10px / 20px 30px";
61                                  "10px", "10px", "10px", "10px" ;
62                                  "20px", "30px", "20px", "30px");
63     assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px";
64                                  "10px", "20px", "30px", "40px" ;
65                                  "1px", "2px", "3px", "4px");
66     assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px";
67                                  "10px", "20px", "30px", "40px" ;
68                                  "1px", "2px", "3px", "4px");
69     assert_border_radius_values!("10px 20px 30px 40px / 1px 2px 3px 4px";
70                                  "10px", "20px", "30px", "40px" ;
71                                  "1px", "2px", "3px", "4px");
72     assert_border_radius_values!("10px -20px 30px 40px";
73                                  "10px", "10px", "10px", "10px";
74                                  "10px", "10px", "10px", "10px");
75     assert_border_radius_values!("10px 20px -30px 40px";
76                                  "10px", "20px", "10px", "20px";
77                                  "10px", "20px", "10px", "20px");
78     assert_border_radius_values!("10px 20px 30px -40px";
79                                  "10px", "20px", "30px", "20px";
80                                  "10px", "20px", "30px", "20px");
81     assert!(parse(BorderRadius::parse, "-10px 20px 30px 40px").is_err());
82 }
83 
84 #[test]
border_image_shorthand_should_parse_when_all_properties_specified()85 fn border_image_shorthand_should_parse_when_all_properties_specified() {
86     let input = "linear-gradient(red, blue) 30 30% 45 fill / 20px 40px / 10px round stretch";
87     let result = parse(border_image::parse_value, input).unwrap();
88 
89     assert_longhand!(result, border_image_source, "linear-gradient(red, blue)");
90     assert_longhand!(result, border_image_slice, "30 30% 45 fill");
91     assert_longhand!(result, border_image_width, "20px 40px");
92     assert_longhand!(result, border_image_outset, "10px");
93     assert_longhand!(result, border_image_repeat, "round stretch");
94 }
95 
96 #[test]
border_image_shorthand_should_parse_without_width()97 fn border_image_shorthand_should_parse_without_width() {
98     let input = "linear-gradient(red, blue) 30 30% 45 fill / / 10px round stretch";
99     let result = parse(border_image::parse_value, input).unwrap();
100 
101     assert_longhand!(result, border_image_source, "linear-gradient(red, blue)");
102     assert_longhand!(result, border_image_slice, "30 30% 45 fill");
103     assert_longhand!(result, border_image_outset, "10px");
104     assert_longhand!(result, border_image_repeat, "round stretch");
105     assert_initial!(result, border_image_width);
106 }
107 
108 #[test]
border_image_shorthand_should_parse_without_outset()109 fn border_image_shorthand_should_parse_without_outset() {
110     let input = "linear-gradient(red, blue) 30 30% 45 fill / 20px 40px round";
111     let result = parse(border_image::parse_value, input).unwrap();
112 
113     assert_longhand!(result, border_image_source, "linear-gradient(red, blue)");
114     assert_longhand!(result, border_image_slice, "30 30% 45 fill");
115     assert_longhand!(result, border_image_width, "20px 40px");
116     assert_longhand!(result, border_image_repeat, "round");
117     assert_initial!(result, border_image_outset);
118 }
119 
120 #[test]
border_image_shorthand_should_parse_without_width_or_outset()121 fn border_image_shorthand_should_parse_without_width_or_outset() {
122     let input = "linear-gradient(red, blue) 30 30% 45 fill round";
123     let result = parse(border_image::parse_value, input).unwrap();
124 
125     assert_longhand!(result, border_image_source, "linear-gradient(red, blue)");
126     assert_longhand!(result, border_image_slice, "30 30% 45 fill");
127     assert_longhand!(result, border_image_repeat, "round");
128     assert_initial!(result, border_image_width);
129     assert_initial!(result, border_image_outset);
130 }
131 
132 #[test]
border_image_shorthand_should_parse_with_just_source()133 fn border_image_shorthand_should_parse_with_just_source() {
134     let result = parse(border_image::parse_value, "linear-gradient(red, blue)").unwrap();
135 
136     assert_longhand!(result, border_image_source, "linear-gradient(red, blue)");
137     assert_initial!(result, border_image_slice);
138     assert_initial!(result, border_image_width);
139     assert_initial!(result, border_image_outset);
140     assert_initial!(result, border_image_repeat);
141 }
142 
143 #[test]
border_image_outset_should_error_on_negative_length()144 fn border_image_outset_should_error_on_negative_length() {
145     let result = parse(border_image_outset::parse, "-1em");
146     assert!(result.is_err());
147 }
148 
149 #[test]
border_image_outset_should_error_on_negative_number()150 fn border_image_outset_should_error_on_negative_number() {
151     let result = parse(border_image_outset::parse, "-15");
152     assert!(result.is_err());
153 }
154 
155 #[test]
border_image_outset_should_return_number_on_plain_zero()156 fn border_image_outset_should_return_number_on_plain_zero() {
157     let result = parse(border_image_outset::parse, "0");
158     assert_eq!(result.unwrap(), parse_longhand!(border_image_outset, "0"));
159 }
160 
161 #[test]
border_image_outset_should_return_length_on_length_zero()162 fn border_image_outset_should_return_length_on_length_zero() {
163     let result = parse(border_image_outset::parse, "0em");
164     assert_eq!(result.unwrap(), parse_longhand!(border_image_outset, "0em"));
165 }
166 
167 #[test]
test_border_style()168 fn test_border_style() {
169     use style::values::specified::BorderStyle;
170 
171     assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"none"#);
172     assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"hidden"#);
173     assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"solid"#);
174     assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"double"#);
175     assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"dotted"#);
176     assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"dashed"#);
177     assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"groove"#);
178     assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"ridge"#);
179     assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"inset"#);
180     assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"outset"#);
181 }
182 
183 #[test]
test_border_spacing()184 fn test_border_spacing() {
185     use style::properties::longhands::border_spacing;
186 
187     assert_parser_exhausted!(border_spacing::parse, "1px rubbish", false);
188     assert_parser_exhausted!(border_spacing::parse, "1px", true);
189     assert_parser_exhausted!(border_spacing::parse, "1px 2px", true);
190 }
191