@@ -394,28 +394,47 @@ let ``Execution when querying returns unique document id with response`` () =
394394 | response -> fail $" Expected a 'Direct' GQLResponse but got\n {response}"
395395
396396type InnerNullableTest = { Kaboom : string }
397- type NullableTest = { Inner : InnerNullableTest }
397+ type NullableTest = {
398+ Inner : InnerNullableTest
399+ InnerPartialSuccess : InnerNullableTest
400+ }
398401
399402[<Fact>]
400403let ``Execution handles errors : properly propagates errors`` () =
401- let InnerObj =
404+ let InnerObjType =
402405 Define.Object< InnerNullableTest>(
403406 " Inner" , [
404407 Define.Field( " kaboom" , StringType, fun _ x -> x.Kaboom)
405408 ])
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+ ])
406418 let schema =
407419 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+ ]))
411424 let expectedData =
412425 NameValueLookup.ofList [
413426 " inner" , null
427+ " partialSuccess" , NameValueLookup.ofList [
428+ " kaboom" , " Yes, Rico, Kaboom"
429+ ]
414430 ]
415431 let expectedErrors = [
416432 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" ])
417434 ]
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)
419438 ensureDirect result <| fun data errors ->
420439 result.DocumentId |> notEquals Unchecked.defaultof< int>
421440 data |> equals ( upcast expectedData)
@@ -425,9 +444,9 @@ let ``Execution handles errors: properly propagates errors`` () =
425444let ``Execution handles errors : exceptions`` () =
426445 let schema =
427446 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+ ]))
431450 let expectedError = GQLProblemDetails.CreateWithKind ( " Resolver Error!" , Execution, [ box " a" ])
432451 let result = sync <| Executor( schema) .AsyncExecute( " query Test { a }" , ())
433452 ensureRequestError result <| fun [ error ] -> error |> equals expectedError
@@ -458,3 +477,129 @@ let ``Execution handles errors: nullable list fields`` () =
458477 result.DocumentId |> notEquals Unchecked.defaultof< int>
459478 data |> equals ( upcast expectedData)
460479 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