use azul_css::parser2::new_from_str;
use azul_css::css::{CssPathSelector, CssPathPseudoSelector};
use azul_css::dynamic_selector::DynamicSelector;
use azul_css::dynamic_selector::OsCondition;
#[test]
fn test_nested_pseudo_class_hover() {
let css = r#"
.button {
color: blue;
:hover {
color: red;
}
}
"#;
let (result, warnings) = new_from_str(css);
for w in &warnings {
eprintln!("Warning: {:?}", w);
}
let rules: Vec<_> = result.rules().collect();
assert!(rules.len() >= 1, "Expected at least 1 rule, got {}", rules.len());
let hover_rule = rules.iter().find(|r| {
r.path.selectors.iter().any(|s| matches!(s, CssPathSelector::PseudoSelector(CssPathPseudoSelector::Hover)))
});
assert!(hover_rule.is_some(), "Expected to find a :hover rule");
let hover_rule = hover_rule.unwrap();
assert!(hover_rule.path.selectors.iter().any(|s| {
matches!(s, CssPathSelector::Class(c) if c.as_str() == "button")
}), "Expected .button in the path");
}
#[test]
fn test_nested_class_selector() {
let css = r#"
.outer {
.inner {
color: red;
}
}
"#;
let (result, warnings) = new_from_str(css);
for w in &warnings {
eprintln!("Warning: {:?}", w);
}
let rules: Vec<_> = result.rules().collect();
assert!(rules.len() >= 1, "Expected at least 1 rule");
let inner_rule = rules.iter().find(|r| {
r.path.selectors.iter().any(|s| matches!(s, CssPathSelector::Class(c) if c.as_str() == "inner"))
});
assert!(inner_rule.is_some(), "Expected to find .inner rule");
let inner_rule = inner_rule.unwrap();
assert!(inner_rule.path.selectors.iter().any(|s| {
matches!(s, CssPathSelector::Class(c) if c.as_str() == "outer")
}), "Expected .outer in the path");
}
#[test]
fn test_nested_at_os() {
let css = r#"
.button {
color: blue;
@os linux {
background: green;
}
}
"#;
let (result, warnings) = new_from_str(css);
for w in &warnings {
eprintln!("Warning: {:?}", w);
}
let rules: Vec<_> = result.rules().collect();
let os_rules: Vec<_> = rules.iter().filter(|r| {
r.conditions.iter().any(|c| matches!(c, DynamicSelector::Os(_)))
}).collect();
assert!(!os_rules.is_empty(), "Expected at least one rule with OS condition");
let linux_rule = os_rules.iter().find(|r| {
r.conditions.iter().any(|c| matches!(c, DynamicSelector::Os(OsCondition::Linux)))
});
assert!(linux_rule.is_some(), "Expected to find a Linux OS rule");
}
#[test]
fn test_deeply_nested_selectors() {
let css = r#"
.a {
.b {
.c {
color: red;
}
}
}
"#;
let (result, warnings) = new_from_str(css);
for w in &warnings {
eprintln!("Warning: {:?}", w);
}
let rules: Vec<_> = result.rules().collect();
let c_rule = rules.iter().find(|r| {
r.path.selectors.iter().any(|s| matches!(s, CssPathSelector::Class(c) if c.as_str() == "c"))
});
assert!(c_rule.is_some(), "Expected to find .c rule");
let c_rule = c_rule.unwrap();
assert!(c_rule.path.selectors.iter().any(|s| {
matches!(s, CssPathSelector::Class(c) if c.as_str() == "a")
}), "Expected .a in the path");
assert!(c_rule.path.selectors.iter().any(|s| {
matches!(s, CssPathSelector::Class(c) if c.as_str() == "b")
}), "Expected .b in the path");
}
#[test]
fn test_nested_comma_selectors() {
let css = r#"
.parent {
:hover, :focus {
color: red;
}
}
"#;
let (result, warnings) = new_from_str(css);
for w in &warnings {
eprintln!("Warning: {:?}", w);
}
let rules: Vec<_> = result.rules().collect();
let hover_rule = rules.iter().find(|r| {
r.path.selectors.iter().any(|s| matches!(s, CssPathSelector::PseudoSelector(CssPathPseudoSelector::Hover)))
});
let focus_rule = rules.iter().find(|r| {
r.path.selectors.iter().any(|s| matches!(s, CssPathSelector::PseudoSelector(CssPathPseudoSelector::Focus)))
});
assert!(hover_rule.is_some(), "Expected to find :hover rule");
assert!(focus_rule.is_some(), "Expected to find :focus rule");
}
#[test]
fn test_mixed_declarations_and_nested() {
let css = r#"
.button {
color: blue;
:hover {
color: red;
}
background: white;
}
"#;
let (_result, warnings) = new_from_str(css);
for w in &warnings {
eprintln!("Warning: {:?}", w);
}
assert!(warnings.iter().all(|w| !format!("{:?}", w).contains("Error")));
}
#[test]
fn test_at_os_top_level() {
let css = r#"
@os linux {
.button {
color: red;
}
}
"#;
let (result, warnings) = new_from_str(css);
for w in &warnings {
eprintln!("Warning: {:?}", w);
}
let rules: Vec<_> = result.rules().collect();
let linux_rule = rules.iter().find(|r| {
r.conditions.iter().any(|c| matches!(c, DynamicSelector::Os(OsCondition::Linux)))
});
assert!(linux_rule.is_some(), "Expected to find a Linux OS rule");
let linux_rule = linux_rule.unwrap();
assert!(linux_rule.path.selectors.iter().any(|s| {
matches!(s, CssPathSelector::Class(c) if c.as_str() == "button")
}), "Expected .button in the path");
}