use super::registry::*;
use super::types::*;
#[test]
fn test_fj063_build_registry_has_all_tools() {
let registry = build_registry();
assert_eq!(registry.len(), 12);
assert!(registry.has_handler("forjar_validate"));
assert!(registry.has_handler("forjar_plan"));
assert!(registry.has_handler("forjar_drift"));
assert!(registry.has_handler("forjar_lint"));
assert!(registry.has_handler("forjar_graph"));
assert!(registry.has_handler("forjar_show"));
assert!(registry.has_handler("forjar_status"));
assert!(registry.has_handler("forjar_trace"));
assert!(registry.has_handler("forjar_anomaly"));
assert!(registry.has_handler("forjar_remediate"));
assert!(registry.has_handler("forjar_audit"));
assert!(registry.has_handler("forjar_workspace"));
}
#[test]
fn test_fj063_build_registry_no_unknown_tools() {
let registry = build_registry();
assert!(!registry.has_handler("forjar_apply"));
assert!(!registry.has_handler("nonexistent"));
}
#[tokio::test]
async fn test_fj063_registry_dispatch_validate() {
let registry = build_registry();
let dir = tempfile::tempdir().unwrap();
let config_path = dir.path().join("forjar.yaml");
std::fs::write(
&config_path,
"version: \"1.0\"\nname: test\nmachines:\n local:\n hostname: localhost\n addr: 127.0.0.1\nresources:\n test-pkg:\n type: package\n provider: apt\n packages: [git]\n",
)
.unwrap();
let input = serde_json::json!({
"path": config_path.to_str().unwrap()
});
let result = registry
.dispatch("forjar_validate", &serde_json::to_vec(&input).unwrap())
.await;
assert!(result.is_ok());
let output: ValidateOutput = serde_json::from_slice(&result.unwrap()).unwrap();
assert!(output.valid);
}
#[tokio::test]
async fn test_fj063_registry_dispatch_unknown_tool() {
let registry = build_registry();
let result = registry.dispatch("nonexistent", b"{}").await;
assert!(result.is_err());
}
#[test]
fn test_fj142_export_schema_has_all_tools() {
let schema = export_schema();
assert_eq!(schema["tool_count"], 12);
let tools = schema["tools"].as_array().unwrap();
assert_eq!(tools.len(), 12);
}
#[test]
fn test_fj142_export_schema_tool_names() {
let schema = export_schema();
let tools = schema["tools"].as_array().unwrap();
let names: Vec<&str> = tools.iter().map(|t| t["name"].as_str().unwrap()).collect();
assert!(names.contains(&"forjar_validate"));
assert!(names.contains(&"forjar_plan"));
assert!(names.contains(&"forjar_drift"));
assert!(names.contains(&"forjar_lint"));
assert!(names.contains(&"forjar_graph"));
assert!(names.contains(&"forjar_show"));
assert!(names.contains(&"forjar_status"));
assert!(names.contains(&"forjar_trace"));
assert!(names.contains(&"forjar_anomaly"));
assert!(names.contains(&"forjar_remediate"));
assert!(names.contains(&"forjar_audit"));
assert!(names.contains(&"forjar_workspace"));
}
#[test]
fn test_fj142_export_schema_has_input_output() {
let schema = export_schema();
let tools = schema["tools"].as_array().unwrap();
for tool in tools {
assert!(
tool["input_schema"].is_object(),
"{} missing input_schema",
tool["name"]
);
assert!(
tool["output_schema"].is_object(),
"{} missing output_schema",
tool["name"]
);
}
}
#[test]
fn test_fj142_export_schema_metadata() {
let schema = export_schema();
assert_eq!(schema["schema_version"], "1.0");
assert_eq!(schema["server"], "forjar-mcp");
assert_eq!(schema["version"], env!("CARGO_PKG_VERSION"));
}
#[test]
fn register_all_matches_the_verb_table() {
let registry = build_registry();
for v in crate::verb::verbs() {
assert!(
registry.has_handler(&v.mcp_name()),
"verb `{}` is in the registry table but no handler is registered for `{}` \
— MCP would advertise a tool that tools/call cannot dispatch",
v.name,
v.mcp_name()
);
}
assert_eq!(
registry.len(),
crate::verb::verbs().len(),
"a handler is registered that the verb table does not declare"
);
}
#[test]
fn export_schema_matches_the_verb_table() {
let schema = export_schema();
let names: Vec<String> = schema["tools"]
.as_array()
.expect("tools array")
.iter()
.map(|t| t["name"].as_str().unwrap_or_default().to_string())
.collect();
let expected: Vec<String> = crate::verb::verbs().iter().map(|v| v.mcp_name()).collect();
assert_eq!(names, expected, "export_schema drifted from the verb table");
}
#[test]
fn every_tool_publishes_a_read_only_hint() {
let schema = export_schema();
for t in schema["tools"].as_array().expect("tools array") {
let hint = &t["annotations"]["readOnlyHint"];
assert!(
hint.is_boolean(),
"{}: readOnlyHint missing or not a boolean",
t["name"]
);
}
}