1#[cfg(test)]
4mod tests {
5 use super::*;
6 use crate::{HttpConfig, MinimalHttpServer};
7 use elif_core::{
8 Container,
9 container::test_implementations::*,
10 app_config::{AppConfigTrait},
11 };
12 use std::sync::Arc;
13
14 fn create_test_container() -> Arc<Container> {
15 let config = Arc::new(create_test_config());
16 let database = Arc::new(TestDatabase::new()) as Arc<dyn elif_core::DatabaseConnection>;
17
18 Container::builder()
19 .config(config)
20 .database(database)
21 .build()
22 .unwrap()
23 .into()
24 }
25
26 #[test]
27 fn test_http_config_defaults() {
28 let config = HttpConfig::default();
29
30 assert_eq!(config.request_timeout_secs, 30);
31 assert_eq!(config.keep_alive_timeout_secs, 75);
32 assert_eq!(config.max_request_size, 16 * 1024 * 1024);
33 assert!(config.enable_tracing);
34 assert_eq!(config.health_check_path, "/health");
35 assert_eq!(config.shutdown_timeout_secs, 10);
36 }
37
38 #[test]
39 fn test_http_config_from_env() {
40 std::env::remove_var("HTTP_REQUEST_TIMEOUT");
41 std::env::remove_var("HTTP_KEEP_ALIVE_TIMEOUT");
42
43 let config = HttpConfig::from_env().unwrap();
44 config.validate().unwrap();
45
46 assert_eq!(config.request_timeout().as_secs(), 30);
48 assert_eq!(config.keep_alive_timeout().as_secs(), 75);
49 assert_eq!(config.shutdown_timeout().as_secs(), 10);
50 }
51
52 #[test]
53 fn test_http_config_validation() {
54 let mut config = HttpConfig::default();
55 assert!(config.validate().is_ok());
56
57 config.request_timeout_secs = 0;
59 assert!(config.validate().is_err());
60
61 config = HttpConfig::default();
63 config.health_check_path = "no-slash".to_string();
64 assert!(config.validate().is_err());
65
66 config.health_check_path = "".to_string();
67 assert!(config.validate().is_err());
68 }
69
70 #[test]
71 fn test_minimal_server_creation() {
72 let container = create_test_container();
73 let http_config = HttpConfig::default();
74
75 let server = MinimalHttpServer::new(container, http_config);
76 assert!(server.is_ok());
77 }
78
79 #[test]
80 fn test_minimal_server_with_invalid_address() {
81 let mut app_config = create_test_config();
83 app_config.server.host = "999.999.999.999".to_string(); let config_arc = Arc::new(app_config);
85
86 let database = Arc::new(TestDatabase::new()) as Arc<dyn elif_core::DatabaseConnection>;
87 let container = Container::builder()
88 .config(config_arc)
89 .database(database)
90 .build()
91 .unwrap();
92
93 let http_config = HttpConfig::default();
94 let result = MinimalHttpServer::new(Arc::new(container), http_config);
95
96 assert!(result.is_err());
97 if let Err(e) = result {
98 assert!(e.to_string().contains("Invalid server address"));
99 }
100 }
101
102 #[tokio::test]
103 async fn test_health_check_endpoint() {
104 use crate::minimal_server::minimal_health_check;
105
106 let response = minimal_health_check().await;
107 let value = response.0;
108
109 assert_eq!(value["status"], "healthy");
110 assert_eq!(value["version"], "0.1.0");
111 assert_eq!(value["server"], "minimal");
112 assert!(value["timestamp"].is_string());
113 }
114
115 #[test]
116 fn test_http_error_types() {
117 use crate::error::HttpError;
118 use axum::http::StatusCode;
119
120 let startup_error = HttpError::startup("Failed to bind");
121 assert_eq!(startup_error.status_code(), StatusCode::INTERNAL_SERVER_ERROR);
122 assert_eq!(startup_error.error_code(), "SERVER_STARTUP_FAILED");
123
124 let timeout_error = HttpError::RequestTimeout;
125 assert_eq!(timeout_error.status_code(), StatusCode::REQUEST_TIMEOUT);
126 assert_eq!(timeout_error.error_code(), "REQUEST_TIMEOUT");
127
128 let bad_request = HttpError::bad_request("Invalid input");
129 assert_eq!(bad_request.status_code(), StatusCode::BAD_REQUEST);
130 assert_eq!(bad_request.error_code(), "BAD_REQUEST");
131 }
132
133 #[test]
134 fn test_error_conversions() {
135 use crate::error::HttpError;
136 use elif_core::app_config::ConfigError;
137
138 let config_error = ConfigError::MissingEnvVar {
140 var: "TEST_VAR".to_string(),
141 };
142 let http_error: HttpError = config_error.into();
143 assert!(matches!(http_error, HttpError::ConfigError { .. }));
144
145 let io_error = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "Access denied");
147 let http_error: HttpError = io_error.into();
148 assert!(matches!(http_error, HttpError::InternalError { .. }));
149 }
150}