mockforge_core/
openapi.rs

1//! OpenAPI specification handling and utilities
2//!
3//! This module has been refactored into sub-modules for better organization:
4//! - spec: OpenAPI specification loading and parsing
5//! - schema: Schema validation and handling
6//! - route: Route generation from OpenAPI paths
7//! - validation: Request/response validation against schemas
8//! - response: Mock response generation based on schemas
9
10// Re-export sub-modules for backward compatibility
11pub mod response;
12pub mod route;
13pub mod schema;
14pub mod spec;
15pub mod validation;
16
17// Re-export commonly used types (avoiding conflicts)
18pub use response::*;
19pub use route::*;
20pub use schema::*;
21pub use spec::*;
22pub use validation::*;
23
24/// Wrapper for OpenAPI operation with enhanced metadata
25#[derive(Debug, Clone)]
26pub struct OpenApiOperation {
27    /// HTTP method (GET, POST, PUT, etc.)
28    pub method: String,
29    /// API path (e.g., "/api/users/{id}")
30    pub path: String,
31    /// OpenAPI operation specification
32    pub operation: openapiv3::Operation,
33    /// Security requirements for this operation
34    pub security: Option<Vec<openapiv3::SecurityRequirement>>,
35}
36
37impl OpenApiOperation {
38    /// Create a new OpenAPI operation wrapper
39    pub fn new(method: String, path: String, operation: openapiv3::Operation) -> Self {
40        Self {
41            method,
42            path,
43            operation: operation.clone(),
44            security: operation.security.clone(),
45        }
46    }
47
48    /// Create an operation from an OpenAPI operation reference
49    pub fn from_operation(
50        method: &str,
51        path: String,
52        operation: &openapiv3::Operation,
53        _spec: &OpenApiSpec,
54    ) -> Self {
55        Self::new(method.to_string(), path, operation.clone())
56    }
57}
58
59/// Type alias for OpenAPI security requirements
60pub type OpenApiSecurityRequirement = openapiv3::SecurityRequirement;
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn test_openapi_operation_new() {
68        let operation = openapiv3::Operation::default();
69        let op = OpenApiOperation::new("GET".to_string(), "/test".to_string(), operation);
70
71        assert_eq!(op.method, "GET");
72        assert_eq!(op.path, "/test");
73        assert!(op.security.is_none());
74    }
75
76    #[test]
77    fn test_openapi_operation_with_security() {
78        let operation = openapiv3::Operation {
79            security: Some(vec![]),
80            ..Default::default()
81        };
82
83        let op = OpenApiOperation::new("POST".to_string(), "/secure".to_string(), operation);
84
85        assert_eq!(op.method, "POST");
86        assert_eq!(op.path, "/secure");
87        assert!(op.security.is_some());
88    }
89
90    #[test]
91    fn test_openapi_operation_from_operation() {
92        let operation = openapiv3::Operation::default();
93        let spec = OpenApiSpec::from_json(serde_json::json!({
94            "openapi": "3.0.0",
95            "info": {"title": "Test", "version": "1.0.0"},
96            "paths": {}
97        }))
98        .unwrap();
99
100        let op =
101            OpenApiOperation::from_operation("PUT", "/resource".to_string(), &operation, &spec);
102
103        assert_eq!(op.method, "PUT");
104        assert_eq!(op.path, "/resource");
105    }
106
107    #[test]
108    fn test_openapi_operation_clone() {
109        let operation = openapiv3::Operation::default();
110        let op1 = OpenApiOperation::new("GET".to_string(), "/test".to_string(), operation);
111        let op2 = op1.clone();
112
113        assert_eq!(op1.method, op2.method);
114        assert_eq!(op1.path, op2.path);
115    }
116}