mod defs;
mod dispatch;
pub use defs::TOOL_DEFS;
pub use dispatch::dispatch;
#[cfg(test)]
mod tests {
use super::*;
use crate::knowledge::Knowledge;
use serde_json::{Value, json};
use std::sync::Arc;
fn empty_kb() -> Arc<Knowledge> {
Arc::new(Knowledge::embedded())
}
#[tokio::test]
async fn dispatch_validate_card_returns_report() {
let kb = empty_kb();
let args = json!({
"card": {
"type": "AdaptiveCard", "version": "1.6",
"speak": "Hi",
"body": [{"type": "TextBlock", "text": "Hello", "wrap": true}]
}
})
.to_string();
let result = dispatch(&kb, "validate_card", &args).await;
let parsed: Value = serde_json::from_str(&result).unwrap();
assert_eq!(parsed["valid"], true);
}
#[tokio::test]
async fn dispatch_unknown_tool_returns_error() {
let kb = empty_kb();
let result = dispatch(&kb, "no_such_tool", "{}").await;
let parsed: Value = serde_json::from_str(&result).unwrap();
assert!(parsed["error"].is_string());
}
#[test]
fn tool_defs_has_twelve_tools() {
assert_eq!(TOOL_DEFS.len(), 12);
}
#[test]
fn all_tool_names_unique() {
let mut names: Vec<&'static str> = TOOL_DEFS.iter().map(|t| t.function.name).collect();
names.sort_unstable();
let original_len = names.len();
names.dedup();
assert_eq!(names.len(), original_len);
}
#[tokio::test]
async fn dispatch_optimize_card_adds_speak() {
let kb = empty_kb();
let args = json!({
"card": {
"type": "AdaptiveCard",
"version": "1.6",
"body": [{"type": "Image", "url": "x.png"}]
},
"accessibility": true
})
.to_string();
let result = dispatch(&kb, "optimize_card", &args).await;
let v: Value = serde_json::from_str(&result).unwrap();
assert!(v["card"]["speak"].is_string());
}
#[tokio::test]
async fn dispatch_transform_card_to_outlook() {
let kb = empty_kb();
let args = json!({
"card": {
"type": "AdaptiveCard",
"version": "1.6",
"body": [],
"actions": [{"type": "Action.Execute", "title": "OK", "verb": "save"}]
},
"target_host": "outlook"
})
.to_string();
let result = dispatch(&kb, "transform_card", &args).await;
let v: Value = serde_json::from_str(&result).unwrap();
assert_eq!(v["card"]["version"], "1.4");
assert_eq!(v["card"]["actions"][0]["type"], "Action.Submit");
}
#[tokio::test]
async fn dispatch_pack_card_returns_ui_message() {
let kb = empty_kb();
let args = json!({ "name": "test", "cards": [] }).to_string();
let result = dispatch(&kb, "pack_card", &args).await;
let v: Value = serde_json::from_str(&result).unwrap();
assert!(v["error"].as_str().unwrap().contains("UI"));
}
}