clawspec_core/test_client/
error.rs1use std::time::Duration;
7
8use crate::ApiClientError;
9
10#[derive(Debug, derive_more::Error, derive_more::Display, derive_more::From)]
25pub enum TestAppError {
26 #[display("I/O error: {_0}")]
31 IoError(tokio::io::Error),
32
33 #[display("API client error: {_0}")]
38 ClientError(ApiClientError),
39
40 #[display("JSON error: {_0}")]
45 JsonError(serde_json::Error),
46
47 #[display("YAML serialization error: {error}")]
52 YamlError {
53 error: String,
55 },
56
57 #[from(ignore)]
69 #[display("Server failed to become healthy within {timeout:?}")]
70 UnhealthyServer {
71 timeout: Duration,
73 },
74
75 #[display("Server error: {_0}")]
80 ServerError(Box<dyn std::error::Error + Send + Sync + 'static>),
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use std::time::Duration;
87
88 #[test]
89 fn test_test_app_error_display() {
90 let yaml_error = TestAppError::YamlError {
91 error: "Invalid YAML format".to_string(),
92 };
93 assert_eq!(
94 format!("{yaml_error}"),
95 "YAML serialization error: Invalid YAML format"
96 );
97
98 let unhealthy_error = TestAppError::UnhealthyServer {
99 timeout: Duration::from_secs(5),
100 };
101 assert_eq!(
102 format!("{unhealthy_error}"),
103 "Server failed to become healthy within 5s"
104 );
105 }
106
107 #[test]
108 fn test_test_app_error_debug() {
109 let yaml_error = TestAppError::YamlError {
110 error: "Invalid YAML format".to_string(),
111 };
112 let debug_str = format!("{yaml_error:?}");
113 assert!(debug_str.contains("YamlError"));
114 assert!(debug_str.contains("Invalid YAML format"));
115
116 let unhealthy_error = TestAppError::UnhealthyServer {
117 timeout: Duration::from_secs(10),
118 };
119 let debug_str = format!("{unhealthy_error:?}");
120 assert!(debug_str.contains("UnhealthyServer"));
121 assert!(debug_str.contains("10s"));
122 }
123
124 #[test]
125 fn test_test_app_error_from_io_error() {
126 let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
127 let tokio_error = io_error;
128 let test_error: TestAppError = tokio_error.into();
129
130 match test_error {
131 TestAppError::IoError(_) => {} other => panic!("Expected IoError, got: {other:?}"),
133 }
134 }
135
136 #[test]
137 fn test_test_app_error_from_json_error() {
138 let json_str = r#"{"invalid": json"#;
139 let json_error = serde_json::from_str::<serde_json::Value>(json_str).unwrap_err();
140 let test_error: TestAppError = json_error.into();
141
142 match test_error {
143 TestAppError::JsonError(_) => {} other => panic!("Expected JsonError, got: {other:?}"),
145 }
146 }
147
148 #[test]
149 fn test_test_app_error_from_api_client_error() {
150 use crate::ApiClient;
152
153 let build_result = ApiClient::builder()
155 .with_scheme(http::uri::Scheme::HTTPS)
156 .with_host("invalid\0host") .build();
158
159 match build_result {
160 Err(api_error) => {
161 let test_error: TestAppError = api_error.into();
162 match test_error {
163 TestAppError::ClientError(_) => {} other => panic!("Expected ClientError, got: {other:?}"),
165 }
166 }
167 Ok(_) => {
168 use crate::ApiClientError;
172 let api_error = ApiClientError::InvalidBasePath {
173 error: "invalid".to_string(),
174 };
175 let test_error: TestAppError = api_error.into();
176 match test_error {
177 TestAppError::ClientError(_) => {} other => panic!("Expected ClientError, got: {other:?}"),
179 }
180 }
181 }
182 }
183
184 #[test]
185 fn test_yaml_error_creation() {
186 let error_msg = "YAML serialization failed";
187 let yaml_error = TestAppError::YamlError {
188 error: error_msg.to_string(),
189 };
190
191 match yaml_error {
192 TestAppError::YamlError { error } => {
193 assert_eq!(error, error_msg);
194 }
195 other => panic!("Expected YamlError, got: {other:?}"),
196 }
197 }
198
199 #[test]
200 fn test_unhealthy_server_error_creation() {
201 let timeout = Duration::from_millis(2500);
202 let unhealthy_error = TestAppError::UnhealthyServer { timeout };
203
204 match unhealthy_error {
205 TestAppError::UnhealthyServer {
206 timeout: actual_timeout,
207 } => {
208 assert_eq!(actual_timeout, timeout);
209 }
210 other => panic!("Expected UnhealthyServer, got: {other:?}"),
211 }
212 }
213
214 #[test]
215 fn test_server_error_creation() {
216 let server_error = std::io::Error::new(std::io::ErrorKind::AddrInUse, "Port in use");
217 let test_error = TestAppError::ServerError(Box::new(server_error));
218
219 match test_error {
220 TestAppError::ServerError(_) => {} other => panic!("Expected ServerError, got: {other:?}"),
222 }
223 }
224
225 #[test]
226 fn test_error_trait_bounds() {
227 fn assert_error_traits<T>(_: T)
229 where
230 T: std::error::Error + std::fmt::Debug + std::fmt::Display + Send + Sync + 'static,
231 {
232 }
233
234 let yaml_error = TestAppError::YamlError {
235 error: "test".to_string(),
236 };
237 assert_error_traits(yaml_error);
238 }
239
240 #[test]
241 fn test_error_source_chain() {
242 let original_io_error =
244 std::io::Error::new(std::io::ErrorKind::PermissionDenied, "Access denied");
245 let tokio_error = original_io_error;
246 let test_error: TestAppError = tokio_error.into();
247
248 match test_error {
250 TestAppError::IoError(ref io_err) => {
251 assert_eq!(io_err.kind(), tokio::io::ErrorKind::PermissionDenied);
252 }
253 other => panic!("Expected IoError, got: {other:?}"),
254 }
255 }
256}