use super::{count, exit, flag, list, opt_text, rows, secs, text};
use serde_json::{Map, Value, json};
fn body(v: &Value) -> Map<String, Value> {
v.as_object().expect("an object").clone()
}
#[test]
fn a_required_field_reads_or_refuses_by_name() {
let o = body(&json!({
"word": "home", "yes": true, "age": -3, "n": 7,
"wrong": [],
}));
assert_eq!(text(&o, "word"), Ok("home".to_owned()));
assert_eq!(flag(&o, "yes"), Ok(true));
assert_eq!(secs(&o, "age"), Ok(-3));
assert_eq!(count(&o, "n"), Ok(7));
for refusal in [
text(&o, "wrong").expect_err("not a string"),
text(&o, "absent").expect_err("absent"),
] {
assert!(refusal.contains("non-string"), "{refusal}");
}
assert!(
flag(&o, "word")
.expect_err("not a bool")
.contains("\"word\""),
"the key is named"
);
assert!(
secs(&o, "word")
.expect_err("not an int")
.contains("\"word\"")
);
assert!(count(&o, "age").expect_err("negative").contains("\"age\""));
}
#[test]
fn an_exit_status_is_narrowed_and_says_so() {
assert_eq!(exit(&body(&json!({"exit": 0}))), Ok(0));
assert_eq!(exit(&body(&json!({"exit": -1}))), Ok(-1));
assert!(
exit(&body(&json!({"exit": 9_999_999_999_i64})))
.expect_err("out of range")
.contains("out of range")
);
assert!(
exit(&body(&json!({})))
.expect_err("absent")
.contains("\"exit\"")
);
}
#[test]
fn an_optional_field_reads_absence_as_a_fact() {
let o = body(&json!({"said": "", "null": null, "wrong": 7}));
assert_eq!(opt_text(&o, "said"), Ok(Some(String::new())));
assert_eq!(opt_text(&o, "null"), Ok(None));
assert_eq!(opt_text(&o, "absent"), Ok(None));
assert!(
opt_text(&o, "wrong")
.expect_err("not a string")
.contains("\"wrong\"")
);
}
#[test]
fn a_listing_refuses_rather_than_shortening() {
let read = |v: &Value| {
v.as_str()
.map(str::to_owned)
.ok_or_else(|| "row: not a string".to_owned())
};
let o = body(&json!({"rows": ["a", "b"], "other": ["c"], "flat": 7}));
assert_eq!(rows(&o, read), Ok(vec!["a".to_owned(), "b".to_owned()]));
assert_eq!(list(&o, "other", read), Ok(vec!["c".to_owned()]));
assert!(
list(&o, "flat", read)
.expect_err("not an array")
.contains("non-array")
);
let bad = body(&json!({"rows": ["a", 7]}));
assert_eq!(rows(&bad, read), Err("row: not a string".to_owned()));
}