mockforge_graphql/
schema.rs1use async_graphql::{Object, Schema, Subscription};
4use futures::stream::Stream;
5use std::time::Duration;
6
7#[derive(async_graphql::SimpleObject, Clone)]
9pub struct User {
10 pub id: String,
12 pub name: String,
14 pub email: String,
16}
17
18#[derive(async_graphql::SimpleObject)]
20pub struct Post {
21 pub id: String,
23 pub title: String,
25 pub content: String,
27 pub author: User,
29}
30
31pub struct QueryRoot;
33
34#[Object]
35impl QueryRoot {
36 async fn users(&self, limit: Option<i32>) -> Vec<User> {
38 let limit = limit.unwrap_or(10) as usize;
39 (0..limit.min(100))
40 .map(|i| User {
41 id: format!("user-{}", i),
42 name: format!("User {}", i),
43 email: format!("user{}@example.com", i),
44 })
45 .collect()
46 }
47
48 async fn user(&self, id: String) -> Option<User> {
50 Some(User {
51 id,
52 name: "Mock User".to_string(),
53 email: "mock@example.com".to_string(),
54 })
55 }
56
57 async fn posts(&self, limit: Option<i32>) -> Vec<Post> {
59 let limit = limit.unwrap_or(10) as usize;
60 (0..limit.min(50))
61 .map(|i| Post {
62 id: format!("post-{}", i),
63 title: format!("Post {}", i),
64 content: format!("This is the content of post {}", i),
65 author: User {
66 id: format!("user-{}", i % 5),
67 name: format!("Author {}", i % 5),
68 email: format!("author{}@example.com", i % 5),
69 },
70 })
71 .collect()
72 }
73}
74
75pub struct MutationRoot;
82
83#[Object]
84impl MutationRoot {
85 async fn create_user(&self, name: String, email: String) -> User {
89 use std::collections::hash_map::DefaultHasher;
90 use std::hash::{Hash, Hasher};
91 let mut hasher = DefaultHasher::new();
92 name.hash(&mut hasher);
93 email.hash(&mut hasher);
94 let id = format!("user-{:012x}", hasher.finish() & 0xffff_ffff_ffff);
98 User { id, name, email }
99 }
100}
101
102pub struct SubscriptionRoot;
112
113#[Subscription]
114impl SubscriptionRoot {
115 async fn tick(&self, count: Option<i32>) -> impl Stream<Item = i32> {
117 let n = count.unwrap_or(5).max(1) as usize;
118 async_stream::stream! {
119 for i in 1..=n {
120 tokio::time::sleep(Duration::from_millis(100)).await;
121 yield i as i32;
122 }
123 }
124 }
125}
126
127pub struct GraphQLSchema {
129 schema: Schema<QueryRoot, MutationRoot, SubscriptionRoot>,
130}
131
132impl GraphQLSchema {
133 pub fn new() -> Self {
135 let schema = Schema::build(QueryRoot, MutationRoot, SubscriptionRoot).finish();
136 Self { schema }
137 }
138
139 pub fn schema(&self) -> &Schema<QueryRoot, MutationRoot, SubscriptionRoot> {
141 &self.schema
142 }
143
144 pub fn generate_basic_schema() -> Self {
146 Self::new()
147 }
148}
149
150impl Default for GraphQLSchema {
151 fn default() -> Self {
152 Self::new()
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn test_user_creation() {
162 let user = User {
163 id: "user-1".to_string(),
164 name: "John Doe".to_string(),
165 email: "john@example.com".to_string(),
166 };
167
168 assert_eq!(user.id, "user-1");
169 assert_eq!(user.name, "John Doe");
170 assert_eq!(user.email, "john@example.com");
171 }
172
173 #[test]
174 fn test_post_creation() {
175 let user = User {
176 id: "user-1".to_string(),
177 name: "Author".to_string(),
178 email: "author@example.com".to_string(),
179 };
180
181 let post = Post {
182 id: "post-1".to_string(),
183 title: "Test Post".to_string(),
184 content: "This is a test post".to_string(),
185 author: user.clone(),
186 };
187
188 assert_eq!(post.id, "post-1");
189 assert_eq!(post.title, "Test Post");
190 assert_eq!(post.author.name, "Author");
191 }
192
193 #[test]
194 fn test_query_root_creation() {
195 let _query = QueryRoot;
196 }
198
199 #[test]
200 fn test_graphql_schema_new() {
201 let schema = GraphQLSchema::new();
202 assert!(!schema.schema().sdl().is_empty());
203 }
204
205 #[test]
206 fn test_graphql_schema_default() {
207 let schema = GraphQLSchema::default();
208 assert!(!schema.schema().sdl().is_empty());
209 }
210
211 #[test]
212 fn test_graphql_schema_generate_basic() {
213 let schema = GraphQLSchema::generate_basic_schema();
214 let sdl = schema.schema().sdl();
215 assert!(sdl.contains("Query"));
216 }
217}