dot-prop 0.1.0

Get, set, has, and delete a property from a nested JSON value using a dot path (a.b.0.c). A faithful port of the dot-prop npm package.
Documentation
//! Integration tests exercising the public API of `dot-prop`.

use dot_prop::{
    delete_property, deep_keys, escape_path, get_property, has_property, parse_path,
    set_property, stringify_path, unflatten, Segment,
};
use serde_json::json;

#[test]
fn config_access() {
    let config = json!({
        "server": { "ports": [8080, 8081], "host": "localhost" },
        "features": { "auth.enabled": true }
    });
    assert_eq!(get_property(&config, "server.ports[1]"), Some(&json!(8081)));
    assert_eq!(get_property(&config, "server.host"), Some(&json!("localhost")));
    // Escaped dot for a literal key containing a dot:
    assert_eq!(get_property(&config, "features.auth\\.enabled"), Some(&json!(true)));
}

#[test]
fn build_nested() {
    let mut value = json!({});
    set_property(&mut value, "a.b.c", json!(1));
    set_property(&mut value, "a.b.d", json!(2));
    set_property(&mut value, "a.list[2]", json!("x"));
    assert_eq!(value, json!({ "a": { "b": { "c": 1, "d": 2 }, "list": [null, null, "x"] } }));
    assert!(has_property(&value, "a.list[2]"));
    assert!(delete_property(&mut value, "a.b.c"));
    assert!(!has_property(&value, "a.b.c"));
}

#[test]
fn prototype_pollution_guard() {
    assert_eq!(parse_path("__proto__.polluted").unwrap(), vec![]);
    let mut value = json!({});
    set_property(&mut value, "__proto__.polluted", json!(true));
    assert_eq!(value, json!({})); // ignored
}

#[test]
fn path_helpers() {
    assert_eq!(escape_path("a.b[c]"), "a\\.b\\[c]");
    let segments = vec![Segment::Key("user".into()), Segment::Index(0), Segment::Key("name".into())];
    assert_eq!(stringify_path(&segments), "user[0].name");
    assert_eq!(parse_path("user[0].name").unwrap(), segments);
}

#[test]
fn flatten_roundtrip() {
    let nested = json!({ "a": { "b": 1 }, "c": [2, 3] });
    let keys = deep_keys(&nested);
    assert_eq!(keys, ["a.b", "c[0]", "c[1]"]);
    let flat = json!({ "a.b": 1, "x.y.z": "deep" });
    assert_eq!(unflatten(&flat), json!({ "a": { "b": 1 }, "x": { "y": { "z": "deep" } } }));
}