Skip to content

Commit

Permalink
getTypeMap() does not include input types used in directives (#1189)
Browse files Browse the repository at this point in the history
* Add failing test for directive's input types in getTypeMap()

* Include directive argument types in getTypeMap()

* Fix lint. Convert to reducer to solve flow issue.
  • Loading branch information
Yogu authored and leebyron committed Jan 8, 2018
1 parent f082e24 commit 87c1bc3
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 5 deletions.
42 changes: 42 additions & 0 deletions src/type/__tests__/schema-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ import {
GraphQLInterfaceType,
GraphQLObjectType,
GraphQLString,
GraphQLInputObjectType,
GraphQLDirective,
} from '../';

import { describe, it } from 'mocha';
import { expect } from 'chai';
import { GraphQLList } from '../wrappers';

const InterfaceType = new GraphQLInterfaceType({
name: 'Interface',
Expand All @@ -26,6 +29,37 @@ const ImplementingType = new GraphQLObjectType({
fields: { fieldName: { type: GraphQLString, resolve: () => '' } },
});

const DirectiveInputType = new GraphQLInputObjectType({
name: 'DirInput',
fields: {
field: {
type: GraphQLString,
},
},
});

const WrappedDirectiveInputType = new GraphQLInputObjectType({
name: 'WrappedDirInput',
fields: {
field: {
type: GraphQLString,
},
},
});

const Directive = new GraphQLDirective({
name: 'dir',
locations: ['OBJECT'],
args: {
arg: {
type: DirectiveInputType,
},
argList: {
type: new GraphQLList(WrappedDirectiveInputType),
},
},
});

const Schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
Expand All @@ -38,6 +72,7 @@ const Schema = new GraphQLSchema({
},
},
}),
directives: [Directive],
});

describe('Type System: Schema', () => {
Expand All @@ -53,4 +88,11 @@ describe('Type System: Schema', () => {
);
});
});

describe('Type Map', () => {
it('includes input types only used in directives', () => {
expect(Schema.getTypeMap()).to.include.key('DirInput');
expect(Schema.getTypeMap()).to.include.key('WrappedDirInput');
});
});
});
35 changes: 30 additions & 5 deletions src/type/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import type {
GraphQLInterfaceType,
} from './definition';
import type { SchemaDefinitionNode } from '../language/ast';
import { GraphQLDirective, specifiedDirectives } from './directives';
import {
GraphQLDirective,
isDirective,
specifiedDirectives,
} from './directives';
import type { GraphQLError } from '../error/GraphQLError';
import { __Schema } from './introspection';
import find from '../jsutils/find';
Expand Down Expand Up @@ -121,10 +125,17 @@ export class GraphQLSchema {
initialTypes = initialTypes.concat(types);
}

this._typeMap = initialTypes.reduce(
typeMapReducer,
(Object.create(null): TypeMap),
);
// Keep track of all types referenced within the schema.
let typeMap: TypeMap = Object.create(null);

// First by deeply visiting all initial types.
typeMap = initialTypes.reduce(typeMapReducer, typeMap);

// Then by deeply visiting all directive types.
typeMap = this._directives.reduce(typeMapDirectiveReducer, typeMap);

// Storing the resulting map for reference by the schema.
this._typeMap = typeMap;

// Keep track of all implementations by interface name.
this._implementations = Object.create(null);
Expand Down Expand Up @@ -269,3 +280,17 @@ function typeMapReducer(map: TypeMap, type: ?GraphQLType): TypeMap {

return reducedMap;
}

function typeMapDirectiveReducer(
map: TypeMap,
directive: ?GraphQLDirective,
): TypeMap {
// Directives are not validated until validateSchema() is called.
if (!isDirective(directive)) {
return map;
}
return directive.args.reduce(
(_map, arg) => typeMapReducer(_map, arg.type),
map,
);
}

0 comments on commit 87c1bc3

Please sign in to comment.