1#![allow(async_fn_in_trait)]
6
7use crate::Error;
8use mockforge_core::{
9 request_logger::get_global_logger, verify_at_least, verify_never, verify_requests,
10 verify_sequence, VerificationCount, VerificationRequest, VerificationResult,
11};
12
13pub trait Verification {
15 async fn verify(
43 &self,
44 pattern: &VerificationRequest,
45 expected: VerificationCount,
46 ) -> Result<VerificationResult, Error>;
47
48 async fn verify_never(
76 &self,
77 pattern: &VerificationRequest,
78 ) -> Result<VerificationResult, Error>;
79
80 async fn verify_at_least(
108 &self,
109 pattern: &VerificationRequest,
110 min: usize,
111 ) -> Result<VerificationResult, Error>;
112
113 async fn verify_sequence(
150 &self,
151 patterns: &[VerificationRequest],
152 ) -> Result<VerificationResult, Error>;
153}
154
155impl Verification for crate::server::MockServer {
156 async fn verify(
157 &self,
158 pattern: &VerificationRequest,
159 expected: VerificationCount,
160 ) -> Result<VerificationResult, Error> {
161 let logger = get_global_logger()
162 .ok_or_else(|| Error::General("Request logger not initialized".to_string()))?;
163
164 Ok(verify_requests(logger, pattern, expected).await)
165 }
166
167 async fn verify_never(
168 &self,
169 pattern: &VerificationRequest,
170 ) -> Result<VerificationResult, Error> {
171 let logger = get_global_logger()
172 .ok_or_else(|| Error::General("Request logger not initialized".to_string()))?;
173
174 Ok(verify_never(logger, pattern).await)
175 }
176
177 async fn verify_at_least(
178 &self,
179 pattern: &VerificationRequest,
180 min: usize,
181 ) -> Result<VerificationResult, Error> {
182 let logger = get_global_logger()
183 .ok_or_else(|| Error::General("Request logger not initialized".to_string()))?;
184
185 Ok(verify_at_least(logger, pattern, min).await)
186 }
187
188 async fn verify_sequence(
189 &self,
190 patterns: &[VerificationRequest],
191 ) -> Result<VerificationResult, Error> {
192 let logger = get_global_logger()
193 .ok_or_else(|| Error::General("Request logger not initialized".to_string()))?;
194
195 Ok(verify_sequence(logger, patterns).await)
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use super::*;
202 use std::collections::HashMap;
203
204 fn create_verification_request(method: &str, path: &str) -> VerificationRequest {
206 VerificationRequest {
207 method: Some(method.to_string()),
208 path: Some(path.to_string()),
209 query_params: HashMap::new(),
210 headers: HashMap::new(),
211 body_pattern: None,
212 }
213 }
214
215 #[test]
216 fn test_verification_request_creation() {
217 let request = create_verification_request("GET", "/api/users");
218 assert_eq!(request.method, Some("GET".to_string()));
219 assert_eq!(request.path, Some("/api/users".to_string()));
220 assert!(request.query_params.is_empty());
221 assert!(request.headers.is_empty());
222 assert!(request.body_pattern.is_none());
223 }
224
225 #[test]
226 fn test_verification_request_with_query_params() {
227 let mut query_params = HashMap::new();
228 query_params.insert("page".to_string(), "1".to_string());
229 query_params.insert("limit".to_string(), "10".to_string());
230
231 let request = VerificationRequest {
232 method: Some("GET".to_string()),
233 path: Some("/api/users".to_string()),
234 query_params,
235 headers: HashMap::new(),
236 body_pattern: None,
237 };
238
239 assert_eq!(request.query_params.len(), 2);
240 assert_eq!(request.query_params.get("page"), Some(&"1".to_string()));
241 assert_eq!(request.query_params.get("limit"), Some(&"10".to_string()));
242 }
243
244 #[test]
245 fn test_verification_request_with_headers() {
246 let mut headers = HashMap::new();
247 headers.insert("Authorization".to_string(), "Bearer token".to_string());
248 headers.insert("Content-Type".to_string(), "application/json".to_string());
249
250 let request = VerificationRequest {
251 method: Some("POST".to_string()),
252 path: Some("/api/users".to_string()),
253 query_params: HashMap::new(),
254 headers,
255 body_pattern: None,
256 };
257
258 assert_eq!(request.headers.len(), 2);
259 assert_eq!(request.headers.get("Authorization"), Some(&"Bearer token".to_string()));
260 }
261
262 #[test]
263 fn test_verification_request_with_body_pattern() {
264 let request = VerificationRequest {
265 method: Some("POST".to_string()),
266 path: Some("/api/users".to_string()),
267 query_params: HashMap::new(),
268 headers: HashMap::new(),
269 body_pattern: Some(r#"{"name":".*"}"#.to_string()),
270 };
271
272 assert_eq!(request.body_pattern, Some(r#"{"name":".*"}"#.to_string()));
273 }
274
275 #[test]
276 fn test_verification_count_exactly() {
277 let count = VerificationCount::Exactly(3);
278 match count {
279 VerificationCount::Exactly(n) => assert_eq!(n, 3),
280 _ => panic!("Expected Exactly variant"),
281 }
282 }
283
284 #[test]
285 fn test_verification_count_at_least() {
286 let count = VerificationCount::AtLeast(2);
287 match count {
288 VerificationCount::AtLeast(n) => assert_eq!(n, 2),
289 _ => panic!("Expected AtLeast variant"),
290 }
291 }
292
293 #[test]
294 fn test_verification_count_at_most() {
295 let count = VerificationCount::AtMost(5);
296 match count {
297 VerificationCount::AtMost(n) => assert_eq!(n, 5),
298 _ => panic!("Expected AtMost variant"),
299 }
300 }
301
302 #[test]
303 fn test_verification_count_never() {
304 let count = VerificationCount::Never;
305 match count {
306 VerificationCount::Never => (),
307 _ => panic!("Expected Never variant"),
308 }
309 }
310
311 #[tokio::test]
312 async fn test_verify_error_when_logger_not_initialized() {
313 let server = crate::server::MockServer::default();
314 let request = create_verification_request("GET", "/api/test");
315
316 let result = server.verify(&request, VerificationCount::Exactly(1)).await;
318
319 if result.is_err() {
322 match result {
323 Err(Error::General(msg)) => {
324 assert!(msg.contains("Request logger not initialized"));
325 }
326 _ => panic!("Expected General error about logger"),
327 }
328 }
329 }
330
331 #[tokio::test]
332 async fn test_verify_never_error_when_logger_not_initialized() {
333 let server = crate::server::MockServer::default();
334 let request = create_verification_request("DELETE", "/api/users/1");
335
336 let result = server.verify_never(&request).await;
337
338 if result.is_err() {
339 match result {
340 Err(Error::General(msg)) => {
341 assert!(msg.contains("Request logger not initialized"));
342 }
343 _ => panic!("Expected General error about logger"),
344 }
345 }
346 }
347
348 #[tokio::test]
349 async fn test_verify_at_least_error_when_logger_not_initialized() {
350 let server = crate::server::MockServer::default();
351 let request = create_verification_request("POST", "/api/orders");
352
353 let result = server.verify_at_least(&request, 2).await;
354
355 if result.is_err() {
356 match result {
357 Err(Error::General(msg)) => {
358 assert!(msg.contains("Request logger not initialized"));
359 }
360 _ => panic!("Expected General error about logger"),
361 }
362 }
363 }
364
365 #[tokio::test]
366 async fn test_verify_sequence_error_when_logger_not_initialized() {
367 let server = crate::server::MockServer::default();
368 let patterns = [
369 create_verification_request("POST", "/api/users"),
370 create_verification_request("GET", "/api/users/1"),
371 ];
372
373 let result = server.verify_sequence(&patterns).await;
374
375 if result.is_err() {
376 match result {
377 Err(Error::General(msg)) => {
378 assert!(msg.contains("Request logger not initialized"));
379 }
380 _ => panic!("Expected General error about logger"),
381 }
382 }
383 }
384
385 #[test]
386 fn test_verification_request_all_fields() {
387 let mut query_params = HashMap::new();
388 query_params.insert("id".to_string(), "123".to_string());
389
390 let mut headers = HashMap::new();
391 headers.insert("X-Custom".to_string(), "value".to_string());
392
393 let request = VerificationRequest {
394 method: Some("PUT".to_string()),
395 path: Some("/api/users/123".to_string()),
396 query_params,
397 headers,
398 body_pattern: Some(r#"{"name":"test"}"#.to_string()),
399 };
400
401 assert_eq!(request.method, Some("PUT".to_string()));
402 assert_eq!(request.path, Some("/api/users/123".to_string()));
403 assert_eq!(request.query_params.len(), 1);
404 assert_eq!(request.headers.len(), 1);
405 assert!(request.body_pattern.is_some());
406 }
407
408 #[test]
409 fn test_verification_request_minimal() {
410 let request = VerificationRequest {
411 method: None,
412 path: None,
413 query_params: HashMap::new(),
414 headers: HashMap::new(),
415 body_pattern: None,
416 };
417
418 assert!(request.method.is_none());
419 assert!(request.path.is_none());
420 assert!(request.query_params.is_empty());
421 assert!(request.headers.is_empty());
422 assert!(request.body_pattern.is_none());
423 }
424
425 #[test]
426 fn test_verification_sequence_empty() {
427 let patterns: Vec<VerificationRequest> = vec![];
428 assert_eq!(patterns.len(), 0);
429 }
430
431 #[test]
432 fn test_verification_sequence_single() {
433 let patterns = [create_verification_request("GET", "/api/test")];
434 assert_eq!(patterns.len(), 1);
435 }
436
437 #[test]
438 fn test_verification_sequence_multiple() {
439 let patterns = [
440 create_verification_request("POST", "/api/users"),
441 create_verification_request("GET", "/api/users/1"),
442 create_verification_request("PUT", "/api/users/1"),
443 create_verification_request("DELETE", "/api/users/1"),
444 ];
445 assert_eq!(patterns.len(), 4);
446 }
447
448 #[test]
449 fn test_verification_with_complex_pattern() {
450 let mut query_params = HashMap::new();
451 query_params.insert("filter".to_string(), "active".to_string());
452 query_params.insert("sort".to_string(), "name".to_string());
453
454 let mut headers = HashMap::new();
455 headers.insert("Accept".to_string(), "application/json".to_string());
456 headers.insert("X-API-Key".to_string(), "secret".to_string());
457
458 let request = VerificationRequest {
459 method: Some("GET".to_string()),
460 path: Some("/api/users".to_string()),
461 query_params,
462 headers,
463 body_pattern: None,
464 };
465
466 assert_eq!(request.method, Some("GET".to_string()));
467 assert_eq!(request.query_params.len(), 2);
468 assert_eq!(request.headers.len(), 2);
469 }
470}