@@ -672,30 +672,37 @@ describe('Execute: Union and intersection types', () => {
672672 const rootValue = new Person ( 'John' , [ ] , [ liz ] , [ garfield ] ) ;
673673 const contextValue = { authToken : '123abc' } ;
674674
675- /* c8 ignore next 4 */
675+ let unhandledRejection : unknown = null ;
676+ const unhandledRejectionListener = ( reason : unknown ) => {
677+ unhandledRejection = reason ;
678+ } ;
676679 // eslint-disable-next-line no-undef
677- process . on ( 'unhandledRejection' , ( ) => {
678- expect . fail ( 'Unhandled rejection' ) ;
679- } ) ;
680-
681- const result = await execute ( {
682- schema,
683- document,
684- rootValue,
685- contextValue,
686- } ) ;
680+ process . on ( 'unhandledRejection' , unhandledRejectionListener ) ;
687681
688- expectJSON ( result ) . toDeepEqual ( {
689- data : {
690- responsibilities : [
691- {
692- __typename : 'Cat' ,
693- meows : false ,
694- name : 'Garfield' ,
695- } ,
696- ] ,
697- } ,
698- } ) ;
682+ try {
683+ const result = await execute ( {
684+ schema,
685+ document,
686+ rootValue,
687+ contextValue,
688+ } ) ;
689+
690+ expectJSON ( result ) . toDeepEqual ( {
691+ data : {
692+ responsibilities : [
693+ {
694+ __typename : 'Cat' ,
695+ meows : false ,
696+ name : 'Garfield' ,
697+ } ,
698+ ] ,
699+ } ,
700+ } ) ;
701+ } finally {
702+ // eslint-disable-next-line no-undef
703+ process . removeListener ( 'unhandledRejection' , unhandledRejectionListener ) ;
704+ }
705+ expect ( unhandledRejection ) . to . equal ( null ) ;
699706 } ) ;
700707
701708 it ( 'handles promises from isTypeOf correctly when a later type matches synchronously' , async ( ) => {
@@ -718,7 +725,7 @@ describe('Execute: Union and intersection types', () => {
718725 const unhandledRejectionListener = ( reason : any ) => {
719726 unhandledRejection = reason ;
720727 } ;
721- // eslint-disable-next-line
728+ // eslint-disable-next-line no-undef
722729 process . on ( 'unhandledRejection' , unhandledRejectionListener ) ;
723730
724731 const result = await execute ( {
@@ -739,7 +746,93 @@ describe('Execute: Union and intersection types', () => {
739746
740747 await new Promise ( ( resolve ) => setTimeout ( resolve , 20 ) ) ;
741748
742- // eslint-disable-next-line
749+ // eslint-disable-next-line no-undef
750+ process . removeListener ( 'unhandledRejection' , unhandledRejectionListener ) ;
751+
752+ expect ( unhandledRejection ) . to . equal ( null ) ;
753+ } ) ;
754+
755+ it ( 'handles pending isTypeOf rejections when a later isTypeOf throws synchronously' , async ( ) => {
756+ const ThrowingSearchableInterface = new GraphQLInterfaceType ( {
757+ name : 'ThrowingSearchable' ,
758+ fields : {
759+ id : { type : GraphQLString } ,
760+ } ,
761+ } ) ;
762+
763+ const TypeAsyncReject = new GraphQLObjectType ( {
764+ name : 'TypeAsyncReject' ,
765+ interfaces : [ ThrowingSearchableInterface ] ,
766+ fields : ( ) => ( {
767+ id : { type : GraphQLString } ,
768+ nameAsyncReject : { type : GraphQLString } ,
769+ } ) ,
770+ isTypeOf : ( _value , _context , _info ) =>
771+ new Promise ( ( _resolve , reject ) =>
772+ setTimeout (
773+ ( ) => reject ( new Error ( 'TypeAsyncReject_isTypeOf_rejected' ) ) ,
774+ 10 ,
775+ ) ,
776+ ) ,
777+ } ) ;
778+
779+ const TypeThrowing = new GraphQLObjectType ( {
780+ name : 'TypeThrowing' ,
781+ interfaces : [ ThrowingSearchableInterface ] ,
782+ fields : ( ) => ( {
783+ id : { type : GraphQLString } ,
784+ nameThrowing : { type : GraphQLString } ,
785+ } ) ,
786+ isTypeOf : ( ) => {
787+ throw new Error ( 'TypeThrowing_isTypeOf_threw' ) ;
788+ } ,
789+ } ) ;
790+
791+ const schemaWithThrowingIsTypeOf = new GraphQLSchema ( {
792+ query : new GraphQLObjectType ( {
793+ name : 'Query' ,
794+ fields : {
795+ search : {
796+ type : ThrowingSearchableInterface ,
797+ resolve : ( ) => ( { id : 'x' , nameThrowing : 'Object X' } ) ,
798+ } ,
799+ } ,
800+ } ) ,
801+ types : [ TypeAsyncReject , TypeThrowing ] ,
802+ } ) ;
803+
804+ const document = parse ( `
805+ {
806+ search {
807+ __typename
808+ id
809+ ... on TypeThrowing {
810+ nameThrowing
811+ }
812+ }
813+ }
814+ ` ) ;
815+
816+ let unhandledRejection : unknown = null ;
817+ const unhandledRejectionListener = ( reason : unknown ) => {
818+ unhandledRejection = reason ;
819+ } ;
820+ // eslint-disable-next-line no-undef
821+ process . on ( 'unhandledRejection' , unhandledRejectionListener ) ;
822+
823+ const result = await execute ( {
824+ schema : schemaWithThrowingIsTypeOf ,
825+ document,
826+ } ) ;
827+
828+ expect ( result . data ) . to . deep . equal ( {
829+ search : null ,
830+ } ) ;
831+ expect ( result . errors ?. [ 0 ] . message ) . to . equal ( 'TypeThrowing_isTypeOf_threw' ) ;
832+
833+ await new Promise ( ( resolve ) => setTimeout ( resolve , 20 ) ) ;
834+
835+ // eslint-disable-next-line no-undef
743836 process . removeListener ( 'unhandledRejection' , unhandledRejectionListener ) ;
744837
745838 expect ( unhandledRejection ) . to . equal ( null ) ;
0 commit comments