@@ -2,15 +2,17 @@ use failure;
2
2
use objects:: GqlObjectField ;
3
3
use proc_macro2:: { Ident , Span , TokenStream } ;
4
4
use query:: QueryContext ;
5
- use selection:: { Selection , SelectionFragmentSpread , SelectionItem } ;
5
+ use selection:: { Selection , SelectionField , SelectionFragmentSpread , SelectionItem } ;
6
6
use shared:: * ;
7
7
use std:: borrow:: Cow ;
8
8
use std:: cell:: Cell ;
9
9
use std:: collections:: HashSet ;
10
10
use unions:: union_variants;
11
11
12
+ /// Represents an Interface type extracted from the schema.
12
13
#[ derive( Debug , Clone , PartialEq ) ]
13
14
pub struct GqlInterface {
15
+ /// The documentation for the interface. Extracted from the schema.
14
16
pub description : Option < String > ,
15
17
/// The set of object types implementing this interface.
16
18
pub implemented_by : HashSet < String > ,
@@ -48,6 +50,32 @@ impl GqlInterface {
48
50
)
49
51
}
50
52
53
+ fn union_selection ( & self , selection : & Selection , query_context : & QueryContext ) -> Selection {
54
+ Selection (
55
+ selection
56
+ . 0
57
+ . iter ( )
58
+ // Only keep what we can handle
59
+ . filter ( |f| match f {
60
+ SelectionItem :: InlineFragment ( _) => true ,
61
+ SelectionItem :: FragmentSpread ( SelectionFragmentSpread { fragment_name } ) => {
62
+ let fragment = query_context
63
+ . fragments
64
+ . get ( fragment_name)
65
+ . ok_or_else ( || format_err ! ( "Unknown fragment: {}" , & fragment_name) )
66
+ // TODO: fix this
67
+ . unwrap ( ) ;
68
+
69
+ // only the fragments _not_ on the interface
70
+ fragment. on != self . name
71
+ } ,
72
+ SelectionItem :: Field ( SelectionField { name, .. } ) => name == "__typename" ,
73
+ } ) . map ( |a| ( * a) . clone ( ) )
74
+ . collect ( ) ,
75
+
76
+ )
77
+ }
78
+
51
79
/// Create an empty interface. This needs to be mutated before it is useful.
52
80
pub ( crate ) fn new ( name : Cow < str > , description : Option < & str > ) -> GqlInterface {
53
81
GqlInterface {
@@ -102,24 +130,15 @@ impl GqlInterface {
102
130
103
131
selection
104
132
. extract_typename ( )
105
- . ok_or_else ( || format_err ! ( "Missing __typename in selection for {}" , prefix) ) ?;
106
-
107
- let union_selection = Selection (
108
- selection
109
- . 0
110
- . iter ( )
111
- // Only keep what we can handle
112
- . filter ( |f| match f {
113
- SelectionItem :: InlineFragment ( _) | SelectionItem :: FragmentSpread ( _) => true ,
114
- SelectionItem :: Field ( _) => false ,
115
- } ) . map ( |a| ( * a) . clone ( ) )
116
- . collect ( ) ,
117
- ) ;
133
+ . ok_or_else ( || format_err ! ( "Missing __typename in selection for the {} interface (type: {})" , prefix, self . name) ) ?;
118
134
119
135
let object_fields =
120
136
self . response_fields_for_selection ( query_context, & selection, prefix) ?;
121
137
122
138
let object_children = self . field_impls_for_selection ( query_context, & selection, prefix) ?;
139
+
140
+ let union_selection = self . union_selection ( & selection, & query_context) ;
141
+
123
142
let ( mut union_variants, union_children, used_variants) =
124
143
union_variants ( & union_selection, query_context, prefix) ?;
125
144
@@ -164,3 +183,44 @@ impl GqlInterface {
164
183
} )
165
184
}
166
185
}
186
+
187
+ #[ cfg( test) ]
188
+ mod tests {
189
+ use super :: * ;
190
+
191
+ // to be improved
192
+ #[ test]
193
+ fn union_selection_works ( ) {
194
+ let iface = GqlInterface {
195
+ description : None ,
196
+ implemented_by : HashSet :: new ( ) ,
197
+ name : "MyInterface" . into ( ) ,
198
+ fields : vec ! [ ] ,
199
+ is_required : Cell :: new ( true ) ,
200
+ } ;
201
+
202
+ let context = QueryContext :: new_empty ( ) ;
203
+
204
+ let selection = Selection ( vec ! [ ] ) ;
205
+
206
+ assert_eq ! ( iface. union_selection( & selection, & context) , Selection ( vec![ ] ) ) ;
207
+ }
208
+
209
+ // to be improved
210
+ #[ test]
211
+ fn object_selection_works ( ) {
212
+ let iface = GqlInterface {
213
+ description : None ,
214
+ implemented_by : HashSet :: new ( ) ,
215
+ name : "MyInterface" . into ( ) ,
216
+ fields : vec ! [ ] ,
217
+ is_required : Cell :: new ( true ) ,
218
+ } ;
219
+
220
+ let context = QueryContext :: new_empty ( ) ;
221
+
222
+ let selection = Selection ( vec ! [ ] ) ;
223
+
224
+ assert_eq ! ( iface. object_selection( & selection, & context) , Selection ( vec![ ] ) ) ;
225
+ }
226
+ }
0 commit comments