#![allow(clippy::unwrap_used, clippy::expect_used)]
use noyalib::Value;
use noyalib::cst::parse_document;
#[test]
fn set_path_refuses_a_path_that_does_not_resolve() {
let src = "a: 1\nb: 2\n";
let mut doc = parse_document(src).expect("parse");
let before = doc.to_string();
let err = doc
.set_path("a.b.c.d", &Value::from(1_i64))
.expect_err("a path through a scalar cannot resolve");
assert!(
err.to_string().contains("set_path") || err.to_string().contains("path"),
"unhelpful error: {err}"
);
assert_eq!(doc.to_string(), before, "document changed despite refusal");
}
#[test]
fn set_path_refuses_when_the_root_is_not_a_mapping() {
for src in ["- 1\n- 2\n", "just a scalar\n"] {
let mut doc = parse_document(src).expect("parse");
let before = doc.to_string();
let err = doc
.set_path("newkey", &Value::from(1_i64))
.expect_err("cannot create a key under a non-mapping root");
assert!(!err.to_string().is_empty());
assert_eq!(
doc.to_string(),
before,
"document changed despite refusal, source was {src:?}"
);
}
}
#[test]
fn swap_items_refuses_an_index_that_is_not_there() {
let src = "xs:\n - a\n - b\n";
let mut doc = parse_document(src).expect("parse");
let before = doc.to_string();
let err = doc
.swap_items("xs", 0, 99)
.expect_err("index 99 does not exist");
assert!(
err.to_string().contains("swap_items"),
"error should name the operation: {err}"
);
assert_eq!(doc.to_string(), before, "document changed despite refusal");
}
#[test]
fn swap_items_refuses_a_path_that_is_not_a_sequence() {
let mut doc = parse_document("m:\n a: 1\n b: 2\n").expect("parse");
let before = doc.to_string();
assert!(
doc.swap_items("m", 0, 1).is_err(),
"a mapping is not swappable"
);
assert_eq!(doc.to_string(), before, "document changed despite refusal");
}
#[test]
fn set_value_refuses_an_unresolvable_path_and_changes_nothing() {
let src = "a:\n b: 1\n";
let mut doc = parse_document(src).expect("parse");
let before = doc.to_string();
assert!(doc.set_value("a.b.c", &Value::from(2_i64)).is_err());
assert_eq!(doc.to_string(), before);
}
#[test]
fn remove_reports_a_path_it_cannot_resolve() {
let src = "a: 1\n";
let mut doc = parse_document(src).expect("parse");
let before = doc.to_string();
let r = doc.remove("nope");
assert_eq!(
doc.to_string(),
before,
"document changed on a no-op remove"
);
if r.is_ok() {
assert_eq!(doc.to_string(), src);
}
}
#[test]
fn set_value_refuses_an_out_of_range_sequence_index() {
let mut doc = parse_document("xs:\n - 1\n - 2\n").expect("parse");
let before = doc.to_string();
assert!(doc.set_value("xs[9]", &Value::from(3_i64)).is_err());
assert_eq!(doc.to_string(), before);
}
#[test]
fn the_same_operations_succeed_on_valid_input() {
let mut doc = parse_document("a:\n b: 1\nxs:\n - p\n - q\n").expect("parse");
doc.set_value("a.b", &Value::from(2_i64))
.expect("set_value should work");
doc.swap_items("xs", 0, 1).expect("swap_items should work");
let out = doc.to_string();
assert!(out.contains('2'), "set_value did not apply: {out}");
let v: Value = noyalib::from_str(&out).expect("reparse");
let xs = v.get("xs").expect("xs present");
assert_eq!(
xs.as_sequence().expect("sequence")[0].as_str(),
Some("q"),
"swap_items did not apply: {out}"
);
}