mockforge_graphql/lib.rs
1//! # MockForge GraphQL
2//!
3//! GraphQL mocking library for MockForge with schema-based query execution.
4//!
5//! This crate provides GraphQL mocking capabilities including:
6//!
7//! - **Schema-Based Mocking**: Define GraphQL schemas and automatically generate resolvers
8//! - **Query & Mutation Support**: Handle queries, mutations, and subscriptions
9//! - **Type System**: Full GraphQL type system support (scalars, objects, interfaces, unions)
10//! - **Introspection**: Built-in introspection queries for tooling
11//! - **Playground Integration**: GraphQL Playground UI for interactive testing
12//!
13//! ## Overview
14//!
15//! MockForge GraphQL allows you to define GraphQL schemas and automatically mock
16//! resolvers with realistic data. Perfect for frontend development and integration testing.
17//!
18//! ## Quick Start
19//!
20//! ### Basic GraphQL Server
21//!
22//! ```rust,no_run
23//! use mockforge_graphql::start;
24//!
25//! #[tokio::main]
26//! async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
27//! // Start GraphQL server on port 4000
28//! start(4000).await?;
29//! Ok(())
30//! }
31//! ```
32//!
33//! ### With Custom Schema
34//!
35//! ```rust,no_run
36//! use mockforge_graphql::{GraphQLSchema, GraphQLExecutor, create_graphql_router};
37//! use mockforge_core::LatencyProfile;
38//!
39//! # async fn example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
40//! let schema = GraphQLSchema::from_file("schema.graphql").await?;
41//! let latency = Some(LatencyProfile::fast());
42//! let router = create_graphql_router(latency).await?;
43//! # Ok(())
44//! # }
45//! ```
46//!
47//! ## GraphQL Schema Example
48//!
49//! Define your GraphQL schema:
50//!
51//! ```graphql
52//! type Query {
53//! user(id: ID!): User
54//! users(limit: Int = 10): [User!]!
55//! }
56//!
57//! type Mutation {
58//! createUser(input: CreateUserInput!): User!
59//! updateUser(id: ID!, input: UpdateUserInput!): User!
60//! }
61//!
62//! type User {
63//! id: ID!
64//! name: String!
65//! email: String!
66//! posts: [Post!]!
67//! }
68//!
69//! type Post {
70//! id: ID!
71//! title: String!
72//! content: String!
73//! author: User!
74//! }
75//!
76//! input CreateUserInput {
77//! name: String!
78//! email: String!
79//! }
80//! ```
81//!
82//! MockForge automatically generates resolvers with realistic data:
83//!
84//! ```bash
85//! # Query
86//! curl -X POST http://localhost:4000/graphql \
87//! -H "Content-Type: application/json" \
88//! -d '{"query": "{ user(id: \"123\") { id name email } }"}'
89//!
90//! # Mutation
91//! curl -X POST http://localhost:4000/graphql \
92//! -H "Content-Type: application/json" \
93//! -d '{"query": "mutation { createUser(input: {name: \"Alice\", email: \"alice@example.com\"}) { id } }"}'
94//! ```
95//!
96//! ## GraphQL Playground
97//!
98//! Access the interactive GraphQL Playground at:
99//! ```
100//! http://localhost:4000/playground
101//! ```
102//!
103//! The Playground provides:
104//! - Schema explorer
105//! - Query editor with auto-complete
106//! - Response viewer
107//! - Request history
108//!
109//! ## Features
110//!
111//! ### Automatic Resolver Generation
112//! - Generates realistic data based on field names and types
113//! - Maintains referential integrity between related types
114//! - Supports nested queries and relationships
115//!
116//! ### Latency Simulation
117//! - Simulate network delays for realistic testing
118//! - Per-resolver latency configuration
119//! - Random or fixed latency profiles
120//!
121//! ### Error Injection
122//! - Simulate GraphQL errors and partial responses
123//! - Configure error rates per resolver
124//! - Test error handling in client applications
125//!
126//! ## Key Modules
127//!
128//! - [`executor`]: GraphQL query execution engine
129//! - [`schema`]: Schema parsing and validation
130//! - [`registry`]: Type and resolver registry
131//! - [`graphql_tracing`]: Distributed tracing integration
132//!
133//! ## Examples
134//!
135//! See the [examples directory](https://github.com/SaaSy-Solutions/mockforge/tree/main/examples)
136//! for complete working examples.
137//!
138//! ## Related Crates
139//!
140//! - [`mockforge-core`](https://docs.rs/mockforge-core): Core mocking functionality
141//! - [`mockforge-data`](https://docs.rs/mockforge-data): Synthetic data generation
142//!
143//! ## Documentation
144//!
145//! - [MockForge Book](https://docs.mockforge.dev/)
146//! - [GraphQL Mocking Guide](https://docs.mockforge.dev/user-guide/graphql-mocking.html)
147//! - [API Reference](https://docs.rs/mockforge-graphql)
148
149use mockforge_core::LatencyProfile;
150
151pub mod executor;
152pub mod graphql_tracing;
153pub mod registry;
154pub mod schema;
155
156pub use executor::{create_graphql_router, start_graphql_server, GraphQLExecutor};
157pub use registry::GraphQLSchemaRegistry;
158pub use schema::GraphQLSchema;
159
160// Re-export tracing utilities
161pub use graphql_tracing::{
162 create_graphql_span, create_resolver_span, record_graphql_error, record_graphql_success,
163 record_resolver_error, record_resolver_success,
164};
165
166/// Start GraphQL server with default configuration
167pub async fn start(port: u16) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
168 start_with_latency(port, None).await
169}
170
171/// Start GraphQL server with latency configuration
172pub async fn start_with_latency(
173 port: u16,
174 latency_profile: Option<LatencyProfile>,
175) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
176 start_graphql_server(port, latency_profile).await
177}
178
179/// Create a GraphQL router with latency support
180pub async fn create_router(
181 latency_profile: Option<LatencyProfile>,
182) -> Result<axum::Router, Box<dyn std::error::Error + Send + Sync>> {
183 create_graphql_router(latency_profile).await
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189
190 #[tokio::test]
191 async fn test_create_router_without_latency() {
192 let result = create_router(None).await;
193 assert!(result.is_ok());
194 }
195
196 #[tokio::test]
197 async fn test_create_router_with_latency() {
198 let latency_profile = LatencyProfile::default();
199 let result = create_router(Some(latency_profile)).await;
200 assert!(result.is_ok());
201 }
202
203 #[tokio::test]
204 async fn test_create_router_with_custom_latency() {
205 let latency_profile = LatencyProfile::with_normal_distribution(50, 10.0);
206 let result = create_router(Some(latency_profile)).await;
207 assert!(result.is_ok());
208 }
209}