1mod ent;
2mod filter;
3
4pub use ent::*;
5pub use filter::*;
6
7#[cfg(feature = "macros")]
8pub use entity_async_graphql_macros::*;
9
10#[cfg(test)]
11mod tests {
12 use super::*;
13
14 use async_graphql::{value, Context, EmptyMutation, EmptySubscription, Object, Schema};
15 use entity::{Database, DatabaseRc, Edge, Field, Id, UntypedEnt, Value};
16 use entity_inmemory::InmemoryDatabase;
17 use entity_sled::SledDatabase;
18 use std::collections::HashMap;
19
20 macro_rules! impl_tests {
21 ($db_type:ty, $new_db:expr) => {
22 fn new_test_database() -> $db_type {
29 let db = $new_db;
30
31 let _ = db
33 .insert(Box::from(UntypedEnt::from_collections(1, vec![], vec![])))
34 .unwrap();
35 let _ = db
36 .insert(Box::from(UntypedEnt::from_collections(2, vec![], vec![])))
37 .unwrap();
38 let _ = db
39 .insert(Box::from(UntypedEnt::from_collections(3, vec![], vec![])))
40 .unwrap();
41
42 let _ = db
44 .insert(Box::from(UntypedEnt::from_collections(
45 4,
46 vec![Field::new("a", 1), Field::new("b", 2)],
47 vec![],
48 )))
49 .unwrap();
50 let _ = db
51 .insert(Box::from(UntypedEnt::from_collections(
52 5,
53 vec![Field::new("a", 3), Field::new("b", 4)],
54 vec![],
55 )))
56 .unwrap();
57 let _ = db
58 .insert(Box::from(UntypedEnt::from_collections(
59 6,
60 vec![Field::new("a", 5), Field::new("b", 6)],
61 vec![],
62 )))
63 .unwrap();
64
65 let _ = db
67 .insert(Box::from(UntypedEnt::from_collections(
68 7,
69 vec![Field::new(
70 "f",
71 Value::from(
72 vec![(String::from("a"), 3), (String::from("b"), 5)]
73 .into_iter()
74 .collect::<HashMap<String, u8>>(),
75 ),
76 )],
77 vec![],
78 )))
79 .unwrap();
80 let _ = db
81 .insert(Box::from(UntypedEnt::from_collections(
82 8,
83 vec![Field::new("f", vec![1, 2])],
84 vec![],
85 )))
86 .unwrap();
87 let _ = db
88 .insert(Box::from(UntypedEnt::from_collections(
89 9,
90 vec![Field::new(
91 "f",
92 Value::from(
93 vec![
94 (String::from("a"), Value::from(vec![1, 2])),
95 (String::from("b"), Value::from(vec![3, 4])),
96 ]
97 .into_iter()
98 .collect::<HashMap<String, Value>>(),
99 ),
100 )],
101 vec![],
102 )))
103 .unwrap();
104
105 let _ = db
107 .insert(Box::from(UntypedEnt::from_collections(
108 10,
109 vec![],
110 vec![
111 Edge::new("a", 1),
112 Edge::new("b", vec![3, 4, 5]),
113 Edge::new("c", None),
114 ],
115 )))
116 .unwrap();
117 let _ = db
118 .insert(Box::from(UntypedEnt::from_collections(
119 11,
120 vec![],
121 vec![Edge::new("a", 2), Edge::new("b", vec![1, 2, 3, 4, 5, 6])],
122 )))
123 .unwrap();
124 let _ = db
125 .insert(Box::from(UntypedEnt::from_collections(
126 12,
127 vec![],
128 vec![
129 Edge::new("a", 3),
130 Edge::new("b", vec![]),
131 Edge::new("c", Some(8)),
132 ],
133 )))
134 .unwrap();
135
136 db
137 }
138
139 struct TestQuery;
140
141 #[Object]
142 impl TestQuery {
143 async fn ent<'ctx>(
144 &self,
145 ctx: &'ctx Context<'_>,
146 id: Option<Id>,
147 filter: Option<GqlEntFilter>,
148 ) -> async_graphql::Result<Vec<GqlDynEnt>> {
149 let db = ctx.data::<DatabaseRc>()?;
150
151 if let Some(id) = id {
152 db.get_all(vec![id]).map(|x| x.into_iter().map(GqlDynEnt::from).collect())
153 .map_err(|x| async_graphql::Error::new(x.to_string()))
154 } else if let Some(filter) = filter {
155 db.find_all(filter.into()).map(|x| x.into_iter().map(GqlDynEnt::from).collect())
156 .map_err(|x| async_graphql::Error::new(x.to_string()))
157 } else {
158 Err(async_graphql::Error::new("Must provide one argument"))
159 }
160 }
161 }
162
163 #[test]
164 fn supports_ent_trait_object_as_output_object() {
165 let schema = Schema::build(TestQuery, EmptyMutation, EmptySubscription)
166 .data(DatabaseRc::new(Box::new(new_test_database())))
167 .finish();
168 let input = r#"
169 {
170 ent(id: 1) {
171 id
172 }
173 }
174 "#;
175 let response = futures::executor::block_on(schema.execute(input.trim()));
176 assert_eq!(
177 response.data,
178 value!({
179 "ent": [
180 { "id": 1 },
181 ],
182 })
183 );
184 }
185
186 #[test]
187 fn supports_filtering() {
188 let schema = Schema::build(TestQuery, EmptyMutation, EmptySubscription)
189 .data(DatabaseRc::new(Box::new(new_test_database())))
190 .finish();
191 let input = r#"
192 {
193 ent(filter: { id: { equals: 1 } }) {
194 id
195 }
196 }
197 "#;
198 let response = futures::executor::block_on(schema.execute(input.trim()));
199 assert_eq!(
200 response.data,
201 value!({
202 "ent": [
203 { "id": 1 },
204 ],
205 })
206 );
207 }
208 };
209 }
210
211 mod inmemory {
212 use super::*;
213
214 impl_tests!(InmemoryDatabase, InmemoryDatabase::default());
215 }
216
217 mod sled {
218 use super::*;
219
220 impl_tests!(
221 SledDatabase,
222 SledDatabase::new(::sled::Config::new().temporary(true).open().unwrap())
223 );
224 }
225}