@@ -2,6 +2,7 @@ import { assert, expect } from 'chai';
22import { describe , it } from 'mocha' ;
33
44import { expectJSON } from '../../__testUtils__/expectJSON' ;
5+ import { resolveOnNextTick } from '../../__testUtils__/resolveOnNextTick' ;
56
67import { inspect } from '../../jsutils/inspect' ;
78
@@ -576,6 +577,55 @@ describe('Execute: Handles basic execution tasks', () => {
576577 } ) ;
577578 } ) ;
578579
580+ it ( 'handles sync errors combined with rejections' , async ( ) => {
581+ let isAsyncResolverCalled = false ;
582+
583+ const schema = new GraphQLSchema ( {
584+ query : new GraphQLObjectType ( {
585+ name : 'Query' ,
586+ fields : {
587+ syncNullError : {
588+ type : new GraphQLNonNull ( GraphQLString ) ,
589+ resolve : ( ) => null ,
590+ } ,
591+ asyncNullError : {
592+ type : new GraphQLNonNull ( GraphQLString ) ,
593+ async resolve ( ) {
594+ await resolveOnNextTick ( ) ;
595+ await resolveOnNextTick ( ) ;
596+ await resolveOnNextTick ( ) ;
597+ isAsyncResolverCalled = true ;
598+ return Promise . resolve ( null ) ;
599+ } ,
600+ } ,
601+ } ,
602+ } ) ,
603+ } ) ;
604+
605+ // Order is important here, as the promise has to be created before the synchronous error is thrown
606+ const document = parse ( `
607+ {
608+ asyncNullError
609+ syncNullError
610+ }
611+ ` ) ;
612+
613+ const result = await execute ( { schema, document } ) ;
614+
615+ expect ( isAsyncResolverCalled ) . to . equal ( true ) ;
616+ expectJSON ( result ) . toDeepEqual ( {
617+ data : null ,
618+ errors : [
619+ {
620+ message :
621+ 'Cannot return null for non-nullable field Query.syncNullError.' ,
622+ locations : [ { line : 4 , column : 9 } ] ,
623+ path : [ 'syncNullError' ] ,
624+ } ,
625+ ] ,
626+ } ) ;
627+ } ) ;
628+
579629 it ( 'Full response path is included for non-nullable fields' , ( ) => {
580630 const A : GraphQLObjectType = new GraphQLObjectType ( {
581631 name : 'A' ,
0 commit comments