use super::*;
use crate::TuiDom;
use crate::layout::{Display, Flow};
use crate::style::{Stylesheet, TuiStyle};
use rdom_core::NodeId;
use rdom_style::property_dispatch;
fn cascade_div(sheet: &Stylesheet) -> ComputedStyle {
let mut dom: TuiDom = TuiDom::new();
let root = dom.root();
let div: NodeId = dom.create_element("div");
dom.append_child(root, div).unwrap();
dom.cascade(sheet);
computed_of(&dom, div)
}
fn style_of(decls: &[(&str, &str)]) -> TuiStyle {
let mut style = TuiStyle::new();
for (name, value) in decls {
property_dispatch::set(name, value, &mut style)
.unwrap_or_else(|e| panic!("{name}: {value}: {e:?}"));
}
style
}
const PERTURB: &[(&str, &str)] = &[
("color", "red"),
("background-color", "blue"),
("border-color", "green"),
("font-weight", "bold"),
("font-style", "italic"),
("text-decoration", "underline"),
("opacity", "0.5"),
("display", "inline-flex"),
("flex-direction", "row"),
("white-space", "pre"),
("user-select", "none"),
("pointer-events", "none"),
("caret-color", "transparent"),
("caret-text-color", "red"),
("overflow-x", "scroll"),
("overflow-y", "hidden"),
("scrollbar-gutter", "stable"),
("scroll-behavior", "smooth"),
("width", "10"),
("height", "5"),
("min-width", "2"),
("max-width", "20"),
("min-height", "1"),
("max-height", "9"),
("aspect-ratio", "2 / 1"),
("gap", "1"),
("flex-shrink", "0"),
("padding", "1"),
("margin", "1"),
("border", "solid"),
("border-collapse", "collapse"),
("position", "relative"),
("top", "1"),
("right", "1"),
("bottom", "1"),
("left", "1"),
("z-index", "3"),
("transition-property", "color"),
("transition-duration", "100ms"),
("transition-timing-function", "ease-in"),
("transition-delay", "10ms"),
("counter-reset", "a"),
("counter-increment", "a"),
];
#[test]
fn initial_keyword_yields_the_initial_computed_value_for_every_property() {
let perturbed = style_of(PERTURB);
let mut reset = TuiStyle::new();
for name in property_dispatch::property_names() {
property_dispatch::set(name, "initial", &mut reset)
.unwrap_or_else(|e| panic!("{name}: initial: {e:?}"));
}
let moved = cascade_div(&Stylesheet::bare().rule_unchecked("div", perturbed.clone()));
let got = cascade_div(
&Stylesheet::bare()
.rule_unchecked("div", perturbed)
.rule_unchecked("div", reset),
);
let ComputedStyle {
fg,
bg,
border_fg,
modifiers,
opacity,
width,
height,
min_width,
max_width,
min_height,
max_height,
aspect_ratio,
padding,
margin,
gap,
flex_shrink,
border,
border_collapse,
border_collapse_declared: _,
direction,
overflow_x,
overflow_y,
scrollbar_gutter,
scroll_behavior,
display,
flow,
establishes_new_bfc: _,
white_space,
user_select,
pointer_events,
caret_color,
caret_text_color,
content: _,
position,
top,
right,
bottom,
left,
z_index,
transition_property,
transition_duration,
transition_timing_function,
transition_delay,
counter_reset,
counter_increment,
vars: _,
} = ComputedStyle::initial();
macro_rules! check {
($($field:ident),* $(,)?) => {$(
assert_ne!(moved.$field, $field, "PERTURB leaves `{}` at its initial value", stringify!($field));
assert_eq!(got.$field, $field, "`initial` for `{}`", stringify!($field));
)*};
}
check!(
fg,
bg,
border_fg,
modifiers,
opacity,
width,
height,
min_width,
max_width,
min_height,
max_height,
aspect_ratio,
padding,
margin,
gap,
flex_shrink,
border,
border_collapse,
direction,
overflow_x,
overflow_y,
scrollbar_gutter,
scroll_behavior,
display,
flow,
white_space,
user_select,
pointer_events,
caret_color,
caret_text_color,
position,
top,
right,
bottom,
left,
z_index,
transition_property,
transition_duration,
transition_timing_function,
transition_delay,
counter_reset,
counter_increment,
);
}
#[test]
fn display_inherit_takes_the_parents_inner_display_too() {
let mut dom: TuiDom = TuiDom::new();
let root = dom.root();
let parent = dom.create_element("section");
let child = dom.create_element("div");
dom.append_child(parent, child).unwrap();
dom.append_child(root, parent).unwrap();
let sheet = Stylesheet::bare()
.rule_unchecked("section", style_of(&[("display", "flex")]))
.rule_unchecked("div", style_of(&[("display", "inherit")]));
dom.cascade(&sheet);
let c = computed_of(&dom, child);
assert_eq!((c.display, c.flow), (Display::Block, Flow::Flex));
}