Skip to content

Commit b6a46a0

Browse files
authored
Merge pull request #984 from excitement-engineer/enum-dangerous-change
Adding a value to an enum is now a dangerous change.
2 parents 0e7d460 + bb98768 commit b6a46a0

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

src/utilities/__tests__/findBreakingChanges-test.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
findTypesRemovedFromUnions,
3333
findTypesThatChangedKind,
3434
findValuesRemovedFromEnums,
35+
findValuesAddedToEnums,
3536
findArgChanges,
3637
findInterfacesRemovedFromObjectTypes,
3738
} from '../findBreakingChanges';
@@ -1349,7 +1350,63 @@ describe('findDangerousChanges', () => {
13491350
});
13501351
});
13511352

1353+
it('should detect if a value was added to an enum type', () => {
1354+
const oldEnumType = new GraphQLEnumType({
1355+
name: 'EnumType1',
1356+
values: {
1357+
VALUE0: { value: 0 },
1358+
VALUE1: { value: 1 },
1359+
}
1360+
});
1361+
const newEnumType = new GraphQLEnumType({
1362+
name: 'EnumType1',
1363+
values: {
1364+
VALUE0: { value: 0 },
1365+
VALUE1: { value: 1 },
1366+
VALUE2: { value: 2 },
1367+
}
1368+
});
1369+
1370+
const oldSchema = new GraphQLSchema({
1371+
query: queryType,
1372+
types: [
1373+
oldEnumType,
1374+
]
1375+
});
1376+
const newSchema = new GraphQLSchema({
1377+
query: queryType,
1378+
types: [
1379+
newEnumType,
1380+
]
1381+
});
1382+
1383+
expect(findValuesAddedToEnums(oldSchema, newSchema)).to.eql(
1384+
[
1385+
{
1386+
type: DangerousChangeType.VALUE_ADDED_TO_ENUM,
1387+
description: 'VALUE2 was added to enum type EnumType1.',
1388+
}
1389+
]
1390+
);
1391+
});
1392+
13521393
it('should find all dangerous changes', () => {
1394+
const enumThatGainsAValueOld = new GraphQLEnumType({
1395+
name: 'EnumType1',
1396+
values: {
1397+
VALUE0: { value: 0 },
1398+
VALUE1: { value: 1 },
1399+
}
1400+
});
1401+
const enumThatGainsAValueNew = new GraphQLEnumType({
1402+
name: 'EnumType1',
1403+
values: {
1404+
VALUE0: { value: 0 },
1405+
VALUE1: { value: 1 },
1406+
VALUE2: { value: 2 },
1407+
}
1408+
});
1409+
13531410
const oldType = new GraphQLObjectType({
13541411
name: 'Type1',
13551412
fields: {
@@ -1384,20 +1441,26 @@ describe('findDangerousChanges', () => {
13841441
query: queryType,
13851442
types: [
13861443
oldType,
1444+
enumThatGainsAValueOld
13871445
]
13881446
});
13891447

13901448
const newSchema = new GraphQLSchema({
13911449
query: queryType,
13921450
types: [
13931451
newType,
1452+
enumThatGainsAValueNew
13941453
]
13951454
});
13961455

13971456
const expectedDangerousChanges = [
13981457
{
13991458
description: 'Type1.field1 arg name has changed defaultValue',
14001459
type: 'ARG_DEFAULT_VALUE_CHANGE'
1460+
},
1461+
{
1462+
description: 'VALUE2 was added to enum type EnumType1.',
1463+
type: 'VALUE_ADDED_TO_ENUM',
14011464
}
14021465
];
14031466

src/utilities/findBreakingChanges.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const BreakingChangeType = {
4444

4545
export const DangerousChangeType = {
4646
ARG_DEFAULT_VALUE_CHANGE: 'ARG_DEFAULT_VALUE_CHANGE',
47+
VALUE_ADDED_TO_ENUM: 'VALUE_ADDED_TO_ENUM'
4748
};
4849

4950
export type BreakingChange = {
@@ -85,6 +86,7 @@ export function findDangerousChanges(
8586
): Array<DangerousChange> {
8687
return [
8788
...findArgChanges(oldSchema, newSchema).dangerousChanges,
89+
...findValuesAddedToEnums(oldSchema, newSchema)
8890
];
8991
}
9092

@@ -542,6 +544,42 @@ export function findValuesRemovedFromEnums(
542544
return valuesRemovedFromEnums;
543545
}
544546

547+
/**
548+
* Given two schemas, returns an Array containing descriptions of any dangerous
549+
* changes in the newSchema related to adding values to an enum type.
550+
*/
551+
export function findValuesAddedToEnums(
552+
oldSchema: GraphQLSchema,
553+
newSchema: GraphQLSchema
554+
): Array<DangerousChange> {
555+
const oldTypeMap = oldSchema.getTypeMap();
556+
const newTypeMap = newSchema.getTypeMap();
557+
558+
const valuesAddedToEnums = [];
559+
Object.keys(oldTypeMap).forEach(typeName => {
560+
const oldType = oldTypeMap[typeName];
561+
const newType = newTypeMap[typeName];
562+
if (!(oldType instanceof GraphQLEnumType) ||
563+
!(newType instanceof GraphQLEnumType)) {
564+
return;
565+
}
566+
567+
const valuesInOldEnum = Object.create(null);
568+
oldType.getValues().forEach(value => {
569+
valuesInOldEnum[value.name] = true;
570+
});
571+
newType.getValues().forEach(value => {
572+
if (!valuesInOldEnum[value.name]) {
573+
valuesAddedToEnums.push({
574+
type: DangerousChangeType.VALUE_ADDED_TO_ENUM,
575+
description: `${value.name} was added to enum type ${typeName}.`
576+
});
577+
}
578+
});
579+
});
580+
return valuesAddedToEnums;
581+
}
582+
545583
export function findInterfacesRemovedFromObjectTypes(
546584
oldSchema: GraphQLSchema,
547585
newSchema: GraphQLSchema

0 commit comments

Comments
 (0)