use super::*;
use crate::ImageHandle;
#[test]
fn spacingTupleUsesCssOrder() {
let container = Container::<NoAction>::new()
.padding((1, 2, 3, 4))
.margin((5, 6, 7, 8));
let padding = container.padding.as_ref().unwrap();
let margin = container.margin.as_ref().unwrap();
assert_eq!(padding.top, 1);
assert_eq!(padding.right, 2);
assert_eq!(padding.bottom, 3);
assert_eq!(padding.left, 4);
assert_eq!(margin.top, 5);
assert_eq!(margin.right, 6);
assert_eq!(margin.bottom, 7);
assert_eq!(margin.left, 8);
}
#[test]
fn spacingNumberAppliesAllSides() {
let container = Container::<NoAction>::new().padding(16).margin(24);
assert_eq!(container.padding, Some(Spacing::all(16)));
assert_eq!(container.margin, Some(Spacing::all(24)));
}
#[test]
fn childrenClosureBuildsNodesInOrder() {
let root = Container::<NoAction>::new().children(|ui| {
ui.text("Title").class("title");
ui.container().class("card").empty();
});
assert_eq!(root.children.len(), 2);
assert!(matches!(root.children[0], UiNode::Text(_)));
assert!(matches!(root.children[1], UiNode::Container(_)));
}
#[test]
fn uiNodeOrderIncludesImageAndButton() {
let image = ImageHandle::new("logo.svg");
let root = Container::<NoAction>::new().children(|ui| {
ui.text("Title");
ui.image(image);
ui.button("Save");
});
assert!(matches!(root.children[0], UiNode::Text(_)));
assert!(matches!(root.children[1], UiNode::Image(_)));
assert!(matches!(root.children[2], UiNode::Button(_)));
}
#[test]
fn classExtendsBaseStyle() {
let theme = AppTheme::new()
.class(Component::Button, "base", |style| {
style.radius(12);
style.padding(8);
})
.class(Component::Button, "primary", |style| {
style.extends("base");
style.background(Color::rgb(0.1, 0.2, 0.8));
});
let style = theme.styleFor(Component::Button, Some("primary"));
assert_eq!(style.radius, Some(12));
assert_eq!(style.padding, Some(Spacing::all(8)));
assert_eq!(style.background, Some(Color::rgb(0.1, 0.2, 0.8)));
}
#[test]
fn localStyleOverridesThemeClass() {
let theme = AppTheme::new().class(Component::Container, "card", |style| {
style.radius(12);
style.background(Color::rgb(0.1, 0.1, 0.1));
});
let mut style = theme.styleFor(Component::Container, Some("card"));
let mut local = Style::default();
local.radius(24);
mergeStyle(&mut style, &local);
assert_eq!(style.radius, Some(24));
assert_eq!(style.background, Some(Color::rgb(0.1, 0.1, 0.1)));
}
#[test]
fn stateStyleExtendsBaseClass() {
let theme = AppTheme::new()
.class(Component::Button, "primary", |style| {
style.background(Color::rgb(0.0, 0.2, 1.0));
style.color(Color::rgb(1.0, 1.0, 1.0));
})
.class(Component::Button, "primary:hover", |style| {
style.background(Color::rgb(0.2, 0.4, 1.0));
});
let style = theme.styleForState(Component::Button, Some("primary"), VisualState::Hover);
assert_eq!(style.background, Some(Color::rgb(0.2, 0.4, 1.0)));
assert_eq!(style.color, Some(Color::rgb(1.0, 1.0, 1.0)));
}
#[derive(Clone, Debug, PartialEq, Eq)]
enum TestAction {
Click,
Hover,
}
#[test]
fn buttonStoresTypedActions() {
let root = Container::<TestAction>::new().children(|ui| {
ui.button("Run")
.onClick(TestAction::Click)
.onHover(TestAction::Hover);
});
let UiNode::Button(button) = &root.children[0] else {
panic!("expected button");
};
assert_eq!(button.interactions.click, Some(TestAction::Click));
assert_eq!(button.interactions.hover, Some(TestAction::Hover));
assert!(button.interactions.hasLocalInput());
}
#[test]
fn textInputStoresPayloadCallbacks() {
let root = Container::<TestAction>::new().children(|ui| {
ui.textInput("hello")
.placeholder("Name")
.onChange(|_| TestAction::Click);
});
let UiNode::TextInput(textInput) = &root.children[0] else {
panic!("expected text input");
};
assert_eq!(textInput.value, "hello");
assert_eq!(textInput.placeholder.as_deref(), Some("Name"));
assert!(textInput.onChange.is_some());
}
#[test]
fn checkboxStoresPayloadCallback() {
let root = Container::<TestAction>::new().children(|ui| {
ui.checkbox(true)
.text("Enabled")
.onToggle(|_| TestAction::Click);
});
let UiNode::Checkbox(checkbox) = &root.children[0] else {
panic!("expected checkbox");
};
assert!(checkbox.checked);
assert_eq!(checkbox.text.as_deref(), Some("Enabled"));
assert!(checkbox.onToggle.is_some());
}
#[test]
fn keyedNodesKeepIdentityWhenReordered() {
let left = UiNode::<NoAction>::Text(Text::new("A").key("a"));
let right = UiNode::<NoAction>::Text(Text::new("B").key("a"));
let different = UiNode::<NoAction>::Button(Button::new("A").key("a"));
assert!(left.sameIdentity(&right));
assert!(!left.sameIdentity(&different));
}