#![cfg_attr(coverage_nightly, coverage(off))]
use crate::handlers::tools::handle_tool_call;
use crate::models::mcp::McpRequest;
use crate::stateless_server::StatelessTemplateServer;
use serde_json::{json, Value};
use std::sync::Arc;
fn create_test_server() -> Arc<StatelessTemplateServer> {
Arc::new(StatelessTemplateServer::new().unwrap())
}
fn create_request(method: &str, params: Option<Value>) -> McpRequest {
McpRequest {
jsonrpc: "2.0".to_string(),
id: json!(1),
method: method.to_string(),
params,
}
}
#[tokio::test]
async fn test_handle_tool_call_missing_params() {
let server = create_test_server();
let request = create_request("tools/call", None);
let response = handle_tool_call(server, request).await;
assert!(response.error.is_some());
assert_eq!(response.error.unwrap().code, -32602);
}
#[tokio::test]
async fn test_handle_tool_call_invalid_params() {
let server = create_test_server();
let request = create_request("tools/call", Some(json!("invalid")));
let response = handle_tool_call(server, request).await;
assert!(response.error.is_some());
assert_eq!(response.error.unwrap().code, -32602);
}
#[tokio::test]
async fn test_list_templates_all() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "list_templates",
"arguments": {}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
assert!(response.error.is_none());
let result = response.result.unwrap();
let templates = result["templates"].as_array().unwrap();
assert!(!templates.is_empty());
}
#[tokio::test]
async fn test_list_templates_by_toolchain() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "list_templates",
"arguments": {
"toolchain": "rust"
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
let result = response.result.unwrap();
let templates = result["templates"].as_array().unwrap();
for template in templates {
assert_eq!(template["toolchain"]["type"], "rust");
}
}
#[tokio::test]
async fn test_list_templates_by_category() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "list_templates",
"arguments": {
"category": "makefile"
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
let result = response.result.unwrap();
let templates = result["templates"].as_array().unwrap();
for template in templates {
assert_eq!(template["category"], "makefile");
}
}
#[tokio::test]
async fn test_validate_template_valid() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "validate_template",
"arguments": {
"resource_uri": "template://makefile/rust/cli",
"parameters": {
"project_name": "test-project",
"has_tests": true
}
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
assert!(response.error.is_none());
let result = response.result.unwrap();
assert_eq!(result["valid"], true);
assert!(result["missing_required"].as_array().unwrap().is_empty());
assert!(result["validation_errors"].as_array().unwrap().is_empty());
}
#[tokio::test]
async fn test_validate_template_missing_required() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "validate_template",
"arguments": {
"resource_uri": "template://makefile/rust/cli",
"parameters": {
"has_tests": true
}
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
let result = response.result.unwrap();
assert_eq!(result["valid"], false);
let missing = result["missing_required"].as_array().unwrap();
assert!(missing.iter().any(|v| v == "project_name"));
}
#[tokio::test]
async fn test_validate_template_unknown_parameter() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "validate_template",
"arguments": {
"resource_uri": "template://makefile/rust/cli",
"parameters": {
"project_name": "test",
"unknown_param": "value"
}
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
let result = response.result.unwrap();
assert_eq!(result["valid"], false);
let errors = result["validation_errors"].as_array().unwrap();
assert!(errors
.iter()
.any(|e| e.as_str().unwrap().contains("Unknown parameter")));
}
#[tokio::test]
async fn test_validate_template_not_found() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "validate_template",
"arguments": {
"resource_uri": "template://invalid/template/path",
"parameters": {}
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.error.is_some());
let error = response.error.unwrap();
assert!(error.message.contains("Template not found"));
}
#[tokio::test]
async fn test_scaffold_project_rust() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "scaffold_project",
"arguments": {
"toolchain": "rust",
"templates": ["makefile", "readme", "gitignore"],
"parameters": {
"project_name": "my-rust-app",
"description": "A sample Rust application",
"has_tests": true
}
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
assert!(response.error.is_none());
let result = response.result.unwrap();
let generated = result["generated"].as_array().unwrap();
assert_eq!(generated.len(), 3);
for file in generated {
let template_type = file["template"].as_str().unwrap();
assert!(["makefile", "readme", "gitignore"].contains(&template_type));
assert!(!file["content"].as_str().unwrap().is_empty());
assert!(!file["filename"].as_str().unwrap().is_empty());
}
}
#[tokio::test]
async fn test_scaffold_project_deno() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "scaffold_project",
"arguments": {
"toolchain": "deno",
"templates": ["makefile"],
"parameters": {
"project_name": "my-deno-app",
"permissions": "read,write,net"
}
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
let result = response.result.unwrap();
let generated = result["generated"].as_array().unwrap();
assert_eq!(generated.len(), 1);
assert_eq!(generated[0]["template"], "makefile");
}
#[tokio::test]
async fn test_search_templates_by_name() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "search_templates",
"arguments": {
"query": "makefile"
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
let result = response.result.unwrap();
let templates = result["templates"].as_array().unwrap();
assert!(!templates.is_empty());
for template in templates {
assert!(
template["name"]
.as_str()
.unwrap()
.to_lowercase()
.contains("makefile")
|| template["description"]
.as_str()
.unwrap()
.to_lowercase()
.contains("makefile")
);
}
}
#[tokio::test]
async fn test_search_templates_with_toolchain_filter() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "search_templates",
"arguments": {
"query": "cli",
"toolchain": "rust"
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
let result = response.result.unwrap();
let templates = result["templates"].as_array().unwrap();
for template in templates {
assert_eq!(template["toolchain"]["type"], "rust");
}
}
#[tokio::test]
async fn test_search_templates_no_results() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "search_templates",
"arguments": {
"query": "nonexistenttemplate123"
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.result.is_some());
let result = response.result.unwrap();
let templates = result["templates"].as_array().unwrap();
assert!(templates.is_empty());
}
#[tokio::test]
async fn test_generate_template_invalid_arguments() {
let server = create_test_server();
let request = create_request(
"tools/call",
Some(json!({
"name": "generate_template",
"arguments": {
"invalid_field": "value"
}
})),
);
let response = handle_tool_call(server, request).await;
assert!(response.error.is_some());
let error = response.error.unwrap();
assert!(error
.message
.contains("Invalid generate_template arguments"));
}