#![allow(missing_docs)]
use noyalib::cst::parse_document;
use noyalib::{Number, Value};
const TWO_SPACE_DOC: &str = "\
metadata:
labels:
app: noyalib
";
#[test]
fn or_insert_runs_when_path_is_vacant() {
let mut doc = parse_document(TWO_SPACE_DOC).unwrap();
let inserted = doc.entry("metadata.labels.env").or_insert("prod").unwrap();
assert!(inserted, "vacant path must report inserted=true");
assert!(doc.to_string().contains("env: prod"));
}
#[test]
fn or_insert_no_op_when_path_is_occupied() {
let mut doc = parse_document(TWO_SPACE_DOC).unwrap();
let inserted = doc
.entry("metadata.labels.app")
.or_insert("staging")
.unwrap();
assert!(!inserted, "occupied path must report inserted=false");
assert!(doc.to_string().contains("app: noyalib"));
assert!(!doc.to_string().contains("app: staging"));
}
#[test]
fn or_insert_with_lazy_default() {
let mut doc = parse_document(TWO_SPACE_DOC).unwrap();
let mut called = 0;
let _ = doc
.entry("metadata.labels.env")
.or_insert_with(|| {
called += 1;
"prod".to_owned()
})
.unwrap();
assert_eq!(called, 1);
let mut called2 = 0;
let _ = doc
.entry("metadata.labels.app")
.or_insert_with(|| {
called2 += 1;
"should-not-run".to_owned()
})
.unwrap();
assert_eq!(called2, 0);
}
#[test]
fn or_insert_value_typed_default() {
let mut doc = parse_document(TWO_SPACE_DOC).unwrap();
let inserted = doc
.entry("metadata.labels.replicas")
.or_insert_value(&Value::Number(Number::Integer(3)))
.unwrap();
assert!(inserted);
assert!(doc.to_string().contains("replicas: 3"));
}
#[test]
fn or_insert_value_no_op_when_occupied() {
let mut doc = parse_document(TWO_SPACE_DOC).unwrap();
let inserted = doc
.entry("metadata.labels.app")
.or_insert_value(&Value::String("ignored".into()))
.unwrap();
assert!(!inserted);
assert!(doc.to_string().contains("app: noyalib"));
}
#[test]
fn or_insert_top_level_key_errors_actionably() {
let mut doc = parse_document(TWO_SPACE_DOC).unwrap();
let err = doc.entry("brand_new_top_key").or_insert("x").unwrap_err();
let msg = err.to_string();
assert!(
msg.contains("top-level"),
"error must mention top-level: {msg}"
);
}
#[test]
fn or_insert_at_sequence_index_errors_actionably() {
let mut doc = parse_document("items:\n - one\n - two\n").unwrap();
let err = doc.entry("items[5]").or_insert("x").unwrap_err();
let msg = err.to_string();
assert!(
msg.contains("push_back") || msg.contains("insert_after"),
"error must redirect to push_back / insert_after: {msg}"
);
}
#[test]
fn and_modify_runs_when_occupied() {
let mut doc = parse_document("service:\n port: 8080\n").unwrap();
let _ = doc
.entry("service.port")
.and_modify(|d| {
let _ = d.set("service.port", "9090");
})
.or_insert("8080") .unwrap();
assert!(doc.to_string().contains("port: 9090"));
}
#[test]
fn and_modify_skipped_when_vacant() {
let mut doc = parse_document("service:\n port: 8080\n").unwrap();
let mut ran = 0;
let _ = doc
.entry("service.replicas")
.and_modify(|_| ran += 1)
.or_insert("3")
.unwrap();
assert_eq!(ran, 0);
assert!(doc.to_string().contains("replicas: 3"));
}
#[test]
fn chained_modify_then_or_insert_idempotent() {
let mut doc = parse_document("counters:\n hits: 1\n").unwrap();
let _ = doc
.entry("counters.hits")
.and_modify(|d| {
let _ = d.set("counters.hits", "2");
})
.or_insert("1")
.unwrap();
assert!(doc.to_string().contains("hits: 2"));
let _ = doc
.entry("counters.misses")
.and_modify(|d| {
let _ = d.set("counters.misses", "999");
})
.or_insert("0")
.unwrap();
assert!(doc.to_string().contains("misses: 0"));
}
#[test]
fn or_insert_preserves_byte_faithful_outside_target() {
let src = "\
# project metadata
metadata:
labels:
app: noyalib # the project name
team: platform
";
let mut doc = parse_document(src).unwrap();
let _ = doc.entry("metadata.labels.env").or_insert("prod").unwrap();
let out = doc.to_string();
assert!(out.contains("# project metadata"));
assert!(out.contains("# the project name"));
assert!(out.contains("team: platform"));
assert!(out.contains("env: prod"));
}
#[test]
fn a_new_key_lands_in_a_mapping_whose_keys_hold_a_dot() {
let mut doc = parse_document(
"metadata:\n labels:\n app.kubernetes.io/name: web\n app.kubernetes.io/component: frontend\n",
)
.unwrap();
doc.insert_entry("metadata.labels", "tier", "frontend")
.unwrap();
assert_eq!(
doc.to_string(),
"metadata:\n labels:\n app.kubernetes.io/name: web\n app.kubernetes.io/component: frontend\n tier: frontend\n"
);
}
#[test]
fn the_same_holds_for_bracket_star_and_quoted_keys() {
for (src, expected) in [
("m:\n a[0]: 1\n", "m:\n a[0]: 1\n b: 2\n"),
("m:\n a*b: 1\n", "m:\n a*b: 1\n b: 2\n"),
("m:\n \"a.b\": 1\n", "m:\n \"a.b\": 1\n b: 2\n"),
] {
let mut doc = parse_document(src).unwrap();
doc.insert_entry("m", "b", "2").unwrap();
assert_eq!(doc.to_string(), expected, "for {src:?}");
}
}
#[test]
fn a_dotted_key_mapping_keeps_its_line_endings() {
let mut doc = parse_document("labels:\r\n app.kubernetes.io/name: web\r\n").unwrap();
doc.insert_entry("labels", "tier", "web").unwrap();
assert_eq!(
doc.to_string(),
"labels:\r\n app.kubernetes.io/name: web\r\n tier: web\r\n"
);
}
#[test]
fn a_trailing_implicit_null_is_the_anchor_rather_than_a_gap() {
let mut doc = parse_document("m:\n a: 1\n b:\n").unwrap();
doc.insert_entry("m", "c", "3").unwrap();
assert_eq!(doc.to_string(), "m:\n a: 1\n b:\n c: 3\n");
let mut doc = parse_document("m:\n a:\n b:\n").unwrap();
doc.insert_entry("m", "c", "3").unwrap();
assert_eq!(doc.to_string(), "m:\n a:\n b:\n c: 3\n");
}
#[test]
fn a_mapping_with_a_merge_key_and_an_entry_of_its_own_anchors_on_the_entry() {
let mut doc = parse_document("d: &d\n x: 1\ns:\n <<: *d\n own: 1\n").unwrap();
doc.insert_entry("s", "y", "2").unwrap();
assert_eq!(
doc.to_string(),
"d: &d\n x: 1\ns:\n <<: *d\n own: 1\n y: 2\n"
);
}
#[test]
fn the_typed_insert_path_gains_the_same_reach() {
let mut doc = parse_document("labels:\n app.kubernetes.io/name: web\n").unwrap();
doc.insert_entry_value("labels", "tier", &Value::String("frontend".into()))
.unwrap();
assert_eq!(
doc.to_string(),
"labels:\n app.kubernetes.io/name: web\n tier: frontend\n"
);
}