@@ -3,6 +3,7 @@ import { describe, it } from 'mocha';
3
3
4
4
import inspect from '../../jsutils/inspect' ;
5
5
import invariant from '../../jsutils/invariant' ;
6
+ import resolveOnNextTick from '../../__testUtils__/resolveOnNextTick' ;
6
7
7
8
import { Kind } from '../../language/kinds' ;
8
9
import { parse } from '../../language/parser' ;
@@ -646,6 +647,56 @@ describe('Execute: Handles basic execution tasks', () => {
646
647
} ) ;
647
648
} ) ;
648
649
650
+ it ( 'handles sync errors combined with rejections' , async ( ) => {
651
+ let isAsyncResolverFinished = false ;
652
+
653
+ const schema = new GraphQLSchema ( {
654
+ query : new GraphQLObjectType ( {
655
+ name : 'Query' ,
656
+ fields : {
657
+ syncNullError : {
658
+ type : new GraphQLNonNull ( GraphQLString ) ,
659
+ resolve : ( ) => null ,
660
+ } ,
661
+ asyncNullError : {
662
+ type : new GraphQLNonNull ( GraphQLString ) ,
663
+ async resolve ( ) {
664
+ await resolveOnNextTick ( ) ;
665
+ await resolveOnNextTick ( ) ;
666
+ await resolveOnNextTick ( ) ;
667
+ isAsyncResolverFinished = true ;
668
+ return null ;
669
+ } ,
670
+ } ,
671
+ } ,
672
+ } ) ,
673
+ } ) ;
674
+
675
+ // Order is important here, as the promise has to be created before the synchronous error is thrown
676
+ const document = parse ( `
677
+ {
678
+ asyncNullError
679
+ syncNullError
680
+ }
681
+ ` ) ;
682
+
683
+ const result = execute ( { schema, document } ) ;
684
+
685
+ expect ( isAsyncResolverFinished ) . to . equal ( false ) ;
686
+ expect ( await result ) . to . deep . equal ( {
687
+ data : null ,
688
+ errors : [
689
+ {
690
+ message :
691
+ 'Cannot return null for non-nullable field Query.syncNullError.' ,
692
+ locations : [ { line : 4 , column : 9 } ] ,
693
+ path : [ 'syncNullError' ] ,
694
+ } ,
695
+ ] ,
696
+ } ) ;
697
+ expect ( isAsyncResolverFinished ) . to . equal ( true ) ;
698
+ } ) ;
699
+
649
700
it ( 'Full response path is included for non-nullable fields' , ( ) => {
650
701
const A = new GraphQLObjectType ( {
651
702
name : 'A' ,
0 commit comments