turbomcp_protocol/
test_helpers.rs

1//! Test utilities for turbomcp-protocol
2//!
3//! This module provides shared test helpers used throughout the crate's tests.
4//! Following the pattern from axum and tokio, these utilities are public to
5//! allow downstream crates to use them in their tests.
6//!
7//! ## Organization
8//!
9//! All test fixtures and helpers are in this single module for simplicity.
10//! As the test suite grows, this can be split into submodules if needed.
11//!
12//! ## Usage
13//!
14//! ```rust
15//! #[cfg(test)]
16//! mod tests {
17//!     use super::*;
18//!     use crate::test_helpers::*;
19//!
20//!     #[test]
21//!     fn my_test() {
22//!         let request = test_request();
23//!         assert_valid(&result);
24//!     }
25//! }
26//! ```
27
28use crate::jsonrpc::*;
29use crate::types::*;
30use crate::validation::*;
31
32// ========== JSON-RPC Request Fixtures ==========
33
34/// Create a standard test JSON-RPC request
35pub fn test_request() -> JsonRpcRequest {
36    JsonRpcRequest {
37        jsonrpc: JsonRpcVersion,
38        method: "tools/list".to_string(),
39        params: None,
40        id: RequestId::String("test-123".to_string()),
41    }
42}
43
44/// Create a valid tool for testing
45pub fn test_tool() -> Tool {
46    Tool {
47        name: "test_tool".to_string(),
48        title: Some("Test Tool".to_string()),
49        description: Some("A test tool for validation".to_string()),
50        input_schema: ToolInputSchema {
51            schema_type: "object".to_string(),
52            properties: None,
53            required: None,
54            additional_properties: None,
55        },
56        output_schema: None,
57        annotations: None,
58        meta: None,
59    }
60}
61
62/// Create a valid prompt for testing
63pub fn test_prompt() -> Prompt {
64    Prompt {
65        name: "test_prompt".to_string(),
66        title: Some("Test Prompt".to_string()),
67        description: Some("A test prompt".to_string()),
68        arguments: None,
69        meta: None,
70    }
71}
72
73/// Create a prompt argument for testing
74pub fn test_prompt_argument(name: &str) -> PromptArgument {
75    PromptArgument {
76        name: name.to_string(),
77        title: Some(format!("Argument {name}")),
78        description: Some(format!("Description for {name}")),
79        required: Some(true),
80    }
81}
82
83/// Create a valid resource for testing
84pub fn test_resource() -> Resource {
85    Resource {
86        name: "test_resource".to_string(),
87        title: Some("Test Resource".to_string()),
88        uri: "file://test/resource.txt".to_string(),
89        description: Some("A test resource".to_string()),
90        mime_type: Some("text/plain".to_string()),
91        annotations: None,
92        size: Some(1024),
93        meta: None,
94    }
95}
96
97/// Create a valid initialize request for testing
98pub fn test_initialize_request() -> InitializeRequest {
99    InitializeRequest {
100        protocol_version: "2025-06-18".to_string(),
101        capabilities: ClientCapabilities::default(),
102        client_info: Implementation {
103            name: "test-client".to_string(),
104            title: Some("Test Client".to_string()),
105            version: "1.0.0".to_string(),
106        },
107        _meta: None,
108    }
109}
110
111// ========== Validation Assertions ==========
112
113/// Assert that validation passed without warnings
114#[allow(dead_code)]
115pub fn assert_valid(result: &ValidationResult) {
116    assert!(
117        result.is_valid(),
118        "Expected validation to pass, but got errors: {:?}",
119        result.errors()
120    );
121}
122
123/// Assert that validation failed
124#[allow(dead_code)]
125pub fn assert_invalid(result: &ValidationResult) {
126    assert!(
127        result.is_invalid(),
128        "Expected validation to fail, but it passed"
129    );
130}