rulemorph 0.3.1

YAML-based declarative data transformation engine for CSV/JSON to JSON
Documentation
use super::*;
use serde_json::json;

#[test]
fn test_context_new() {
    let ctx = V2EvalContext::new();
    assert!(ctx.get_pipe_value().is_none());
    assert!(ctx.resolve_local("x").is_none());
    assert!(ctx.get_item().is_none());
    assert!(ctx.get_acc().is_none());
}

#[test]
fn test_context_with_pipe_value() {
    let ctx = V2EvalContext::new().with_pipe_value(EvalValue::Value(json!(42)));
    assert!(ctx.get_pipe_value().is_some());
    assert_eq!(ctx.get_pipe_value(), Some(&EvalValue::Value(json!(42))));
}

#[test]
fn test_context_with_let_binding() {
    let ctx =
        V2EvalContext::new().with_let_binding("x".to_string(), EvalValue::Value(json!(100)));
    assert!(ctx.resolve_local("x").is_some());
    assert_eq!(ctx.resolve_local("x"), Some(&EvalValue::Value(json!(100))));
    assert!(ctx.resolve_local("y").is_none());
}

#[test]
fn test_context_with_multiple_let_bindings() {
    let ctx = V2EvalContext::new().with_let_bindings(vec![
        ("a".to_string(), EvalValue::Value(json!(1))),
        ("b".to_string(), EvalValue::Value(json!(2))),
    ]);
    assert!(ctx.resolve_local("a").is_some());
    assert!(ctx.resolve_local("b").is_some());
    assert!(ctx.resolve_local("c").is_none());
}

#[test]
fn test_context_scope_chain() {
    let ctx = V2EvalContext::new().with_let_binding("x".to_string(), EvalValue::Value(json!(1)));
    let inner_ctx = ctx
        .clone()
        .with_let_binding("y".to_string(), EvalValue::Value(json!(2)));

    assert!(inner_ctx.resolve_local("x").is_some());
    assert!(inner_ctx.resolve_local("y").is_some());

    assert!(ctx.resolve_local("x").is_some());
    assert!(ctx.resolve_local("y").is_none());
}

#[test]
fn test_context_with_item() {
    let item_value = json!({"name": "test"});
    let ctx = V2EvalContext::new().with_item(EvalItem {
        value: &item_value,
        index: 0,
    });
    assert!(ctx.has_item_scope());
    assert!(ctx.get_item().is_some());
    let item = ctx.get_item().unwrap();
    assert_eq!(item.value, &json!({"name": "test"}));
    assert_eq!(item.index, 0);
}

#[test]
fn test_context_with_acc() {
    let acc_value = json!(0);
    let ctx = V2EvalContext::new().with_acc(&acc_value);
    assert!(ctx.has_acc_scope());
    assert!(ctx.get_acc().is_some());
    assert_eq!(ctx.get_acc(), Some(&json!(0)));
}

#[test]
fn test_eval_value_is_missing() {
    assert!(EvalValue::Missing.is_missing());
    assert!(!EvalValue::Value(json!(null)).is_missing());
}

#[test]
fn test_eval_value_into_value() {
    assert_eq!(EvalValue::Missing.into_value(), None);
    assert_eq!(
        EvalValue::Value(json!("hello")).into_value(),
        Some(json!("hello"))
    );
}

#[test]
fn test_eval_value_as_value() {
    let missing = EvalValue::Missing;
    let val = EvalValue::Value(json!(42));
    assert!(missing.as_value().is_none());
    assert_eq!(val.as_value(), Some(&json!(42)));
}

#[test]
fn test_context_preserves_pipe_value_after_let() {
    let ctx = V2EvalContext::new()
        .with_pipe_value(EvalValue::Value(json!(100)))
        .with_let_binding("x".to_string(), EvalValue::Value(json!(50)));

    assert_eq!(ctx.get_pipe_value(), Some(&EvalValue::Value(json!(100))));
    assert_eq!(ctx.resolve_local("x"), Some(&EvalValue::Value(json!(50))));
}