@@ -394,28 +394,47 @@ let ``Execution when querying returns unique document id with response`` () =
394
394
| response -> fail $" Expected a 'Direct' GQLResponse but got\n {response}"
395
395
396
396
type InnerNullableTest = { Kaboom : string }
397
- type NullableTest = { Inner : InnerNullableTest }
397
+ type NullableTest = {
398
+ Inner : InnerNullableTest
399
+ InnerPartialSuccess : InnerNullableTest
400
+ }
398
401
399
402
[<Fact>]
400
403
let ``Execution handles errors : properly propagates errors`` () =
401
- let InnerObj =
404
+ let InnerObjType =
402
405
Define.Object< InnerNullableTest>(
403
406
" Inner" , [
404
407
Define.Field( " kaboom" , StringType, fun _ x -> x.Kaboom)
405
408
])
409
+ let InnerPartialSuccessObjType =
410
+ // executeResolvers/resolveWith, case 5
411
+ let resolvePartialSuccess ( ctx : ResolveFieldContext ) ( _ : InnerNullableTest ) =
412
+ ctx.AddError { new IGQLError with member _.Message = " Some non-critical error" }
413
+ " Yes, Rico, Kaboom"
414
+ Define.Object< InnerNullableTest>(
415
+ " InnerPartialSuccess" , [
416
+ Define.Field( " kaboom" , StringType, resolvePartialSuccess)
417
+ ])
406
418
let schema =
407
419
Schema( Define.Object< NullableTest>(
408
- " Type" , [
409
- Define.Field( " inner" , Nullable InnerObj, fun _ x -> Some x.Inner)
410
- ]))
420
+ " Type" , [
421
+ Define.Field( " inner" , Nullable InnerObjType, fun _ x -> Some x.Inner)
422
+ Define.Field( " partialSuccess" , Nullable InnerPartialSuccessObjType, fun _ x -> Some x.InnerPartialSuccess)
423
+ ]))
411
424
let expectedData =
412
425
NameValueLookup.ofList [
413
426
" inner" , null
427
+ " partialSuccess" , NameValueLookup.ofList [
428
+ " kaboom" , " Yes, Rico, Kaboom"
429
+ ]
414
430
]
415
431
let expectedErrors = [
416
432
GQLProblemDetails.CreateWithKind ( " Non-Null field kaboom resolved as a null!" , Execution, [ box " inner" ; " kaboom" ])
433
+ GQLProblemDetails.CreateWithKind ( " Some non-critical error" , Execution, [ box " partialSuccess" ; " kaboom" ])
417
434
]
418
- let result = sync <| Executor( schema) .AsyncExecute( " query Example { inner { kaboom } }" , { Inner = { Kaboom = null } })
435
+ let result =
436
+ let variables = { Inner = { Kaboom = null }; InnerPartialSuccess = { Kaboom = " Yes, Rico, Kaboom" } }
437
+ sync <| Executor( schema) .AsyncExecute( " query Example { inner { kaboom } partialSuccess { kaboom } }" , variables)
419
438
ensureDirect result <| fun data errors ->
420
439
result.DocumentId |> notEquals Unchecked.defaultof< int>
421
440
data |> equals ( upcast expectedData)
@@ -425,9 +444,9 @@ let ``Execution handles errors: properly propagates errors`` () =
425
444
let ``Execution handles errors : exceptions`` () =
426
445
let schema =
427
446
Schema( Define.Object< unit>(
428
- " Type" , [
429
- Define.Field( " a" , StringType, fun _ _ -> failwith " Resolver Error!" )
430
- ]))
447
+ " Type" , [
448
+ Define.Field( " a" , StringType, fun _ _ -> failwith " Resolver Error!" )
449
+ ]))
431
450
let expectedError = GQLProblemDetails.CreateWithKind ( " Resolver Error!" , Execution, [ box " a" ])
432
451
let result = sync <| Executor( schema) .AsyncExecute( " query Test { a }" , ())
433
452
ensureRequestError result <| fun [ error ] -> error |> equals expectedError
@@ -458,3 +477,129 @@ let ``Execution handles errors: nullable list fields`` () =
458
477
result.DocumentId |> notEquals Unchecked.defaultof< int>
459
478
data |> equals ( upcast expectedData)
460
479
errors |> equals expectedErrors
480
+
481
+
482
+ [<Fact>]
483
+ let ``Execution handles errors : additional error added when exception is rised in a nullable field resolver`` () =
484
+ let InnerNullableExceptionObjType =
485
+ // executeResolvers/resolveWith, case 1
486
+ let resolveWithException ( ctx : ResolveFieldContext ) ( _ : InnerNullableTest ) : string option =
487
+ ctx.AddError { new IGQLError with member _.Message = " Non-critical error" }
488
+ raise ( System.Exception " Unexpected error" )
489
+ Define.Object< InnerNullableTest>(
490
+ " InnerNullableException" , [
491
+ Define.Field( " kaboom" , Nullable StringType, resolve = resolveWithException)
492
+ ])
493
+ let schema =
494
+ Schema( Define.Object< NullableTest>(
495
+ " Type" , [
496
+ Define.Field( " inner" , Nullable InnerNullableExceptionObjType, fun _ x -> Some x.Inner)
497
+ ]))
498
+ let expectedData =
499
+ NameValueLookup.ofList [
500
+ " inner" , NameValueLookup.ofList [
501
+ " kaboom" , null
502
+ ]
503
+ ]
504
+ let expectedErrors =
505
+ [
506
+ GQLProblemDetails.CreateWithKind ( " Unexpected error" , Execution, [ box " inner" ; " kaboom" ])
507
+ GQLProblemDetails.CreateWithKind ( " Non-critical error" , Execution, [ box " inner" ; " kaboom" ])
508
+ ]
509
+ let result =
510
+ let variables = { Inner = { Kaboom = null }; InnerPartialSuccess = { Kaboom = " Yes, Rico, Kaboom" } }
511
+ sync <| Executor( schema) .AsyncExecute( " query Example { inner { kaboom } }" , variables)
512
+ ensureDirect result <| fun data errors ->
513
+ result.DocumentId |> notEquals Unchecked.defaultof< int>
514
+ data |> equals ( upcast expectedData)
515
+ errors |> equals expectedErrors
516
+
517
+ [<Fact>]
518
+ let ``Execution handles errors : additional error added when None returned from a nullable field resolver`` () =
519
+ let InnerNullableNoneObjType =
520
+ // executeResolvers/resolveWith, case 2
521
+ let resolveWithNone ( ctx : ResolveFieldContext ) ( _ : InnerNullableTest ) : string option =
522
+ ctx.AddError { new IGQLError with member _.Message = " Non-critical error" }
523
+ None
524
+ Define.Object< InnerNullableTest>(
525
+ " InnerNullableException" , [
526
+ Define.Field( " kaboom" , Nullable StringType, resolve = resolveWithNone)
527
+ ])
528
+ let schema =
529
+ Schema( Define.Object< NullableTest>(
530
+ " Type" , [
531
+ Define.Field( " inner" , Nullable InnerNullableNoneObjType, fun _ x -> Some x.Inner)
532
+ ]))
533
+ let expectedData =
534
+ NameValueLookup.ofList [
535
+ " inner" , NameValueLookup.ofList [
536
+ " kaboom" , null
537
+ ]
538
+ ]
539
+ let expectedErrors =
540
+ [
541
+ GQLProblemDetails.CreateWithKind ( " Non-critical error" , Execution, [ box " inner" ; " kaboom" ])
542
+ ]
543
+ let result =
544
+ let variables = { Inner = { Kaboom = null }; InnerPartialSuccess = { Kaboom = " Yes, Rico, Kaboom" } }
545
+ sync <| Executor( schema) .AsyncExecute( " query Example { inner { kaboom } }" , variables)
546
+ ensureDirect result <| fun data errors ->
547
+ result.DocumentId |> notEquals Unchecked.defaultof< int>
548
+ data |> equals ( upcast expectedData)
549
+ errors |> equals expectedErrors
550
+
551
+ [<Fact>]
552
+ let ``Execution handles errors : additional error added when exception is rised in a non - nullable field resolver`` () =
553
+ let InnerNonNullableExceptionObjType =
554
+ // executeResolvers/resolveWith, case 3
555
+ let resolveWithException ( ctx : ResolveFieldContext ) ( _ : InnerNullableTest ) : string =
556
+ ctx.AddError { new IGQLError with member _.Message = " Non-critical error" }
557
+ raise ( System.Exception " Fatal error" )
558
+ Define.Object< InnerNullableTest>(
559
+ " InnerNonNullableException" , [
560
+ Define.Field( " kaboom" , StringType, resolve = resolveWithException)
561
+ ])
562
+ let schema =
563
+ Schema( Define.Object< NullableTest>(
564
+ " Type" , [
565
+ Define.Field( " inner" , InnerNonNullableExceptionObjType, fun _ x -> x.Inner)
566
+ ]))
567
+ let expectedErrors =
568
+ [
569
+ GQLProblemDetails.CreateWithKind ( " Fatal error" , Execution, [ box " inner" ; " kaboom" ])
570
+ GQLProblemDetails.CreateWithKind ( " Non-critical error" , Execution, [ box " inner" ; " kaboom" ])
571
+ ]
572
+ let result =
573
+ let variables = { Inner = { Kaboom = " Yes, Rico, Kaboom" }; InnerPartialSuccess = { Kaboom = " Yes, Rico, Kaboom" } }
574
+ sync <| Executor( schema) .AsyncExecute( " query Example { inner { kaboom } }" , variables)
575
+ ensureRequestError result <| fun errors ->
576
+ result.DocumentId |> notEquals Unchecked.defaultof< int>
577
+ errors |> equals expectedErrors
578
+
579
+ [<Fact>]
580
+ let ``Execution handles errors : additional error added and when null returned from a non - nullable field resolver`` () =
581
+ let InnerNonNullableNullObjType =
582
+ // executeResolvers/resolveWith, case 4
583
+ let resolveWithNull ( ctx : ResolveFieldContext ) ( _ : InnerNullableTest ) : string =
584
+ ctx.AddError { new IGQLError with member _.Message = " Non-critical error" }
585
+ null
586
+ Define.Object< InnerNullableTest>(
587
+ " InnerNonNullableNull" , [
588
+ Define.Field( " kaboom" , StringType, resolveWithNull)
589
+ ])
590
+ let schema =
591
+ Schema( Define.Object< NullableTest>(
592
+ " Type" , [
593
+ Define.Field( " inner" , InnerNonNullableNullObjType, fun _ x -> x.Inner)
594
+ ]))
595
+ let expectedErrors =
596
+ [
597
+ GQLProblemDetails.CreateWithKind ( " Non-Null field kaboom resolved as a null!" , Execution, [ box " inner" ; " kaboom" ])
598
+ GQLProblemDetails.CreateWithKind ( " Non-critical error" , Execution, [ box " inner" ; " kaboom" ])
599
+ ]
600
+ let result =
601
+ let variables = { Inner = { Kaboom = " Yes, Rico, Kaboom" }; InnerPartialSuccess = { Kaboom = " Yes, Rico, Kaboom" } }
602
+ sync <| Executor( schema) .AsyncExecute( " query Example { inner { kaboom } }" , variables)
603
+ ensureRequestError result <| fun errors ->
604
+ result.DocumentId |> notEquals Unchecked.defaultof< int>
605
+ errors |> equals expectedErrors
0 commit comments