Skip to content
This repository has been archived by the owner on Apr 15, 2020. It is now read-only.

Commit

Permalink
fix(visitSchema): visitSchema must reinitialize private variables whe…
Browse files Browse the repository at this point in the history
…n updating interfaces.
  • Loading branch information
yaacovCR committed Sep 17, 2019
1 parent 2593c44 commit c3bbeaf
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 19 deletions.
23 changes: 7 additions & 16 deletions src/test/testDirectives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
GraphQLList,
GraphQLUnionType,
GraphQLInt,
GraphQLOutputType,
} from 'graphql';

import formatDate = require('dateformat');
Expand Down Expand Up @@ -202,24 +203,19 @@ describe('@directives', () => {
it('can be implemented with SchemaDirectiveVisitor', () => {
const visited: Set<GraphQLObjectType> = new Set;
const schema = makeExecutableSchema({ typeDefs });
let visitCount = 0;

SchemaDirectiveVisitor.visitSchemaDirectives(schema, {
// The directive subclass can be defined anonymously inline!
queryTypeDirective: class extends SchemaDirectiveVisitor {
public static description = 'A @directive for query object types';
public visitObject(object: GraphQLObjectType) {
assert.strictEqual(object, schema.getQueryType());
visited.add(object);
visitCount++;
}
},
});

assert.strictEqual(visited.size, 1);
assert.strictEqual(visitCount, 1);
visited.forEach(object => {
assert.strictEqual(object, schema.getType('Query'));
});
});

it('can visit the schema itself', () => {
Expand Down Expand Up @@ -1081,14 +1077,12 @@ describe('@directives', () => {
});

it('automatically updates references to changed types', () => {
let HumanType: GraphQLObjectType = null;

const schema = makeExecutableSchema({
typeDefs,
schemaDirectives: {
objectTypeDirective: class extends SchemaDirectiveVisitor {
public visitObject(object: GraphQLObjectType) {
return HumanType = Object.create(object, {
return Object.create(object, {
name: { value: 'Human' }
});
}
Expand All @@ -1099,19 +1093,19 @@ describe('@directives', () => {
const Query = schema.getType('Query') as GraphQLObjectType;
const peopleType = Query.getFields().people.type;
if (peopleType instanceof GraphQLList) {
assert.strictEqual(peopleType.ofType, HumanType);
assert.strictEqual(peopleType.ofType, schema.getType('Human'));
} else {
throw new Error('Query.people not a GraphQLList type');
}

const Mutation = schema.getType('Mutation') as GraphQLObjectType;
const addPersonResultType = Mutation.getFields().addPerson.type;
assert.strictEqual(addPersonResultType, HumanType);
assert.strictEqual(addPersonResultType, schema.getType('Human') as GraphQLOutputType);

const WhateverUnion = schema.getType('WhateverUnion') as GraphQLUnionType;
const found = WhateverUnion.getTypes().some(type => {
if (type.name === 'Human') {
assert.strictEqual(type, HumanType);
assert.strictEqual(type, schema.getType('Human'));
return true;
}
});
Expand Down Expand Up @@ -1209,7 +1203,7 @@ describe('@directives', () => {

it('does not enforce query directive locations (issue #680)', () => {
const visited = new Set<GraphQLObjectType>();
const schema = makeExecutableSchema({
makeExecutableSchema({
typeDefs: `
directive @hasScope(scope: [String]) on QUERY | FIELD | OBJECT
Expand All @@ -1228,9 +1222,6 @@ describe('@directives', () => {
});

assert.strictEqual(visited.size, 1);
visited.forEach(object => {
assert.strictEqual(schema.getType('Query'), object);
});
});

it('allows multiple directives when first replaces type (issue #851)', () => {
Expand Down
9 changes: 6 additions & 3 deletions src/utils/visitSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,12 @@ export function visitSchema(
// during the traversal, so implementors don't have to worry about that.
healSchema(schema);

// Return a cloned version of the schema as a workaround for constructor
// initiliazation not currently healed, e.g. the stored implementation map.
return cloneSchema(schema);
// Reconstruct the schema to reinitialize private variables
// e.g. the stored implementation map.
Object.assign(schema, cloneSchema(schema));

// Return schema for convenience, even though schema parameter has all updated types.
return schema;
}


Expand Down

0 comments on commit c3bbeaf

Please sign in to comment.