Skip to content

Commit 6857be1

Browse files
committed
Adds support for resolving a union type when using a generated schema
1 parent b42a8ea commit 6857be1

File tree

2 files changed

+139
-4
lines changed

2 files changed

+139
-4
lines changed

src/utilities/__tests__/buildASTSchema-test.js

+131
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,137 @@ describe('Schema Builder', () => {
394394
expect(output).to.equal(body);
395395
});
396396

397+
it('Specifying Union type using __typename', async () => {
398+
const schema = buildSchema(`
399+
schema {
400+
query: Root
401+
}
402+
403+
type Root {
404+
fruits: [Fruit]
405+
}
406+
407+
union Fruit = Apple | Banana
408+
409+
type Apple {
410+
color: String
411+
}
412+
413+
type Banana {
414+
length: Int
415+
}
416+
`);
417+
418+
const query = `
419+
{
420+
fruits {
421+
... on Apple {
422+
color
423+
}
424+
... on Banana {
425+
length
426+
}
427+
}
428+
}
429+
`;
430+
431+
const root = {
432+
fruits: [
433+
{
434+
color: 'green',
435+
__typename: 'Apple',
436+
},
437+
{
438+
length: 5,
439+
__typename: 'Banana',
440+
}
441+
]
442+
};
443+
444+
expect(await graphql(schema, query, root)).to.deep.equal({
445+
data: {
446+
fruits: [
447+
{
448+
color: 'green',
449+
},
450+
{
451+
length: 5,
452+
}
453+
]
454+
}
455+
});
456+
});
457+
458+
it('Specifying Interface type using __typename', async () => {
459+
const schema = buildSchema(`
460+
schema {
461+
query: Root
462+
}
463+
464+
type Root {
465+
characters: [Character]
466+
}
467+
468+
interface Character {
469+
name: String!
470+
}
471+
472+
type Human implements Character {
473+
name: String!
474+
totalCredits: Int
475+
}
476+
477+
type Droid implements Character {
478+
name: String!
479+
primaryFunction: String
480+
}
481+
`);
482+
483+
const query = `
484+
{
485+
characters {
486+
name
487+
... on Human {
488+
totalCredits
489+
}
490+
... on Droid {
491+
primaryFunction
492+
}
493+
}
494+
}
495+
`;
496+
497+
const root = {
498+
characters: [
499+
{
500+
name: 'Han Solo',
501+
totalCredits: 10,
502+
__typename: 'Human',
503+
},
504+
{
505+
name: 'R2-D2',
506+
primaryFunction: 'Astromech',
507+
__typename: 'Droid',
508+
}
509+
]
510+
};
511+
512+
expect(await graphql(schema, query, root)).to.deep.equal({
513+
data: {
514+
characters: [
515+
{
516+
name: 'Han Solo',
517+
totalCredits: 10,
518+
},
519+
{
520+
name: 'R2-D2',
521+
primaryFunction: 'Astromech',
522+
}
523+
]
524+
}
525+
});
526+
});
527+
397528
it('Custom Scalar', () => {
398529
const body = dedent`
399530
schema {

src/utilities/buildASTSchema.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema {
409409
description: getDescription(def),
410410
fields: () => makeFieldDefMap(def),
411411
astNode: def,
412-
resolveType: cannotExecuteSchema,
412+
resolveType,
413413
});
414414
}
415415

@@ -437,7 +437,7 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema {
437437
name: def.name.value,
438438
description: getDescription(def),
439439
types: def.types.map(t => produceObjectType(t)),
440-
resolveType: cannotExecuteSchema,
440+
resolveType,
441441
astNode: def,
442442
});
443443
}
@@ -530,8 +530,12 @@ function leadingSpaces(str) {
530530
return i;
531531
}
532532

533-
function cannotExecuteSchema() {
533+
function resolveType(result) {
534+
if (result && result.__typename) {
535+
return result.__typename;
536+
}
534537
throw new Error(
535-
'Generated Schema cannot use Interface or Union types for execution.'
538+
'To resolve a Union or Interface type with a generated schema the result ' +
539+
'must have a __typename property corresponding to the exact type used.'
536540
);
537541
}

0 commit comments

Comments
 (0)