@@ -12,7 +12,7 @@ import {
12
12
import { GraphQLBoolean , GraphQLString } from '../../type/scalars' ;
13
13
import { GraphQLSchema } from '../../type/schema' ;
14
14
15
- import { executeSync } from '../execute' ;
15
+ import { execute , executeSync } from '../execute' ;
16
16
17
17
class Dog {
18
18
name : string ;
@@ -154,6 +154,80 @@ odie.mother.progeny = [odie];
154
154
const liz = new Person ( 'Liz' ) ;
155
155
const john = new Person ( 'John' , [ garfield , odie ] , [ liz , odie ] ) ;
156
156
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
+
157
231
describe ( 'Execute: Union and intersection types' , ( ) => {
158
232
it ( 'can introspect on union and intersection types' , ( ) => {
159
233
const document = parse ( `
@@ -545,4 +619,50 @@ describe('Execute: Union and intersection types', () => {
545
619
expect ( encounteredRootValue ) . to . equal ( rootValue ) ;
546
620
expect ( encounteredContext ) . to . equal ( contextValue ) ;
547
621
} ) ;
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
+ } ) ;
548
668
} ) ;
0 commit comments