use hypen_engine::{
ir::{Element, Value},
lifecycle::{Module, ModuleInstance},
reactive::{Binding, Scheduler},
reconcile::InstanceTree,
render::render_dirty_nodes,
};
use serde_json::json;
#[test]
fn test_render_dirty_nodes_generates_patches_for_changed_binding() {
let mut tree = InstanceTree::new();
let mut element = Element::new("Text");
element.props.insert(
"text".to_string(),
Value::Binding(Binding::state(vec!["count".to_string()])),
);
let initial_state = json!({"count": 0});
let node_id = tree.create_node(&element, &initial_state);
tree.set_root(node_id);
let module_meta = Module::new("TestModule");
let updated_state = json!({"count": 1});
let module = ModuleInstance::new(module_meta, updated_state);
let mut scheduler = Scheduler::new();
scheduler.mark_dirty(node_id);
let patches = render_dirty_nodes(&mut scheduler, &mut tree, Some(&module));
assert!(
!patches.is_empty(),
"Should generate patches when binding value changes"
);
assert!(
patches
.iter()
.any(|p| matches!(p, hypen_engine::reconcile::Patch::SetProp { .. })),
"Should have SetProp patch for changed text"
);
}
#[test]
fn test_render_dirty_nodes_no_patches_when_value_unchanged() {
let mut tree = InstanceTree::new();
let mut element = Element::new("Text");
element.props.insert(
"text".to_string(),
Value::Binding(Binding::state(vec!["message".to_string()])),
);
let state = json!({"message": "Hello"});
let node_id = tree.create_node(&element, &state);
let module_meta = Module::new("TestModule");
let module = ModuleInstance::new(module_meta, state);
let mut scheduler = Scheduler::new();
scheduler.mark_dirty(node_id);
let patches = render_dirty_nodes(&mut scheduler, &mut tree, Some(&module));
assert!(
patches.is_empty(),
"Should not generate patches when value is unchanged"
);
}
#[test]
fn test_render_dirty_nodes_multiple_props_change() {
let mut tree = InstanceTree::new();
let mut element = Element::new("Text");
element.props.insert(
"text".to_string(),
Value::Binding(Binding::state(vec!["user".to_string(), "name".to_string()])),
);
element.props.insert(
"color".to_string(),
Value::Binding(Binding::state(vec![
"theme".to_string(),
"color".to_string(),
])),
);
let initial = json!({
"user": {"name": "Alice"},
"theme": {"color": "blue"}
});
let node_id = tree.create_node(&element, &initial);
let updated = json!({
"user": {"name": "Bob"},
"theme": {"color": "red"}
});
let module_meta = Module::new("TestModule");
let module = ModuleInstance::new(module_meta, updated);
let mut scheduler = Scheduler::new();
scheduler.mark_dirty(node_id);
let patches = render_dirty_nodes(&mut scheduler, &mut tree, Some(&module));
let set_prop_count = patches
.iter()
.filter(|p| matches!(p, hypen_engine::reconcile::Patch::SetProp { .. }))
.count();
assert_eq!(
set_prop_count, 2,
"Should generate SetProp patch for each changed prop"
);
}