use crate::reply::{Read, Reply, read};
use serde_json::json;
fn full() -> serde_json::Value {
json!({"ok": true, "kind": "clients", "rows": [
{"client": "laptop", "present": true, "last_seen": 1_757_000_000_i64, "tools": [
{"name": "Bash", "description": "run a command",
"input_schema": {"type": "object"}},
{"name": "bash", "description": "run it where the caller says",
"input_schema": {"type": "object"}, "subject_cwd": true}]},
{"client": "phone", "present": false, "tools": []}]})
}
#[test]
fn a_row_carries_presence_the_set_and_each_tool_s_consent() {
let Read::Answer(Reply::Clients(rows)) = read(&full()) else {
panic!("a clients answer: {:?}", read(&full()));
};
assert_eq!(rows.len(), 2);
assert_eq!(rows[0].client, "laptop");
assert!(rows[0].present);
assert_eq!(
rows[0]
.tools
.iter()
.map(|tool| (tool.name.clone(), tool.subject_cwd))
.collect::<Vec<(String, bool)>>(),
vec![("Bash".to_owned(), false), ("bash".to_owned(), true)]
);
assert_eq!(
rows[0].last_seen,
Some(1_757_000_000),
"when it last spoke is durable, unlike presence"
);
assert!(!rows[1].present, "presence is a fact about the moment");
assert!(rows[1].tools.is_empty(), "and the set is its own fact");
assert_eq!(
rows[1].last_seen, None,
"and an absent stamp is a machine that has never once dialled"
);
}
#[test]
fn the_schema_is_not_read_and_a_row_without_one_still_lands() {
let bare = json!({"ok": true, "kind": "clients", "rows": [
{"client": "laptop", "present": true,
"tools": [{"name": "Bash", "description": "run a command"}]}]});
assert!(matches!(read(&bare), Read::Answer(Reply::Clients(_))));
}
#[test]
fn a_consent_that_is_not_a_boolean_refuses_and_names_the_field() {
for wrong in [json!("yes"), json!(null), json!(1)] {
let frame = json!({"ok": true, "kind": "clients", "rows": [
{"client": "laptop", "present": true, "tools": [
{"name": "Bash", "description": "d", "subject_cwd": wrong}]}]});
let Read::Unreadable(why) = read(&frame) else {
panic!("a mistyped consent refuses: {frame}");
};
assert!(why.contains("subject_cwd"), "{why}");
}
}
#[test]
fn a_missing_field_refuses_and_names_itself() {
for (frame, key) in [
(
json!({"ok": true, "kind": "clients", "rows": [{"present": true, "tools": []}]}),
"client",
),
(
json!({"ok": true, "kind": "clients", "rows": [{"client": "a", "tools": []}]}),
"present",
),
(
json!({"ok": true, "kind": "clients", "rows": [{"client": "a", "present": true}]}),
"tools",
),
(
json!({"ok": true, "kind": "clients", "rows": [{"client": "a", "present": true,
"tools": [{"description": "d"}]}]}),
"name",
),
(
json!({"ok": true, "kind": "clients", "rows": ["not an object"]}),
"not a JSON object",
),
(
json!({"ok": true, "kind": "clients", "rows": [{"client": "a", "present": true,
"tools": ["not an object"]}]}),
"not a JSON object",
),
] {
let Read::Unreadable(why) = read(&frame) else {
panic!("{key}: {frame}");
};
assert!(why.contains(key), "{key:?}: {why}");
}
}
#[test]
fn the_line_says_presence_and_how_much_is_offered() {
let Read::Answer(Reply::Clients(rows)) = read(&full()) else {
panic!("a clients answer");
};
assert_eq!(
rows[0].line(),
format!("laptop — {}, 2 tool(s)", super::HERE)
);
assert_eq!(
rows[1].line(),
format!("phone — {}, 0 tool(s), {}", super::AWAY, super::NEVER)
);
}