@@ -166,21 +166,29 @@ mod threads_context_correctly {
166
166
use value:: Value ;
167
167
use types:: scalars:: EmptyMutation ;
168
168
use schema:: model:: RootNode ;
169
+ use executor:: Context ;
169
170
170
171
struct Schema ;
171
172
172
- graphql_object ! ( Schema : String |& self | {
173
- field a( & executor) -> String { executor. context( ) . clone( ) }
173
+ struct TestContext {
174
+ value : String ,
175
+ }
176
+
177
+ impl Context for TestContext { }
178
+
179
+ graphql_object ! ( Schema : TestContext |& self | {
180
+ field a( & executor) -> String { executor. context( ) . value. clone( ) }
174
181
} ) ;
175
182
176
183
#[ test]
177
184
fn test ( ) {
178
- let schema = RootNode :: new ( Schema , EmptyMutation :: < String > :: new ( ) ) ;
185
+ let schema = RootNode :: new ( Schema , EmptyMutation :: < TestContext > :: new ( ) ) ;
179
186
let doc = r"{ a }" ;
180
187
181
188
let vars = vec ! [ ] . into_iter ( ) . collect ( ) ;
182
189
183
- let ( result, errs) = :: execute ( doc, None , & schema, & vars, & "Context value" . to_owned ( ) )
190
+ let ( result, errs) = :: execute ( doc, None , & schema, & vars,
191
+ & TestContext { value : "Context value" . to_owned ( ) } )
184
192
. expect ( "Execution failed" ) ;
185
193
186
194
assert_eq ! ( errs, [ ] ) ;
@@ -195,6 +203,209 @@ mod threads_context_correctly {
195
203
}
196
204
}
197
205
206
+ mod dynamic_context_switching {
207
+ use std:: collections:: HashMap ;
208
+
209
+ use value:: Value ;
210
+ use types:: scalars:: EmptyMutation ;
211
+ use schema:: model:: RootNode ;
212
+ use parser:: SourcePosition ;
213
+ use executor:: { FieldResult , Context , ExecutionError } ;
214
+
215
+ struct Schema ;
216
+
217
+ struct InnerContext {
218
+ value : String ,
219
+ }
220
+
221
+ struct OuterContext {
222
+ items : HashMap < i64 , InnerContext > ,
223
+ }
224
+
225
+ impl Context for OuterContext { }
226
+ impl Context for InnerContext { }
227
+
228
+ struct ItemRef ;
229
+
230
+ graphql_object ! ( Schema : OuterContext |& self | {
231
+ field item_opt( & executor, key: i64 ) -> Option <( & InnerContext , ItemRef ) > {
232
+ executor. context( ) . items. get( & key) . map( |c| ( c, ItemRef ) )
233
+ }
234
+
235
+ field item_res( & executor, key: i64 ) -> FieldResult <( & InnerContext , ItemRef ) > {
236
+ executor. context( ) . items. get( & key)
237
+ . ok_or( format!( "Could not find key {}" , key) )
238
+ . map( |c| ( c, ItemRef ) )
239
+ }
240
+
241
+ field item_res_opt( & executor, key: i64 ) -> FieldResult <Option <( & InnerContext , ItemRef ) >> {
242
+ if key > 100 {
243
+ Err ( format!( "Key too large: {}" , key) )
244
+ } else {
245
+ Ok ( executor. context( ) . items. get( & key)
246
+ . map( |c| ( c, ItemRef ) ) )
247
+ }
248
+ }
249
+
250
+ field item_always( & executor, key: i64 ) -> ( & InnerContext , ItemRef ) {
251
+ executor. context( ) . items. get( & key)
252
+ . map( |c| ( c, ItemRef ) )
253
+ . unwrap( )
254
+ }
255
+ } ) ;
256
+
257
+ graphql_object ! ( ItemRef : InnerContext |& self | {
258
+ field value( & executor) -> String { executor. context( ) . value. clone( ) }
259
+ } ) ;
260
+
261
+ #[ test]
262
+ fn test_opt ( ) {
263
+ let schema = RootNode :: new ( Schema , EmptyMutation :: < OuterContext > :: new ( ) ) ;
264
+ let doc = r"{ first: itemOpt(key: 0) { value }, missing: itemOpt(key: 2) { value } }" ;
265
+
266
+ let vars = vec ! [ ] . into_iter ( ) . collect ( ) ;
267
+
268
+ let ctx = OuterContext {
269
+ items : vec ! [
270
+ ( 0 , InnerContext { value: "First value" . to_owned( ) } ) ,
271
+ ( 1 , InnerContext { value: "Second value" . to_owned( ) } ) ,
272
+ ] . into_iter ( ) . collect ( ) ,
273
+ } ;
274
+
275
+ let ( result, errs) = :: execute ( doc, None , & schema, & vars, & ctx)
276
+ . expect ( "Execution failed" ) ;
277
+
278
+ assert_eq ! ( errs, [ ] ) ;
279
+
280
+ println ! ( "Result: {:?}" , result) ;
281
+
282
+ assert_eq ! (
283
+ result,
284
+ Value :: object( vec![
285
+ ( "first" , Value :: object( vec![
286
+ ( "value" , Value :: string( "First value" ) ) ,
287
+ ] . into_iter( ) . collect( ) ) ) ,
288
+ ( "missing" , Value :: null( ) ) ,
289
+ ] . into_iter( ) . collect( ) ) ) ;
290
+ }
291
+
292
+ #[ test]
293
+ fn test_res ( ) {
294
+ let schema = RootNode :: new ( Schema , EmptyMutation :: < OuterContext > :: new ( ) ) ;
295
+ let doc = r"
296
+ {
297
+ first: itemRes(key: 0) { value }
298
+ missing: itemRes(key: 2) { value }
299
+ }
300
+ " ;
301
+
302
+ let vars = vec ! [ ] . into_iter ( ) . collect ( ) ;
303
+
304
+ let ctx = OuterContext {
305
+ items : vec ! [
306
+ ( 0 , InnerContext { value: "First value" . to_owned( ) } ) ,
307
+ ( 1 , InnerContext { value: "Second value" . to_owned( ) } ) ,
308
+ ] . into_iter ( ) . collect ( ) ,
309
+ } ;
310
+
311
+ let ( result, errs) = :: execute ( doc, None , & schema, & vars, & ctx)
312
+ . expect ( "Execution failed" ) ;
313
+
314
+ assert_eq ! ( errs, vec![
315
+ ExecutionError :: new(
316
+ SourcePosition :: new( 70 , 3 , 12 ) ,
317
+ & [ "missing" ] ,
318
+ "Could not find key 2" ,
319
+ ) ,
320
+ ] ) ;
321
+
322
+ println ! ( "Result: {:?}" , result) ;
323
+
324
+ assert_eq ! (
325
+ result,
326
+ Value :: object( vec![
327
+ ( "first" , Value :: object( vec![
328
+ ( "value" , Value :: string( "First value" ) ) ,
329
+ ] . into_iter( ) . collect( ) ) ) ,
330
+ ( "missing" , Value :: null( ) ) ,
331
+ ] . into_iter( ) . collect( ) ) ) ;
332
+ }
333
+
334
+ #[ test]
335
+ fn test_res_opt ( ) {
336
+ let schema = RootNode :: new ( Schema , EmptyMutation :: < OuterContext > :: new ( ) ) ;
337
+ let doc = r"
338
+ {
339
+ first: itemResOpt(key: 0) { value }
340
+ missing: itemResOpt(key: 2) { value }
341
+ tooLarge: itemResOpt(key: 200) { value }
342
+ }
343
+ " ;
344
+
345
+ let vars = vec ! [ ] . into_iter ( ) . collect ( ) ;
346
+
347
+ let ctx = OuterContext {
348
+ items : vec ! [
349
+ ( 0 , InnerContext { value: "First value" . to_owned( ) } ) ,
350
+ ( 1 , InnerContext { value: "Second value" . to_owned( ) } ) ,
351
+ ] . into_iter ( ) . collect ( ) ,
352
+ } ;
353
+
354
+ let ( result, errs) = :: execute ( doc, None , & schema, & vars, & ctx)
355
+ . expect ( "Execution failed" ) ;
356
+
357
+ assert_eq ! ( errs, [
358
+ ExecutionError :: new(
359
+ SourcePosition :: new( 123 , 4 , 12 ) ,
360
+ & [ "tooLarge" ] ,
361
+ "Key too large: 200" ,
362
+ ) ,
363
+ ] ) ;
364
+
365
+ println ! ( "Result: {:?}" , result) ;
366
+
367
+ assert_eq ! (
368
+ result,
369
+ Value :: object( vec![
370
+ ( "first" , Value :: object( vec![
371
+ ( "value" , Value :: string( "First value" ) ) ,
372
+ ] . into_iter( ) . collect( ) ) ) ,
373
+ ( "missing" , Value :: null( ) ) ,
374
+ ( "tooLarge" , Value :: null( ) ) ,
375
+ ] . into_iter( ) . collect( ) ) ) ;
376
+ }
377
+
378
+ #[ test]
379
+ fn test_always ( ) {
380
+ let schema = RootNode :: new ( Schema , EmptyMutation :: < OuterContext > :: new ( ) ) ;
381
+ let doc = r"{ first: itemAlways(key: 0) { value } }" ;
382
+
383
+ let vars = vec ! [ ] . into_iter ( ) . collect ( ) ;
384
+
385
+ let ctx = OuterContext {
386
+ items : vec ! [
387
+ ( 0 , InnerContext { value: "First value" . to_owned( ) } ) ,
388
+ ( 1 , InnerContext { value: "Second value" . to_owned( ) } ) ,
389
+ ] . into_iter ( ) . collect ( ) ,
390
+ } ;
391
+
392
+ let ( result, errs) = :: execute ( doc, None , & schema, & vars, & ctx)
393
+ . expect ( "Execution failed" ) ;
394
+
395
+ assert_eq ! ( errs, [ ] ) ;
396
+
397
+ println ! ( "Result: {:?}" , result) ;
398
+
399
+ assert_eq ! (
400
+ result,
401
+ Value :: object( vec![
402
+ ( "first" , Value :: object( vec![
403
+ ( "value" , Value :: string( "First value" ) ) ,
404
+ ] . into_iter( ) . collect( ) ) ) ,
405
+ ] . into_iter( ) . collect( ) ) ) ;
406
+ }
407
+ }
408
+
198
409
mod nulls_out_errors {
199
410
use value:: Value ;
200
411
use schema:: model:: RootNode ;
0 commit comments