use hypen_engine::ir::NodeId;
use hypen_engine::reconcile::Patch;
use indexmap::indexmap;
use serde_json::json;
fn test_node_id() -> NodeId {
NodeId::default()
}
#[test]
fn test_create_patch_basic() {
let node_id = test_node_id();
let props = indexmap! {
"text".to_string() => json!("Hello"),
"color".to_string() => json!("blue"),
};
let patch = Patch::create(node_id, "Text".to_string(), props.clone());
match patch {
Patch::Create {
id,
element_type,
props: patch_props,
} => {
assert!(!id.is_empty());
assert_eq!(element_type, "Text");
assert_eq!(patch_props.get("text"), Some(&json!("Hello")));
assert_eq!(patch_props.get("color"), Some(&json!("blue")));
}
_ => panic!("Expected Create patch"),
}
}
#[test]
fn test_set_prop_patch() {
let node_id = test_node_id();
let patch = Patch::set_prop(node_id, "fontSize".to_string(), json!(18));
match patch {
Patch::SetProp { id, name, value } => {
assert!(!id.is_empty());
assert_eq!(name, "fontSize");
assert_eq!(value, json!(18));
}
_ => panic!("Expected SetProp patch"),
}
}
#[test]
fn test_set_text_patch() {
let node_id = test_node_id();
let patch = Patch::set_text(node_id, "Updated text".to_string());
match patch {
Patch::SetText { id, text } => {
assert!(!id.is_empty());
assert_eq!(text, "Updated text");
}
_ => panic!("Expected SetText patch"),
}
}
#[test]
fn test_insert_patch_without_before() {
let parent_id = test_node_id();
let child_id = test_node_id();
let patch = Patch::insert(parent_id, child_id, None);
match patch {
Patch::Insert {
parent_id: parent,
id,
before_id,
} => {
assert!(!parent.is_empty());
assert!(!id.is_empty());
assert_eq!(before_id, None);
}
_ => panic!("Expected Insert patch"),
}
}
#[test]
fn test_insert_patch_with_before() {
let parent_id = test_node_id();
let child_id = test_node_id();
let sibling_id = test_node_id();
let patch = Patch::insert(parent_id, child_id, Some(sibling_id));
match patch {
Patch::Insert {
parent_id: parent,
id,
before_id,
} => {
assert!(!parent.is_empty());
assert!(!id.is_empty());
assert!(before_id.is_some());
}
_ => panic!("Expected Insert patch"),
}
}
#[test]
fn test_insert_root_patch() {
let node_id = test_node_id();
let patch = Patch::insert_root(node_id);
match patch {
Patch::Insert {
parent_id,
id,
before_id,
} => {
assert_eq!(parent_id, "root");
assert!(!id.is_empty());
assert_eq!(before_id, None);
}
_ => panic!("Expected Insert patch"),
}
}
#[test]
fn test_move_patch() {
let parent_id = test_node_id();
let node_id = test_node_id();
let before_id = test_node_id();
let patch = Patch::move_node(parent_id, node_id, Some(before_id));
match patch {
Patch::Move {
parent_id: parent,
id,
before_id: before,
} => {
assert!(!parent.is_empty());
assert!(!id.is_empty());
assert!(before.is_some());
}
_ => panic!("Expected Move patch"),
}
}
#[test]
fn test_remove_patch() {
let node_id = test_node_id();
let patch = Patch::remove(node_id);
match patch {
Patch::Remove { id } => {
assert!(!id.is_empty());
}
_ => panic!("Expected Remove patch"),
}
}
#[test]
fn test_patch_clone() {
let node_id = test_node_id();
let original = Patch::set_text(node_id, "Original".to_string());
let cloned = original.clone();
match (&original, &cloned) {
(Patch::SetText { text: t1, .. }, Patch::SetText { text: t2, .. }) => {
assert_eq!(t1, t2);
}
_ => panic!("Expected SetText patches"),
}
}
#[test]
fn test_create_patch_with_empty_props() {
let node_id = test_node_id();
let props = indexmap! {};
let patch = Patch::create(node_id, "EmptyElement".to_string(), props);
match patch {
Patch::Create {
element_type,
props,
..
} => {
assert_eq!(element_type, "EmptyElement");
assert_eq!(props.len(), 0);
}
_ => panic!("Expected Create patch"),
}
}
#[test]
fn test_serialize_create_patch() {
let node_id = test_node_id();
let props = indexmap! {
"text".to_string() => json!("Hello"),
};
let patch = Patch::create(node_id, "Text".to_string(), props);
let json = serde_json::to_value(&patch).unwrap();
assert_eq!(json["type"], "create");
assert!(json.get("id").is_some());
assert!(json.get("elementType").is_some() || json.get("element_type").is_some());
assert!(json.get("props").is_some());
}
#[test]
fn test_serialize_set_prop_patch() {
let node_id = test_node_id();
let patch = Patch::set_prop(node_id, "color".to_string(), json!("red"));
let json = serde_json::to_value(&patch).unwrap();
assert_eq!(json["type"], "setProp");
assert!(json["id"].is_string());
assert_eq!(json["name"], "color");
assert_eq!(json["value"], "red");
}
#[test]
fn test_serialize_insert_patch() {
let parent_id = test_node_id();
let child_id = test_node_id();
let patch = Patch::insert(parent_id, child_id, None);
let json = serde_json::to_value(&patch).unwrap();
assert_eq!(json["type"], "insert");
assert!(json.get("parentId").is_some() || json.get("parent_id").is_some());
assert!(json.get("id").is_some());
let before_field = json.get("beforeId").or_else(|| json.get("before_id"));
assert!(before_field.is_some());
}
#[test]
fn test_deserialize_patch() {
let json = json!({
"type": "remove",
"id": "42"
});
let patch: Patch = serde_json::from_value(json).unwrap();
match patch {
Patch::Remove { id } => {
assert_eq!(id, "42");
}
_ => panic!("Expected Remove patch"),
}
}
#[test]
fn test_remove_prop_patch() {
let node_id = test_node_id();
let patch = Patch::remove_prop(node_id, "color".to_string());
match patch {
Patch::RemoveProp { id, name } => {
assert!(!id.is_empty());
assert_eq!(name, "color");
}
_ => panic!("Expected RemoveProp patch"),
}
}
#[test]
fn test_serialize_remove_prop_patch() {
let node_id = test_node_id();
let patch = Patch::remove_prop(node_id, "color".to_string());
let json = serde_json::to_value(&patch).unwrap();
assert_eq!(json["type"], "removeProp");
assert!(json["id"].is_string());
assert_eq!(json["name"], "color");
}
#[test]
fn test_deserialize_remove_prop_patch() {
let json = json!({
"type": "removeProp",
"id": "99",
"name": "color"
});
let patch: Patch = serde_json::from_value(json).unwrap();
match patch {
Patch::RemoveProp { id, name } => {
assert_eq!(id, "99");
assert_eq!(name, "color");
}
_ => panic!("Expected RemoveProp patch"),
}
}