use serde_json::json;
use value_ext::{AsType, JsonValueExt};
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
#[test]
fn test_value_insert_ok() -> Result<()> {
let mut value = json!({"tokens": 3});
let fx_node_value = "hello";
value.x_insert("/happy/word", fx_node_value)?;
let actual_value: String = value.x_get("/happy/word")?;
assert_eq!(actual_value.as_str(), fx_node_value);
Ok(())
}
#[test]
fn test_value_walk_ok() -> Result<()> {
let mut root_value = json!(
{
"tokens": 3,
"schema": {
"type": "object",
"additionalProperties": false,
"properties": {
"all_models": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"maker": { "type": "string" },
"model_name": { "type": "string" }
},
"required": ["maker", "model_name"]
}
}
},
"required": ["all_models"]
}
});
root_value.x_walk(|parent_map, property_name| {
if property_name == "type" {
let val = parent_map.get(property_name).and_then(|v| v.as_str());
if let Some("object") = val {
parent_map.remove("additionalProperties");
return false; }
}
true
});
let mut marker_count = 0;
root_value.x_walk(|_parent_map, property_name| {
if property_name == "additionalProperties" {
marker_count += 1;
}
true
});
assert_eq!(1, marker_count);
Ok(())
}
#[test]
fn test_as_type_for_vec() -> Result<()> {
let json_array = json!([ {"a": 1}, {"b": 2} ]);
let vec_ref: &Vec<serde_json::Value> = <&Vec<serde_json::Value>>::from_value(&json_array)?;
assert_eq!(vec_ref.len(), 2);
let first_obj = &vec_ref[0];
let a_val = first_obj
.get("a")
.and_then(|v| v.as_i64())
.ok_or("Missing 'a' in first element")?;
assert_eq!(a_val, 1);
Ok(())
}
#[test]
fn test_as_type_for_vec_str() -> Result<()> {
let json_array = json!(["hello", "world"]);
let vec_str: Vec<&str> = <Vec<&str>>::from_value(&json_array)?;
assert_eq!(vec_str, vec!["hello", "world"]);
Ok(())
}
#[test]
fn test_x_remove_direct() -> Result<()> {
let mut value = json!({"key": "direct_value", "other": 42});
let removed: String = value.x_remove("key")?;
assert_eq!(removed, "direct_value");
let obj = value.as_object().ok_or("Expected object after removal")?;
assert!(!obj.contains_key("key"));
let other: i64 = value.x_get("other")?;
assert_eq!(other, 42);
Ok(())
}
#[test]
fn test_x_remove_nested() -> Result<()> {
let mut value = json!({
"a": {
"b": {
"c": "nested_value",
"d": "keep_this"
},
"e": "direct_in_a"
},
"f": "outside"
});
let removed: String = value.x_remove("/a/b/c")?;
assert_eq!(removed, "nested_value");
let d: String = value.x_get("/a/b/d")?;
assert_eq!(d, "keep_this");
let b = value.pointer("/a/b").ok_or("Expected pointer /a/b not found")?;
let b_obj = b.as_object().ok_or("Expected object at /a/b")?;
assert!(!b_obj.contains_key("c"));
let direct_in_a: String = value.x_get("/a/e")?;
assert_eq!(direct_in_a, "direct_in_a");
let outside: String = value.x_get("f")?;
assert_eq!(outside, "outside");
Ok(())
}
#[test]
fn test_x_merge_ok() -> Result<()> {
let mut value = json!({"a": 1, "b": 2});
let other = json!({"b": 3, "c": 4});
value.x_merge(other)?;
assert_eq!(value["a"], 1);
assert_eq!(value["b"], 3);
assert_eq!(value["c"], 4);
value.x_merge(serde_json::Value::Null)?;
assert_eq!(value["b"], 3);
Ok(())
}