liminal-sdk 0.20.20

Application-facing SDK traits for liminal messaging clients
Documentation
//! NET-031 R1 and R5: the one substitution the seat's flow and a line's stages share.

use serde_json::json;

use super::{fill, fill_with, names_prev};

#[test]
fn a_prev_pointer_is_filled_anywhere_and_the_rest_is_kept() -> Result<(), String> {
    let prev = json!({ "a": { "b": [10, 20] }, "whole": true });
    let filled = fill(
        &json!({ "x": { "$prev": "/a/b/1" }, "y": [{ "$prev": "" }, 3], "z": "text" }),
        Some(&prev),
    )?;
    assert_eq!(filled, json!({ "x": 20, "y": [prev, 3], "z": "text" }));
    Ok(())
}

#[test]
fn a_prev_naming_nothing_or_in_the_first_step_is_refused_in_the_seats_words() {
    let prev = json!({ "a": 1 });
    assert_eq!(
        fill(&json!({ "x": { "$prev": "/b" } }), Some(&prev)),
        Err("$prev \"/b\" names nothing in the previous reply".to_owned())
    );
    assert_eq!(
        fill(&json!({ "x": { "$prev": "/a" } }), None),
        Err("$prev \"/a\" in the first step".to_owned())
    );
}

#[test]
fn an_item_pointer_is_filled_from_the_element_and_refused_outside_a_fan_out() -> Result<(), String>
{
    let prev = json!({ "size": 3 });
    let element = json!({ "text": "chunk" });
    let filled = fill_with(
        &json!({ "body": { "$item": "/text" }, "size": { "$prev": "/size" } }),
        Some(&prev),
        Some(&element),
    )?;
    assert_eq!(filled, json!({ "body": "chunk", "size": 3 }));
    assert_eq!(
        fill_with(&json!({ "body": { "$item": "" } }), Some(&prev), None),
        Err("$item \"\" outside a fan-out".to_owned())
    );
    assert_eq!(
        fill_with(
            &json!({ "body": { "$item": "/gone" } }),
            None,
            Some(&element)
        ),
        Err("$item \"/gone\" names nothing in the element".to_owned())
    );
    Ok(())
}

#[test]
fn names_prev_finds_a_prev_at_any_depth_and_nothing_else() {
    assert!(names_prev(&json!({ "a": [{ "b": { "$prev": "/x" } }] })));
    assert!(!names_prev(&json!({ "a": { "$prev": "/x", "other": 1 } })));
    assert!(!names_prev(&json!({ "a": { "$item": "/x" } })));
}

#[test]
fn prev_uses_json_pointer_escapes_and_leaves_non_pointer_objects_alone() -> Result<(), String> {
    let prev = json!({"a/b": {"~key": [null, false]}});
    assert_eq!(
        fill(
            &json!([{"$prev": "/a~1b/~0key/1"}, {"$prev": "/a~1b/~0key/0"}]),
            Some(&prev)
        )?,
        json!([false, null])
    );
    let literal = json!({"$prev": "/missing", "other": [{"$prev": 3}]});
    assert_eq!(fill(&literal, None)?, literal);
    assert!(!names_prev(&literal));
    Ok(())
}

#[test]
fn an_item_and_prev_are_filled_together_in_nested_inputs() -> Result<(), String> {
    let previous = json!({"count": 2});
    let item = json!({"a/b": ["first", "second"]});
    assert_eq!(
        fill_with(
            &json!({"nested": [
                {"$item": "/a~1b/1"}, {"$prev": "/count"}, {"$item": ""}
            ]}),
            Some(&previous),
            Some(&item)
        )?,
        json!({"nested": ["second", 2, item]})
    );
    assert_eq!(
        fill_with(
            &json!({"$item": "/gone"}),
            Some(&previous),
            Some(&json!({}))
        ),
        Err("$item \"/gone\" names nothing in the element".to_owned())
    );
    Ok(())
}