@@ -12,7 +12,7 @@ import {
1212import  {  GraphQLBoolean ,  GraphQLString  }  from  '../../type/scalars' ; 
1313import  {  GraphQLSchema  }  from  '../../type/schema' ; 
1414
15- import  {  executeSync  }  from  '../execute' ; 
15+ import  {  execute ,   executeSync  }  from  '../execute' ; 
1616
1717class  Dog  { 
1818  name : string ; 
@@ -154,6 +154,80 @@ odie.mother.progeny = [odie];
154154const  liz  =  new  Person ( 'Liz' ) ; 
155155const  john  =  new  Person ( 'John' ,  [ garfield ,  odie ] ,  [ liz ,  odie ] ) ; 
156156
157+ // New types for the unhandled rejection test 
158+ const  SearchableInterface  =  new  GraphQLInterfaceType ( { 
159+   name : 'Searchable' , 
160+   fields : { 
161+     id : {  type : GraphQLString  } , 
162+   } , 
163+   // Deliberately no resolveType, to use isTypeOf from concrete types 
164+ } ) ; 
165+ 
166+ const  TypeA  =  new  GraphQLObjectType ( { 
167+   name : 'TypeA' , 
168+   interfaces : [ SearchableInterface ] , 
169+   fields : ( )  =>  ( { 
170+     id : {  type : GraphQLString  } , 
171+     nameA : {  type : GraphQLString  } , 
172+   } ) , 
173+   isTypeOf : ( _value ,  _context ,  _info )  =>  { 
174+     return  new  Promise ( ( _resolve ,  reject )  =>  { 
175+       setTimeout ( ( )  =>  { 
176+         reject ( new  Error ( 'TypeA_isTypeOf_rejected' ) ) ; 
177+       } ,  10 ) ; 
178+     } ) ; 
179+   } , 
180+ } ) ; 
181+ 
182+ const  TypeB  =  new  GraphQLObjectType ( { 
183+   name : 'TypeB' , 
184+   interfaces : [ SearchableInterface ] , 
185+   fields : ( )  =>  ( { 
186+     id : {  type : GraphQLString  } , 
187+     nameB : {  type : GraphQLString  } , 
188+   } ) , 
189+   isTypeOf : ( value : any ,  _context ,  _info )  =>  { 
190+     return  value . id  ===  'b' ; 
191+   } , 
192+ } ) ; 
193+ 
194+ const  queryTypeWithSearchable  =  new  GraphQLObjectType ( { 
195+   name : 'Query' , 
196+   fields : { 
197+     person : { 
198+       type : PersonType , 
199+       resolve : ( )  =>  john , 
200+     } , 
201+     search : { 
202+       type : SearchableInterface , 
203+       args : {  id : {  type : GraphQLString  }  } , 
204+       resolve : ( _source ,  {  id } )  =>  { 
205+         /* c8 ignore start */ 
206+         if  ( id  ===  'a' )  { 
207+           return  {  id : 'a' ,  nameA : 'Object A'  } ; 
208+           /* c8 ignore end */ 
209+         }  else  if  ( id  ===  'b' )  { 
210+           return  {  id : 'b' ,  nameB : 'Object B'  } ; 
211+         } 
212+       } , 
213+     } , 
214+   } , 
215+ } ) ; 
216+ 
217+ const  schemaWithSearchable  =  new  GraphQLSchema ( { 
218+   query : queryTypeWithSearchable , 
219+   types : [ 
220+     PetType , 
221+     TypeA , 
222+     TypeB , 
223+     SearchableInterface , 
224+     PersonType , 
225+     DogType , 
226+     CatType , 
227+   ] ,  // Added new types 
228+ } ) ; 
229+ // End of new types 
230+ 
157231describe ( 'Execute: Union and intersection types' ,  ( )  =>  { 
158232  it ( 'can introspect on union and intersection types' ,  ( )  =>  { 
159233    const  document  =  parse ( ` 
@@ -545,4 +619,50 @@ describe('Execute: Union and intersection types', () => {
545619    expect ( encounteredRootValue ) . to . equal ( rootValue ) ; 
546620    expect ( encounteredContext ) . to . equal ( contextValue ) ; 
547621  } ) ; 
622+ 
623+   it ( 'handles promises from isTypeOf correctly when a later type matches synchronously' ,  async  ( )  =>  { 
624+     const  document  =  parse ( ` 
625+       query TestSearch { 
626+         search(id: "b") { 
627+           __typename 
628+           id 
629+           ... on TypeA { 
630+             nameA 
631+           } 
632+           ... on TypeB { 
633+             nameB 
634+           } 
635+         } 
636+       } 
637+     ` ) ; 
638+ 
639+     let  unhandledRejection : any  =  null ; 
640+     /* c8 ignore start */ 
641+     const  unhandledRejectionListener  =  ( reason : any )  =>  { 
642+       unhandledRejection  =  reason ; 
643+     } ; 
644+     process . on ( 'unhandledRejection' ,  unhandledRejectionListener ) ; 
645+     /* c8 ignore end */ 
646+ 
647+     const  result  =  await  execute ( { 
648+       schema : schemaWithSearchable , 
649+       document, 
650+     } ) ; 
651+ 
652+     expect ( result . errors ) . to . be . undefined ; 
653+     expect ( result . data ) . to . deep . equal ( { 
654+       search : { 
655+         __typename : 'TypeB' , 
656+         id : 'b' , 
657+         nameB : 'Object B' , 
658+       } , 
659+     } ) ; 
660+ 
661+     // Give the TypeA promise a chance to reject and the listener to fire 
662+     await  new  Promise ( ( resolve )  =>  setTimeout ( resolve ,  20 ) ) ; 
663+ 
664+     process . removeListener ( 'unhandledRejection' ,  unhandledRejectionListener ) ; 
665+ 
666+     expect ( unhandledRejection ) . to . be . null ; 
667+   } ) ; 
548668} ) ; 
0 commit comments