diff --git a/src/utilities/__tests__/buildASTSchema-test.js b/src/utilities/__tests__/buildASTSchema-test.js index 0bdce53f4a1..607a2a8c291 100644 --- a/src/utilities/__tests__/buildASTSchema-test.js +++ b/src/utilities/__tests__/buildASTSchema-test.js @@ -9,7 +9,7 @@ import { expect } from 'chai'; import { describe, it } from 'mocha'; -import { parse } from '../../language'; +import { parse, print } from '../../language'; import { printSchema } from '../schemaPrinter'; import { buildASTSchema, buildSchema } from '../buildASTSchema'; import dedent from '../../jsutils/dedent'; @@ -560,6 +560,78 @@ describe('Schema Builder', () => { expect(rootFields.field2.isDeprecated).to.equal(true); expect(rootFields.field2.deprecationReason).to.equal('Because I said so'); }); + + it('Correctly assign AST nodes', () => { + const schema = buildSchema(` + schema { + query: Query + } + + type Query { + testField(testArg: TestInput): TestUnion + } + + input TestInput { + testInputField: TestEnum + } + + enum TestEnum { + TEST_VALUE + } + + union TestUnion = TestType + + interface TestInterface { + interfaceField: String + } + + type TestType implements TestInterface { + interfaceField: String + } + + directive @test(arg: Int) on FIELD + `); + const query = schema.getType('Query'); + const testInput = schema.getType('TestInput'); + const testEnum = schema.getType('TestEnum'); + const testUnion = schema.getType('TestUnion'); + const testInterface = schema.getType('TestInterface'); + const testType = schema.getType('TestType'); + const testDirective = schema.getDirective('test'); + + const restoredIDL = printSchema(buildSchema( + print(schema.astNode) + '\n' + + print(query.astNode) + '\n' + + print(testInput.astNode) + '\n' + + print(testEnum.astNode) + '\n' + + print(testUnion.astNode) + '\n' + + print(testInterface.astNode) + '\n' + + print(testType.astNode) + '\n' + + print(testDirective.astNode) + )); + expect(restoredIDL).to.be.equal(printSchema(schema)); + + const testField = query.getFields().testField; + expect(print(testField.astNode)).to.equal( + 'testField(testArg: TestInput): TestUnion' + ); + expect(print(testField.args[0].astNode)).to.equal( + 'testArg: TestInput' + ); + expect(print(testInput.getFields().testInputField.astNode)).to.equal( + 'testInputField: TestEnum' + ); + expect(print(testEnum.getValue('TEST_VALUE').astNode)).to.equal( + 'TEST_VALUE' + ); + expect(print(testInterface.getFields().interfaceField.astNode)).to.equal( + 'interfaceField: String' + ); + expect(print(testType.getFields().interfaceField.astNode)).to.equal( + 'interfaceField: String' + ); + expect(print(testDirective.args[0].astNode)).to.equal('arg: Int'); + }); }); describe('Failures', () => { diff --git a/src/utilities/buildASTSchema.js b/src/utilities/buildASTSchema.js index 511dca40c90..f3d0e6dac2f 100644 --- a/src/utilities/buildASTSchema.js +++ b/src/utilities/buildASTSchema.js @@ -263,6 +263,7 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema { null, types, directives, + astNode: schemaDef, }); function getDirective( @@ -275,6 +276,7 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema { node => ((node.value: any): DirectiveLocationEnum) ), args: directiveNode.arguments && makeInputValues(directiveNode.arguments), + astNode: directiveNode, }); } @@ -359,6 +361,7 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema { description: getDescription(def), fields: () => makeFieldDefMap(def), interfaces: () => makeImplementedInterfaces(def), + astNode: def, }); } @@ -372,7 +375,8 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema { type: produceOutputType(field.type), description: getDescription(field), args: makeInputValues(field.arguments), - deprecationReason: getDeprecationReason(field) + deprecationReason: getDeprecationReason(field), + astNode: field, }) ); } @@ -391,7 +395,8 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema { return { type, description: getDescription(value), - defaultValue: valueFromAST(value.defaultValue, type) + defaultValue: valueFromAST(value.defaultValue, type), + astNode: value, }; } ); @@ -403,6 +408,7 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema { name: typeName, description: getDescription(def), fields: () => makeFieldDefMap(def), + astNode: def, resolveType: cannotExecuteSchema, }); } @@ -416,9 +422,11 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema { enumValue => enumValue.name.value, enumValue => ({ description: getDescription(enumValue), - deprecationReason: getDeprecationReason(enumValue) + deprecationReason: getDeprecationReason(enumValue), + astNode: enumValue, }) ), + astNode: def, }); return enumType; @@ -430,6 +438,7 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema { description: getDescription(def), types: def.types.map(t => produceObjectType(t)), resolveType: cannotExecuteSchema, + astNode: def, }); } @@ -437,6 +446,7 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema { return new GraphQLScalarType({ name: def.name.value, description: getDescription(def), + astNode: def, serialize: () => null, // Note: validation calls the parse functions to determine if a // literal value is correct. Returning null would cause use of custom @@ -452,6 +462,7 @@ export function buildASTSchema(ast: DocumentNode): GraphQLSchema { name: def.name.value, description: getDescription(def), fields: () => makeInputValues(def.fields), + astNode: def, }); } }