Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/utilities/__tests__/findBreakingChanges-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
findTypesRemovedFromUnions,
findTypesThatChangedKind,
findValuesRemovedFromEnums,
findValuesAddedToEnums,
findArgChanges,
findInterfacesRemovedFromObjectTypes,
} from '../findBreakingChanges';
Expand Down Expand Up @@ -1349,7 +1350,63 @@ describe('findDangerousChanges', () => {
});
});

it('should detect if a value was added to an enum type', () => {
const oldEnumType = new GraphQLEnumType({
name: 'EnumType1',
values: {
VALUE0: { value: 0 },
VALUE1: { value: 1 },
}
});
const newEnumType = new GraphQLEnumType({
name: 'EnumType1',
values: {
VALUE0: { value: 0 },
VALUE1: { value: 1 },
VALUE2: { value: 2 },
}
});

const oldSchema = new GraphQLSchema({
query: queryType,
types: [
oldEnumType,
]
});
const newSchema = new GraphQLSchema({
query: queryType,
types: [
newEnumType,
]
});

expect(findValuesAddedToEnums(oldSchema, newSchema)).to.eql(
[
{
type: DangerousChangeType.VALUE_ADDED_TO_ENUM,
description: 'VALUE2 was added to enum type EnumType1.',
}
]
);
});

it('should find all dangerous changes', () => {
const enumThatGainsAValueOld = new GraphQLEnumType({
name: 'EnumType1',
values: {
VALUE0: { value: 0 },
VALUE1: { value: 1 },
}
});
const enumThatGainsAValueNew = new GraphQLEnumType({
name: 'EnumType1',
values: {
VALUE0: { value: 0 },
VALUE1: { value: 1 },
VALUE2: { value: 2 },
}
});

const oldType = new GraphQLObjectType({
name: 'Type1',
fields: {
Expand Down Expand Up @@ -1384,20 +1441,26 @@ describe('findDangerousChanges', () => {
query: queryType,
types: [
oldType,
enumThatGainsAValueOld
]
});

const newSchema = new GraphQLSchema({
query: queryType,
types: [
newType,
enumThatGainsAValueNew
]
});

const expectedDangerousChanges = [
{
description: 'Type1.field1 arg name has changed defaultValue',
type: 'ARG_DEFAULT_VALUE_CHANGE'
},
{
description: 'VALUE2 was added to enum type EnumType1.',
type: 'VALUE_ADDED_TO_ENUM',
}
];

Expand Down
38 changes: 38 additions & 0 deletions src/utilities/findBreakingChanges.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const BreakingChangeType = {

export const DangerousChangeType = {
ARG_DEFAULT_VALUE_CHANGE: 'ARG_DEFAULT_VALUE_CHANGE',
VALUE_ADDED_TO_ENUM: 'VALUE_ADDED_TO_ENUM'
};

export type BreakingChange = {
Expand Down Expand Up @@ -85,6 +86,7 @@ export function findDangerousChanges(
): Array<DangerousChange> {
return [
...findArgChanges(oldSchema, newSchema).dangerousChanges,
...findValuesAddedToEnums(oldSchema, newSchema)
];
}

Expand Down Expand Up @@ -542,6 +544,42 @@ export function findValuesRemovedFromEnums(
return valuesRemovedFromEnums;
}

/**
* Given two schemas, returns an Array containing descriptions of any dangerous
* changes in the newSchema related to adding values to an enum type.
*/
export function findValuesAddedToEnums(
oldSchema: GraphQLSchema,
newSchema: GraphQLSchema
): Array<DangerousChange> {
const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();

const valuesAddedToEnums = [];
Object.keys(oldTypeMap).forEach(typeName => {
const oldType = oldTypeMap[typeName];
const newType = newTypeMap[typeName];
if (!(oldType instanceof GraphQLEnumType) ||
!(newType instanceof GraphQLEnumType)) {
return;
}

const valuesInOldEnum = Object.create(null);
oldType.getValues().forEach(value => {
valuesInOldEnum[value.name] = true;
});
newType.getValues().forEach(value => {
if (!valuesInOldEnum[value.name]) {
valuesAddedToEnums.push({
type: DangerousChangeType.VALUE_ADDED_TO_ENUM,
description: `${value.name} was added to enum type ${typeName}.`
});
}
});
});
return valuesAddedToEnums;
}

export function findInterfacesRemovedFromObjectTypes(
oldSchema: GraphQLSchema,
newSchema: GraphQLSchema
Expand Down