use whisker_css::data_type::{
Angle, CalcExpr, Color, ColorStop, CssString, FitContent, Gradient, Length, LengthPercentage,
LinearDirection, MaxContent, NamedColor, Number, Percentage, RadialShape, StopPosition, Time,
};
use whisker_css::data_type_ext::{
EasingFunction, Integer, Position, PositionKeyword, StepPosition,
};
use whisker_css::ext::*;
use whisker_css::shorthand::padding_margin::MarginValue;
use whisker_css::shorthand::{Animation, Background, BackgroundLayer, Border, Transition};
use whisker_css::value::{
BorderRadius, FlexBasis, GridLine, GridTemplate, ImageRef, LineHeight, Repeated, Size,
};
use whisker_css::{Css, ToCss};
#[test]
#[allow(clippy::clone_on_copy)]
fn debug_and_clone_pass_through() {
let n = Number(1.0);
let p = Percentage(50.0);
let l = Length::Px(8.0);
let lp = LengthPercentage::Length(l);
let a = Angle::Deg(45.0);
let t = Time::Ms(300.0);
let cs = CssString::new("x");
let c = Color::Named(NamedColor::Red);
let g = Gradient::linear_to_bottom([ColorStop::new(c)]);
let f = FitContent::with_limit(l);
let m = MaxContent;
let calc = CalcExpr::value(l);
let i = Integer(2);
let pos = Position::Keyword(PositionKeyword::Center);
let stop = StopPosition::Number(0.5);
let easing = EasingFunction::Steps(2, StepPosition::JumpEnd);
let stop_pos = StepPosition::JumpStart;
let lin = LinearDirection::ToBottom;
let radial = RadialShape::Circle;
let _ = (
n.clone(),
p.clone(),
l,
lp.clone(),
a,
t,
cs.clone(),
c,
g.clone(),
f.clone(),
m,
calc.clone(),
i,
pos.clone(),
stop.clone(),
easing,
stop_pos,
lin,
radial.clone(),
);
let _ = format!(
"{:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?} {:?}",
n, p, l, lp, a, t, cs, c, g, f, m, calc, i, pos, stop, easing, stop_pos, lin, radial,
);
}
#[test]
fn length_zero_via_constructor_helpers() {
let z = whisker_css::ext::ZERO;
assert!(z.is_zero());
assert!(0.px().is_zero());
}
#[test]
fn length_percentage_calc_all_operators() {
let e = CalcExpr::value(px(10))
.add(CalcExpr::value(20.percent()))
.sub(CalcExpr::value(px(5)))
.mul(CalcExpr::number(2.0))
.div(CalcExpr::number(4.0));
let css = LengthPercentage::calc(e).to_css_string();
assert!(css.starts_with("calc("));
assert!(css.ends_with(")"));
}
#[test]
fn color_hex_alpha_opaque_path() {
assert_eq!(
Color::hex_alpha(0xFF0000FF).to_css_string(),
"rgb(255, 0, 0)"
);
}
#[test]
fn color_rgb_constructor_path() {
assert_eq!(Color::rgb(1, 2, 3).to_css_string(), "rgb(1, 2, 3)");
}
#[test]
fn color_named_round_trip_via_from() {
let c: Color = NamedColor::Red.into();
assert_eq!(c.to_css_string(), "red");
}
#[test]
fn gradient_radial_with_shape_keywords() {
let g = Gradient::Radial {
shape: RadialShape::Ellipse,
stops: vec![ColorStop::new(Color::Named(NamedColor::Red))],
};
assert!(g.to_css_string().contains("ellipse"));
}
#[test]
fn gradient_color_stop_at_constructor() {
let s = ColorStop::at(Color::Named(NamedColor::Red), Percentage(20.0));
assert_eq!(s.to_css_string(), "red 20%");
}
#[test]
fn css_string_via_string_from() {
let s: CssString = String::from("y").into();
assert_eq!(s.to_css_string(), "\"y\"");
let s2: CssString = "z".into();
assert_eq!(s2.to_css_string(), "\"z\"");
assert_eq!(s2.as_str(), "z");
}
#[test]
fn integer_constructor_paths() {
assert_eq!(Integer::new(5).value(), 5);
assert_eq!(Integer::from(3).to_css_string(), "3");
}
#[test]
fn percentage_constructor_paths() {
assert_eq!(Percentage::new(33.0).value(), 33.0);
let from_i: Percentage = 4.into();
let from_f: Percentage = 4.0_f32.into();
assert_eq!(from_i.to_css_string(), "4%");
assert_eq!(from_f.to_css_string(), "4%");
}
#[test]
fn easing_step_position_legacy_aliases() {
let s = EasingFunction::Steps(2, StepPosition::Start);
assert_eq!(s.to_css_string(), "steps(2, start)");
let s = EasingFunction::Steps(2, StepPosition::End);
assert_eq!(s.to_css_string(), "steps(2, end)");
}
#[test]
fn position_mixed_keyword_offset() {
let p = Position::Mixed(PositionKeyword::Bottom, px(8).into());
assert_eq!(p.to_css_string(), "bottom 8px");
}
#[test]
fn position_keyword_each_variant() {
use PositionKeyword::*;
for k in [Left, Right, Top, Bottom, Center] {
assert!(!Position::Keyword(k).to_css_string().is_empty());
}
}
#[test]
fn image_ref_url_then_gradient_then_none() {
let url = ImageRef::Url(CssString::new("a.png"));
let gradient: ImageRef =
Gradient::linear_to_bottom([ColorStop::new(NamedColor::Red.into())]).into();
let none = ImageRef::None;
assert!(url.to_css_string().contains("url"));
assert!(gradient.to_css_string().contains("linear-gradient"));
assert!(none.to_css_string() == "none");
}
#[test]
fn flex_basis_from_paths() {
let from_lp: FlexBasis = LengthPercentage::Length(px(8)).into();
let from_p: FlexBasis = 20.percent().into();
let from_l: FlexBasis = px(8).into();
for f in [from_lp, from_p, from_l] {
assert!(!f.to_css_string().is_empty());
}
}
#[test]
fn line_height_from_paths() {
let from_lp: LineHeight = LengthPercentage::Length(px(20)).into();
let from_p: LineHeight = 150.percent().into();
let from_l: LineHeight = px(20).into();
let from_f: LineHeight = 1.5_f32.into();
for h in [from_lp, from_p, from_l, from_f] {
assert!(!h.to_css_string().is_empty());
}
}
#[test]
fn size_from_paths_all() {
let from_l: Size = px(8).into();
let from_p: Size = 50.percent().into();
let from_lp: Size = LengthPercentage::Length(px(8)).into();
let from_mc: Size = MaxContent.into();
let from_fc: Size = FitContent::keyword().into();
for s in [from_l, from_p, from_lp, from_mc, from_fc] {
assert!(!s.to_css_string().is_empty());
}
assert_eq!(Size::None.to_css_string(), "none");
}
#[test]
fn margin_value_all_from_impls() {
let from_l: MarginValue = px(8).into();
let from_p: MarginValue = 25.percent().into();
let from_lp: MarginValue = LengthPercentage::Length(px(8)).into();
let auto = MarginValue::Auto;
assert_eq!(from_l.to_css_string(), "8px");
assert_eq!(from_p.to_css_string(), "25%");
assert_eq!(from_lp.to_css_string(), "8px");
assert_eq!(auto.to_css_string(), "auto");
}
#[test]
fn border_radius_all_constructor() {
let r = BorderRadius::all(px(4));
assert!(r.to_css_string().contains("4px"));
}
#[test]
fn grid_line_all_variants() {
assert!(matches!(GridLine::Auto, GridLine::Auto));
assert_eq!(GridLine::Number(0).to_css_string(), "0");
assert_eq!(GridLine::Span(1).to_css_string(), "span 1");
}
#[test]
fn grid_template_empty_then_extend() {
let tracks: Vec<String> = Vec::new();
let t1 = GridTemplate::tracks(tracks);
assert!(t1.to_css_string().is_empty());
let t2 = GridTemplate::tracks(["1fr".to_string(), "2fr".to_string()]);
assert_eq!(t2.to_css_string(), "1fr 2fr");
}
#[test]
fn repeated_empty_collection() {
let v: Vec<Length> = Vec::new();
let r: Repeated<Length> = Repeated::new(v);
assert!(r.to_css_string().is_empty());
}
#[test]
fn animation_only_a_few_fields_set() {
let s = Css::new().animation(Animation::new("x"));
assert_eq!(s.to_string(), "animation: x;");
let s = Css::new().animation(Animation::new("y").delay(50.ms()));
assert!(s.to_string().contains("50ms"));
}
#[test]
fn transition_skip_some_fields() {
let t = Transition::new(whisker_css::keyword::TransitionPropertyKind::All).delay(0.s());
let s = Css::new().transition(t);
assert!(s.to_string().contains("0s"));
}
#[test]
fn background_color_only_via_struct() {
let s = Css::new().background(Background::new().color(Color::Named(NamedColor::Black)));
assert_eq!(s.to_string(), "background: black;");
}
#[test]
fn background_layer_image_only_then_color() {
let s = Css::new().background(
Background::new()
.layer(BackgroundLayer::new(ImageRef::None))
.color(Color::Named(NamedColor::Black)),
);
assert!(s.to_string().contains("none"));
}
#[test]
fn border_constructor_default() {
let b = Border::new();
assert!(b.width.is_none() && b.style.is_none() && b.color.is_none());
}
#[test]
fn calc_expr_value_and_number_constructors() {
let v = CalcExpr::value(px(4));
let n = CalcExpr::number(2.0);
let _ = LengthPercentage::calc(v.clone().mul(n.clone()));
assert!(v.to_css_string().contains("4px"));
assert!(n.to_css_string() == "2");
}
#[test]
fn linear_direction_keyword_directions_in_gradient() {
use LinearDirection::*;
for d in [
ToTop,
ToRight,
ToBottom,
ToLeft,
ToTopRight,
ToTopLeft,
ToBottomRight,
ToBottomLeft,
] {
let g = Gradient::Linear {
direction: d,
stops: vec![ColorStop::new(Color::Named(NamedColor::Red))],
};
assert!(g.to_css_string().contains("linear-gradient"));
}
let g = Gradient::Linear {
direction: LinearDirection::Angle(45.deg()),
stops: vec![ColorStop::new(Color::Named(NamedColor::Red))],
};
assert!(g.to_css_string().contains("45deg"));
}
#[test]
fn fit_content_keyword_path() {
let fc = FitContent::keyword();
assert_eq!(fc.to_css_string(), "fit-content");
}
#[test]
fn length_each_unit_zero_path() {
assert!(Length::Px(0.0).is_zero());
assert!(Length::Rpx(0.0).is_zero());
assert!(Length::Ppx(0.0).is_zero());
assert!(Length::Em(0.0).is_zero());
assert!(Length::Rem(0.0).is_zero());
assert!(Length::Vh(0.0).is_zero());
assert!(Length::Vw(0.0).is_zero());
}