Skip to content

Commit 612fd45

Browse files
committed
fix: improve handling of promises in defaultTypeResolver
1 parent 8a9658f commit 612fd45

File tree

2 files changed

+100
-3
lines changed

2 files changed

+100
-3
lines changed

src/execution/__tests__/union-interface-test.ts

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { expect } from 'chai';
22
import { describe, it } from 'mocha';
33

4+
import { expectJSON } from '../../__testUtils__/expectJSON';
5+
46
import { parse } from '../../language/parser';
57

68
import {
@@ -12,7 +14,7 @@ import {
1214
import { GraphQLBoolean, GraphQLString } from '../../type/scalars';
1315
import { GraphQLSchema } from '../../type/schema';
1416

15-
import { executeSync } from '../execute';
17+
import { execute, executeSync } from '../execute';
1618

1719
class Dog {
1820
name: string;
@@ -42,19 +44,30 @@ class Cat {
4244
}
4345
}
4446

47+
class Plant {
48+
name: string;
49+
50+
constructor(name: string) {
51+
this.name = name;
52+
}
53+
}
54+
4555
class Person {
4656
name: string;
4757
pets?: ReadonlyArray<Dog | Cat>;
4858
friends?: ReadonlyArray<Dog | Cat | Person>;
59+
responsibilities?: ReadonlyArray<Dog | Cat | Plant>;
4960

5061
constructor(
5162
name: string,
5263
pets?: ReadonlyArray<Dog | Cat>,
5364
friends?: ReadonlyArray<Dog | Cat | Person>,
65+
responsibilities?: ReadonlyArray<Dog | Cat | Plant>,
5466
) {
5567
this.name = name;
5668
this.pets = pets;
5769
this.friends = friends;
70+
this.responsibilities = responsibilities;
5871
}
5972
}
6073

@@ -108,6 +121,18 @@ const CatType: GraphQLObjectType = new GraphQLObjectType({
108121
isTypeOf: (value) => value instanceof Cat,
109122
});
110123

124+
const PlantType: GraphQLObjectType = new GraphQLObjectType({
125+
name: 'Plant',
126+
interfaces: [NamedType],
127+
fields: () => ({
128+
name: { type: GraphQLString },
129+
}),
130+
// eslint-disable-next-line @typescript-eslint/require-await
131+
isTypeOf: async () => {
132+
throw new Error('Not sure if this is a plant');
133+
},
134+
});
135+
111136
const PetType = new GraphQLUnionType({
112137
name: 'Pet',
113138
types: [DogType, CatType],
@@ -124,12 +149,18 @@ const PetType = new GraphQLUnionType({
124149
},
125150
});
126151

152+
const PetOrPlantType = new GraphQLUnionType({
153+
name: 'PetOrPlantType',
154+
types: [PlantType, DogType, CatType],
155+
});
156+
127157
const PersonType: GraphQLObjectType = new GraphQLObjectType({
128158
name: 'Person',
129159
interfaces: [NamedType, MammalType, LifeType],
130160
fields: () => ({
131161
name: { type: GraphQLString },
132162
pets: { type: new GraphQLList(PetType) },
163+
responsibilities: { type: new GraphQLList(PetOrPlantType) },
133164
friends: { type: new GraphQLList(NamedType) },
134165
progeny: { type: new GraphQLList(PersonType) },
135166
mother: { type: PersonType },
@@ -151,8 +182,15 @@ const odie = new Dog('Odie', true);
151182
odie.mother = new Dog("Odie's Mom", true);
152183
odie.mother.progeny = [odie];
153184

185+
const fern = new Plant('Fern');
186+
154187
const liz = new Person('Liz');
155-
const john = new Person('John', [garfield, odie], [liz, odie]);
188+
const john = new Person(
189+
'John',
190+
[garfield, odie],
191+
[liz, odie],
192+
[garfield, fern],
193+
);
156194

157195
describe('Execute: Union and intersection types', () => {
158196
it('can introspect on union and intersection types', () => {
@@ -195,7 +233,12 @@ describe('Execute: Union and intersection types', () => {
195233
name: 'Named',
196234
fields: [{ name: 'name' }],
197235
interfaces: [],
198-
possibleTypes: [{ name: 'Dog' }, { name: 'Cat' }, { name: 'Person' }],
236+
possibleTypes: [
237+
{ name: 'Dog' },
238+
{ name: 'Cat' },
239+
{ name: 'Person' },
240+
{ name: 'Plant' },
241+
],
199242
enumValues: null,
200243
inputFields: null,
201244
},
@@ -545,4 +588,54 @@ describe('Execute: Union and intersection types', () => {
545588
expect(encounteredRootValue).to.equal(rootValue);
546589
expect(encounteredContext).to.equal(contextValue);
547590
});
591+
592+
it('it rejects if isTypeOf check rejects in defaultResolveType', async () => {
593+
const document = parse(`
594+
{
595+
responsibilities {
596+
__typename
597+
... on Dog {
598+
name
599+
barks
600+
}
601+
... on Cat {
602+
name
603+
meows
604+
}
605+
}
606+
}
607+
`);
608+
609+
const rootValue = new Person('John', [], [liz], [garfield]);
610+
const contextValue = { authToken: '123abc' };
611+
612+
process.on('unhandledRejection', () => {
613+
expect.fail('Unhandled rejection');
614+
});
615+
616+
const result = await execute({
617+
schema,
618+
document,
619+
rootValue,
620+
contextValue,
621+
});
622+
623+
expectJSON(result).toDeepEqual({
624+
data: {
625+
responsibilities: [null],
626+
},
627+
errors: [
628+
{
629+
message: 'Not sure if this is a plant',
630+
locations: [
631+
{
632+
column: 9,
633+
line: 3,
634+
},
635+
],
636+
path: ['responsibilities', 0],
637+
},
638+
],
639+
});
640+
});
548641
});

src/execution/execute.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,10 @@ export const defaultTypeResolver: GraphQLTypeResolver<unknown, unknown> =
986986
if (isPromise(isTypeOfResult)) {
987987
promisedIsTypeOfResults[i] = isTypeOfResult;
988988
} else if (isTypeOfResult) {
989+
if (promisedIsTypeOfResults.length > 0) {
990+
return Promise.all(promisedIsTypeOfResults).then(() => type.name);
991+
}
992+
989993
return type.name;
990994
}
991995
}

0 commit comments

Comments
 (0)