pub const SCHEMA_VERSION: u32 = 1;
pub enum ErrorKind {
Usage,
ConfigInvalid,
ConfigUnreadable,
Io,
Conflict,
Internal,
}
impl ErrorKind {
fn as_str(&self) -> &'static str {
match self {
Self::Usage => "usage",
Self::ConfigInvalid => "config_invalid",
Self::ConfigUnreadable => "config_unreadable",
Self::Io => "io",
Self::Conflict => "conflict",
Self::Internal => "internal",
}
}
}
pub fn ok(result: serde_json::Value) -> serde_json::Value {
serde_json::json!({
"schema": SCHEMA_VERSION,
"apimock": env!("CARGO_PKG_VERSION"),
"result": result,
})
}
pub fn err(kind: ErrorKind, message: impl Into<String>) -> serde_json::Value {
serde_json::json!({
"schema": SCHEMA_VERSION,
"apimock": env!("CARGO_PKG_VERSION"),
"error": {
"kind": kind.as_str(),
"message": message.into(),
},
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ok_has_schema_apimock_and_exactly_result() {
let v = ok(serde_json::json!({"a": 1}));
let obj = v.as_object().expect("envelope must be a JSON object");
assert_eq!(obj["schema"], SCHEMA_VERSION);
assert_eq!(obj["apimock"], env!("CARGO_PKG_VERSION"));
assert!(obj.contains_key("result"));
assert!(!obj.contains_key("error"));
assert_eq!(obj["result"]["a"], 1);
}
#[test]
fn err_has_schema_apimock_and_exactly_error() {
let v = err(ErrorKind::Usage, "missing required flag --config");
let obj = v.as_object().expect("envelope must be a JSON object");
assert_eq!(obj["schema"], SCHEMA_VERSION);
assert_eq!(obj["apimock"], env!("CARGO_PKG_VERSION"));
assert!(obj.contains_key("error"));
assert!(!obj.contains_key("result"));
assert_eq!(obj["error"]["kind"], "usage");
assert_eq!(obj["error"]["message"], "missing required flag --config");
}
#[test]
fn unknown_field_is_tolerated_when_parsed_back() {
let mut v = ok(serde_json::json!({"a": 1}));
v["future_field_from_a_later_schema"] = serde_json::json!("anything");
let reparsed: serde_json::Value =
serde_json::from_str(&v.to_string()).expect("must still parse");
assert_eq!(reparsed["result"]["a"], 1);
}
#[test]
fn is_never_a_bare_array() {
assert!(ok(serde_json::json!([1, 2, 3])).is_object());
assert!(err(ErrorKind::Internal, "x").is_object());
}
}