Skip to content

Commit 028a169

Browse files
authored
Merge pull request #8 from tomhoule/test-union-generation
Test union codegen
2 parents fc123fe + dd4cd4a commit 028a169

File tree

4 files changed

+115
-20
lines changed

4 files changed

+115
-20
lines changed

.travis.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ rust:
55
- nightly
66
cache: cargo
77
script:
8-
- cargo test --verbose
9-
- cargo test --verbose --manifest-path=./graphql_query_derive/Cargo.toml
8+
- cargo test --all
109
- cargo build --manifest-path=./examples/github/Cargo.toml
1110
- cargo build --manifest-path=./graphql_client_cli/Cargo.toml

graphql_query_derive/src/objects.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl GqlObject {
8585
.fields
8686
.iter()
8787
.find(|field| field.name.as_str() == name.as_str())
88-
.unwrap()
88+
.expect("could not find field")
8989
.type_;
9090
let ty = ty.to_rust(
9191
query_context,

graphql_query_derive/src/query.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl QueryContext {
5353
} else if let Some(iface) = self.schema.interfaces.get(ty) {
5454
Ok(iface.response_for_selection(self, &selection, prefix))
5555
} else if let Some(unn) = self.schema.unions.get(ty) {
56-
Ok(unn.response_for_selection(self, &selection, prefix))
56+
unn.response_for_selection(self, &selection, prefix)
5757
} else {
5858
Ok(quote!())
5959
}

graphql_query_derive/src/unions.rs

Lines changed: 112 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,28 @@ use query::QueryContext;
33
use std::collections::BTreeSet;
44
use selection::{Selection, SelectionItem};
55
use heck::SnakeCase;
6+
use failure;
67

78
#[derive(Debug, PartialEq)]
89
pub struct GqlUnion(pub BTreeSet<String>);
910

11+
#[derive(Debug, Fail)]
12+
#[fail(display = "UnionError")]
13+
enum UnionError {
14+
#[fail(display = "Unknown type: {}", ty)]
15+
UnknownType { ty: String },
16+
}
17+
1018
impl GqlUnion {
1119
pub fn response_for_selection(
1220
&self,
1321
query_context: &QueryContext,
1422
selection: &Selection,
1523
prefix: &str,
16-
) -> TokenStream {
24+
) -> Result<TokenStream, failure::Error> {
1725
let struct_name = Ident::new(prefix, Span::call_site());
18-
let mut children_definitions = Vec::new();
19-
let fields = selection.0.iter().map(|item| {
26+
let mut children_definitions: Vec<TokenStream> = Vec::new();
27+
let fields: Result<Vec<TokenStream>, failure::Error> = selection.0.iter().map(|item| {
2028
match item {
2129
SelectionItem::Field(_) => unreachable!("field selection on union"),
2230
SelectionItem::FragmentSpread(_) => unreachable!("fragment spread on union"),
@@ -38,35 +46,123 @@ impl GqlUnion {
3846
let field_union_type = query_context.schema.unions.get(&frag.on)
3947
.map(|f| query_context.maybe_expand_field(&frag.on, &frag.fields, &new_prefix));
4048

41-
if let Some(tokens) = field_object_type.or(field_interface).or(field_union_type) {
42-
children_definitions.push(tokens)
43-
}
49+
match field_object_type.or(field_interface).or(field_union_type) {
50+
Some(tokens) => children_definitions.push(tokens?),
51+
None => Err(UnionError::UnknownType { ty: frag.on.to_string() })?,
52+
};
4453

45-
// query_context.maybe_expand_field(
46-
47-
// );
48-
quote! {
54+
Ok(quote! {
4955
#field_name: #field_type
50-
}
56+
})
5157
}
5258
}
53-
});
59+
}).collect();
60+
61+
let fields = fields?;
62+
63+
Ok(quote!{
64+
#(#children_definitions)*
5465

55-
quote!{
5666
#[derive(Deserialize)]
5767
pub struct #struct_name {
5868
#(#fields),*
5969
}
60-
}
70+
})
6171
}
6272
}
6373

6474
#[cfg(test)]
6575
mod tests {
76+
use selection::*;
77+
use super::*;
78+
use objects::{GqlObject, GqlObjectField};
79+
use field_type::FieldType;
6680

6781
#[test]
6882
fn union_response_for_selection_works() {
69-
// unimplemented!()
70-
}
83+
let fields = vec![
84+
SelectionItem::InlineFragment(SelectionInlineFragment {
85+
on: "User".to_string(),
86+
fields: Selection(vec![SelectionItem::Field(SelectionField {
87+
name: "first_name".to_string(),
88+
fields: Selection(vec![]),
89+
})]),
90+
}),
91+
SelectionItem::InlineFragment(SelectionInlineFragment {
92+
on: "Organization".to_string(),
93+
fields: Selection(vec![SelectionItem::Field(SelectionField {
94+
name: "title".to_string(),
95+
fields: Selection(vec![]),
96+
})]),
97+
}),
98+
];
99+
let mut context = QueryContext::new_empty();
100+
let selection = Selection(fields);
101+
let prefix = "Meow";
102+
let union = GqlUnion(BTreeSet::new());
103+
104+
let result = union.response_for_selection(
105+
&context,
106+
&selection,
107+
&prefix,
108+
);
109+
71110

111+
assert!(result.is_err());
112+
113+
context.schema.objects.insert(
114+
"User".to_string(), GqlObject {
115+
name: "User".to_string(),
116+
fields: vec![
117+
GqlObjectField {
118+
name: "first_name".to_string(),
119+
type_: FieldType::Named(Ident::new("String", Span::call_site())),
120+
},
121+
GqlObjectField {
122+
name: "last_name".to_string(),
123+
type_: FieldType::Named(Ident::new("String", Span::call_site())),
124+
},
125+
GqlObjectField {
126+
name: "created_at".to_string(),
127+
type_: FieldType::Named(Ident::new("Date", Span::call_site())),
128+
}
129+
],
130+
}
131+
);
132+
133+
context.schema.objects.insert(
134+
"Organization".to_string(), GqlObject {
135+
name: "Organization".to_string(),
136+
fields: vec![
137+
GqlObjectField {
138+
name: "title".to_string(),
139+
type_: FieldType::Named(Ident::new("String", Span::call_site())),
140+
},
141+
GqlObjectField {
142+
name: "created_at".to_string(),
143+
type_: FieldType::Named(Ident::new("Date", Span::call_site())),
144+
}
145+
],
146+
}
147+
);
148+
149+
let result = union.response_for_selection(
150+
&context,
151+
&selection,
152+
&prefix,
153+
);
154+
155+
assert!(result.is_ok());
156+
157+
assert_eq!(
158+
result.unwrap().to_string(),
159+
vec![
160+
"# [ derive ( Debug , Serialize , Deserialize ) ] ",
161+
"pub struct MeowOnUser { first_name : String , } ",
162+
"# [ derive ( Debug , Serialize , Deserialize ) ] ",
163+
"pub struct MeowOnOrganization { title : String , } ",
164+
"# [ derive ( Deserialize ) ] pub struct Meow { on_user : MeowOnUser , on_organization : MeowOnOrganization }",
165+
].into_iter().collect::<String>(),
166+
);
167+
}
72168
}

0 commit comments

Comments
 (0)