From aeb8949c7ef273c25c8dd8ef7166633393ffba0b Mon Sep 17 00:00:00 2001 From: Dirk-Jan Rutten Date: Sat, 12 Aug 2017 14:41:47 +0200 Subject: [PATCH 1/4] Adding an interface to a type is now a dangerous change. --- .../__tests__/findBreakingChanges-test.js | 96 ++++++++++++++++++- src/utilities/findBreakingChanges.js | 39 +++++++- 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/src/utilities/__tests__/findBreakingChanges-test.js b/src/utilities/__tests__/findBreakingChanges-test.js index 26a5205e64..bc68b34845 100644 --- a/src/utilities/__tests__/findBreakingChanges-test.js +++ b/src/utilities/__tests__/findBreakingChanges-test.js @@ -35,6 +35,7 @@ import { findValuesAddedToEnums, findArgChanges, findInterfacesRemovedFromObjectTypes, + findInterfacesAddedToObjectTypes } from '../findBreakingChanges'; describe('findBreakingChanges', () => { @@ -1390,6 +1391,60 @@ describe('findDangerousChanges', () => { ); }); + it('should detect interfaces added to types', () => { + const interface1 = new GraphQLInterfaceType({ + name: 'Interface1', + fields: { + field1: { type: GraphQLString }, + }, + resolveType: () => null, + }); + const oldType = new GraphQLObjectType({ + name: 'Type1', + interfaces: [], + fields: { + field1: { + type: GraphQLString, + }, + }, + }); + + const newType = new GraphQLObjectType({ + name: 'Type1', + interfaces: [ + interface1 + ], + fields: { + field1: { + type: GraphQLString, + }, + }, + }); + + const oldSchema = new GraphQLSchema({ + query: queryType, + types: [ + oldType, + ] + }); + + const newSchema = new GraphQLSchema({ + query: queryType, + types: [ + newType, + ] + }); + + expect( + findInterfacesAddedToObjectTypes(oldSchema, newSchema) + ).to.eql([ + { + description: 'Interface1 added to interfaces implemented by Type1.', + type: DangerousChangeType.INTERFACE_ADDED_TO_OBJECT + } + ]); + }); + it('should find all dangerous changes', () => { const enumThatGainsAValueOld = new GraphQLEnumType({ name: 'EnumType1', @@ -1437,11 +1492,42 @@ describe('findDangerousChanges', () => { }, }); + const interface1 = new GraphQLInterfaceType({ + name: 'Interface1', + fields: { + field1: { type: GraphQLString }, + }, + resolveType: () => null, + }); + + const typeThatGainsInterfaceOld = new GraphQLObjectType({ + name: 'TypeThatGainsInterface1', + interfaces: [], + fields: { + field1: { + type: GraphQLString, + }, + }, + }); + + const typeThaGainsInterfaceNew = new GraphQLObjectType({ + name: 'TypeThatGainsInterface1', + interfaces: [ + interface1 + ], + fields: { + field1: { + type: GraphQLString, + }, + }, + }); + const oldSchema = new GraphQLSchema({ query: queryType, types: [ oldType, - enumThatGainsAValueOld + enumThatGainsAValueOld, + typeThatGainsInterfaceOld ] }); @@ -1449,7 +1535,8 @@ describe('findDangerousChanges', () => { query: queryType, types: [ newType, - enumThatGainsAValueNew + enumThatGainsAValueNew, + typeThaGainsInterfaceNew ] }); @@ -1461,6 +1548,11 @@ describe('findDangerousChanges', () => { { description: 'VALUE2 was added to enum type EnumType1.', type: 'VALUE_ADDED_TO_ENUM', + }, + { + description: 'Interface1 added to interfaces implemented ' + + 'by TypeThatGainsInterface1.', + type: DangerousChangeType.INTERFACE_ADDED_TO_OBJECT } ]; diff --git a/src/utilities/findBreakingChanges.js b/src/utilities/findBreakingChanges.js index a6b137a9cd..db7df31432 100644 --- a/src/utilities/findBreakingChanges.js +++ b/src/utilities/findBreakingChanges.js @@ -44,7 +44,8 @@ export const BreakingChangeType = { export const DangerousChangeType = { ARG_DEFAULT_VALUE_CHANGE: 'ARG_DEFAULT_VALUE_CHANGE', - VALUE_ADDED_TO_ENUM: 'VALUE_ADDED_TO_ENUM' + VALUE_ADDED_TO_ENUM: 'VALUE_ADDED_TO_ENUM', + INTERFACE_ADDED_TO_OBJECT: 'INTERFACE_ADDED_TO_OBJECT' }; export type BreakingChange = { @@ -86,7 +87,8 @@ export function findDangerousChanges( ): Array { return [ ...findArgChanges(oldSchema, newSchema).dangerousChanges, - ...findValuesAddedToEnums(oldSchema, newSchema) + ...findValuesAddedToEnums(oldSchema, newSchema), + ...findInterfacesAddedToObjectTypes(oldSchema, newSchema) ]; } @@ -612,3 +614,36 @@ export function findInterfacesRemovedFromObjectTypes( }); return breakingChanges; } + +export function findInterfacesAddedToObjectTypes( + oldSchema: GraphQLSchema, + newSchema: GraphQLSchema +): Array { + const oldTypeMap = oldSchema.getTypeMap(); + const newTypeMap = newSchema.getTypeMap(); + const interfacesAddedToObjectTypes = []; + + Object.keys(newTypeMap).forEach(typeName => { + const oldType = oldTypeMap[typeName]; + const newType = newTypeMap[typeName]; + if ( + !(oldType instanceof GraphQLObjectType) || + !(newType instanceof GraphQLObjectType) + ) { + return; + } + + const oldInterfaces = oldType.getInterfaces(); + const newInterfaces = newType.getInterfaces(); + newInterfaces.forEach(newInterface => { + if (!oldInterfaces.some(int => int.name === newInterface.name)) { + interfacesAddedToObjectTypes.push({ + type: DangerousChangeType.INTERFACE_ADDED_TO_OBJECT, + description: `${newInterface.name} added to interfaces implemented ` + + `by ${typeName}.` + }); + } + }); + }); + return interfacesAddedToObjectTypes; +} From 7ba2d33de199476e772f0f623769089d7489feec Mon Sep 17 00:00:00 2001 From: Matt Mahoney Date: Tue, 21 Nov 2017 11:49:17 -0500 Subject: [PATCH 2/4] Trailing space issue from my conflict resolution --- src/utilities/__tests__/findBreakingChanges-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utilities/__tests__/findBreakingChanges-test.js b/src/utilities/__tests__/findBreakingChanges-test.js index efad75ddfd..abc7b13e93 100644 --- a/src/utilities/__tests__/findBreakingChanges-test.js +++ b/src/utilities/__tests__/findBreakingChanges-test.js @@ -1481,7 +1481,7 @@ describe('findDangerousChanges', () => { } ]); }); - + it('should detect if a type was added to a union type', () => { const type1 = new GraphQLObjectType({ name: 'Type1', From eb135801f2db36583ce6697e9fd1305c12843a46 Mon Sep 17 00:00:00 2001 From: Matt Mahoney Date: Tue, 21 Nov 2017 11:51:31 -0500 Subject: [PATCH 3/4] Trailing commas missed in conflict resolution --- src/utilities/findBreakingChanges.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utilities/findBreakingChanges.js b/src/utilities/findBreakingChanges.js index 9dd4293a3e..be12154922 100644 --- a/src/utilities/findBreakingChanges.js +++ b/src/utilities/findBreakingChanges.js @@ -44,7 +44,7 @@ export const BreakingChangeType = { export const DangerousChangeType = { ARG_DEFAULT_VALUE_CHANGE: 'ARG_DEFAULT_VALUE_CHANGE', VALUE_ADDED_TO_ENUM: 'VALUE_ADDED_TO_ENUM', - INTERFACE_ADDED_TO_OBJECT: 'INTERFACE_ADDED_TO_OBJECT' + INTERFACE_ADDED_TO_OBJECT: 'INTERFACE_ADDED_TO_OBJECT', TYPE_ADDED_TO_UNION: 'TYPE_ADDED_TO_UNION', }; @@ -88,8 +88,8 @@ export function findDangerousChanges( return [ ...findArgChanges(oldSchema, newSchema).dangerousChanges, ...findValuesAddedToEnums(oldSchema, newSchema), - ...findInterfacesAddedToObjectTypes(oldSchema, newSchema) - ...findTypesAddedToUnions(oldSchema, newSchema) + ...findInterfacesAddedToObjectTypes(oldSchema, newSchema), + ...findTypesAddedToUnions(oldSchema, newSchema), ]; } From 424194da1b91b403a6cff8812ef6fbceebdd6c71 Mon Sep 17 00:00:00 2001 From: Matt Mahoney Date: Tue, 21 Nov 2017 11:52:50 -0500 Subject: [PATCH 4/4] Additional trailing comma --- src/utilities/__tests__/findBreakingChanges-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utilities/__tests__/findBreakingChanges-test.js b/src/utilities/__tests__/findBreakingChanges-test.js index abc7b13e93..0d2580dd20 100644 --- a/src/utilities/__tests__/findBreakingChanges-test.js +++ b/src/utilities/__tests__/findBreakingChanges-test.js @@ -34,7 +34,7 @@ import { findValuesAddedToEnums, findArgChanges, findInterfacesRemovedFromObjectTypes, - findInterfacesAddedToObjectTypes + findInterfacesAddedToObjectTypes, } from '../findBreakingChanges'; describe('findBreakingChanges', () => {