//! Table-driven conformance for happy paths and error messages.
//!
//! Each row in `fixtures/cases.json` carries a target, a raw spec, and either an
//! expected result or an expected error string. The same data exercises the
//! command set and the exact failure text.

mod support;

use immutability_helper::update_value;
use support::{load_cases, to_value};

const CASES: &str = include_str!("fixtures/cases.json");

#[test]
fn conformance_table() {
    let cases = load_cases(CASES);
    assert!(!cases.is_empty(), "fixtures should not be empty");

    for case in cases {
        let input = to_value(&case.input);
        let spec = to_value(&case.spec);
        let result = update_value(&input, &spec);

        match (&case.expect, &case.error) {
            (Some(expected), None) => {
                let value = result.unwrap_or_else(|e| {
                    panic!("case '{}' expected success, got error: {e}", case.name)
                });
                let want = to_value(expected);
                assert_eq!(value, want, "case '{}' result mismatch", case.name);
            }
            (None, Some(message)) => {
                let err = result.expect_err(&format!(
                    "case '{}' expected an error, got success",
                    case.name
                ));
                assert_eq!(
                    err.message(),
                    message,
                    "case '{}' error mismatch",
                    case.name
                );
            }
            _ => panic!("case '{}' must set exactly one of expect/error", case.name),
        }
    }
}
