use colored::Colorize;
use serde_json::Value;
#[derive(Debug, Clone)]
pub enum JsonExpectation {
Has(Vec<String>),
Eq(Vec<String>, String),
}
pub fn check_all(json: &Value, expectations: &Vec<JsonExpectation>) -> Result<(), Vec<String>> {
let all_errors: Vec<String> = expectations
.iter()
.map(|t| check(json, t))
.filter(|t| t.is_err())
.map(|t| t.err().unwrap())
.collect();
if all_errors.len() == 0 {
Ok(())
} else {
Err(all_errors)
}
}
pub fn check(json: &Value, expectation: &JsonExpectation) -> Result<(), String> {
match expectation {
JsonExpectation::Has(path) => check_has(json, path),
JsonExpectation::Eq(path, val) => check_eq(json, path, val),
}
}
pub fn check_has(json: &Value, path: &Vec<String>) -> Result<(), String> {
get_value_for_path(json, path)
.map(|_| ())
.map_err(|error_message| {
format!("Testing: Has {}\n{}", path.join("."), error_message.red())
})
}
pub fn check_eq(json: &Value, path: &Vec<String>, val: &String) -> Result<(), String> {
match get_value_for_path(json, path) {
Ok(json_val) => {
let err_msg = format!("{}{}", "Invalid json value: ".red(), val.red());
let json_expected: Value = serde_json::from_str(val.as_str()).expect(err_msg.as_str());
if !json_expected.eq(&json_val) {
Err(format!("\tExpected: {}\n\tFound: {}", val, json_val))
} else {
Ok(())
}
}
Err(error_message) => Err(error_message),
}
.map_err(|error_message| {
format!(
"Testing: Eq {} {}\n{}",
path.join("."),
val,
error_message.red()
)
})
}
fn get_value_for_path(json: &Value, path: &Vec<String>) -> Result<Value, String> {
let mut current_json = json;
for key in path {
current_json = current_json
.get(&key)
.ok_or(format!("\tKey \"{}\" does not exist", key))?;
}
Ok(current_json.clone())
}