graphql_operation_server_harness/
lib.rs

1//! GraphQL Operation Server Harness
2//!
3//! A test harness for mocking GraphQL endpoints with predefined responses.
4//!
5//! # Example
6//!
7//! ```rust,no_run
8//! use graphql_operation_server_harness::prelude::*;
9//!
10//! #[tokio::main]
11//! async fn main() -> Result<(), HarnessError> {
12//!     let result = ScenarioBuilder::new()
13//!         .server(AsyncGraphQL::default())
14//!         .collector(DefaultCollector::new())
15//!         .operation(
16//!             Operation::query()
17//!                 .with_field(
18//!                     Field::new("users")
19//!                         .with_handler(Handler::new(serde_json::json!({
20//!                             "users": [{"id": 1, "name": "John"}]
21//!                         })))
22//!                 )
23//!         )
24//!         .build()
25//!         .execute()
26//!         .await?;
27//!
28//!     Ok(())
29//! }
30//! ```
31
32mod adapters;
33pub mod entities;
34pub mod error;
35pub mod use_cases;
36
37pub use error::HarnessError;
38
39#[cfg(feature = "async-graphql")]
40pub use adapters::gateways::AsyncGraphQL;
41
42/// Default collector implementation using a thread-safe vector
43pub struct DefaultCollector {
44    requests: std::sync::Mutex<Vec<entities::CollectedRequest>>,
45}
46
47impl DefaultCollector {
48    pub fn new() -> Self {
49        Self {
50            requests: std::sync::Mutex::new(Vec::new()),
51        }
52    }
53}
54
55impl Default for DefaultCollector {
56    fn default() -> Self {
57        Self::new()
58    }
59}
60
61impl use_cases::ports::Collector for DefaultCollector {
62    type Output = Vec<entities::CollectedRequest>;
63
64    fn collect(&self, request: entities::CollectedRequest) {
65        if let Ok(mut requests) = self.requests.lock() {
66            requests.push(request);
67        }
68    }
69
70    fn into_output(self) -> Self::Output {
71        self.requests.into_inner().unwrap_or_default()
72    }
73}
74
75/// Prelude module for convenient imports
76pub mod prelude {
77    pub use crate::entities::{
78        CollectedRequest, Field, GraphQLError, Handler, HandlerResponse, Operation, OperationType,
79        RequestContext, Scenario,
80    };
81    pub use crate::error::HarnessError;
82    pub use crate::use_cases::ports::{Collector, Server};
83    pub use crate::use_cases::ScenarioBuilder;
84    pub use crate::DefaultCollector;
85    pub use serde_json::json;
86
87    #[cfg(feature = "async-graphql")]
88    pub use crate::AsyncGraphQL;
89}