use super::*;
use schemars::JsonSchema;
use serde::Deserialize;
#[derive(Deserialize, JsonSchema)]
struct TodoItemParam {
#[serde(default)]
id: Option<String>,
#[serde(default)]
content: String,
#[serde(default = "default_status")]
status: String,
}
fn default_status() -> String {
"pending".to_string()
}
#[derive(Deserialize, JsonSchema)]
struct TodoWriteParams {
todos: Vec<TodoItemParam>,
#[serde(default)]
merge: bool,
}
#[test]
fn test_schema_content_not_required() {
let schema = schema_to_tool_params::<TodoWriteParams>();
let required: Vec<&str> = schema
.get("required")
.and_then(|r| r.as_array())
.map(|arr| arr.iter().filter_map(|v| v.as_str()).collect())
.unwrap_or_default();
assert!(
required.contains(&"todos"),
"todos should be required, got: {:?}",
required
);
assert!(
!required.contains(&"merge"),
"merge should NOT be required (has serde default), got: {:?}",
required
);
let todos_schema = schema
.get("properties")
.and_then(|p| p.get("todos"))
.and_then(|t| t.get("items"));
assert!(todos_schema.is_some(), "todos.items should exist in schema");
let item_required: Vec<&str> = todos_schema
.and_then(|s| s.get("required"))
.and_then(|r| r.as_array())
.map(|arr| arr.iter().filter_map(|v| v.as_str()).collect())
.unwrap_or_default();
assert!(
!item_required.contains(&"content"),
"content should NOT be required in todo items (has serde default), got required: {:?}",
item_required
);
assert!(
!item_required.contains(&"id"),
"id should NOT be required in todo items (has serde default), got required: {:?}",
item_required
);
}
#[test]
fn test_schema_no_dangling_refs() {
let schema = schema_to_tool_params::<TodoWriteParams>();
let schema_str = serde_json::to_string(&schema).unwrap();
assert!(
!schema_str.contains("\"$ref\""),
"Schema should not contain any $ref after inlining, got: {}",
schema_str
);
}
#[test]
fn test_merge_without_content_deserializes() {
let json = r#"{"todos": [{"id": "1", "status": "completed"}], "merge": true}"#;
let params: TodoWriteParams = serde_json::from_str(json).unwrap();
assert!(params.merge);
assert_eq!(params.todos.len(), 1);
assert_eq!(params.todos[0].id, Some("1".to_string()));
assert_eq!(params.todos[0].content, ""); assert_eq!(params.todos[0].status, "completed");
}
#[test]
fn test_full_params_deserialize() {
let json = r#"{"todos": [{"id": "1", "content": "implement feature", "status": "in_progress"}, {"content": "write tests"}], "merge": false}"#;
let params: TodoWriteParams = serde_json::from_str(json).unwrap();
assert!(!params.merge);
assert_eq!(params.todos.len(), 2);
assert_eq!(params.todos[0].content, "implement feature");
assert_eq!(params.todos[1].id, None);
assert_eq!(params.todos[1].content, "write tests");
assert_eq!(params.todos[1].status, "pending"); }