Skip to content

Commit

Permalink
Add a utility to detect description changes
Browse files Browse the repository at this point in the history
We use this internally for pinging docs team for PR reviews.
  • Loading branch information
eapache committed Jan 2, 2018
1 parent fd4a69c commit ae3ba3a
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 0 deletions.
76 changes: 76 additions & 0 deletions src/utilities/__tests__/findDescriptionChanges-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* Copyright (c) 2016, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

import { expect } from 'chai';
import { describe, it } from 'mocha';
import { GraphQLObjectType, GraphQLSchema, GraphQLString } from '../../type';
import { findDescriptionChanges } from '../findDescriptionChanges';

describe('findDescriptionChanges', () => {
const queryType = new GraphQLObjectType({
name: 'Query',
fields: {
field1: { type: GraphQLString },
},
});

it('should detect if a description was added to a type', () => {
const typeOld = new GraphQLObjectType({
name: 'Type',
fields: {
field1: { type: GraphQLString },
},
});
const typeNew = new GraphQLObjectType({
name: 'Type',
description: 'Something rather',
fields: {
field1: { type: GraphQLString },
},
});

const oldSchema = new GraphQLSchema({
query: queryType,
types: [typeOld],
});
const newSchema = new GraphQLSchema({
query: queryType,
types: [typeNew],
});
expect(findDescriptionChanges(oldSchema, newSchema)).to.eql([
'Description added on type Type.',
]);
expect(findDescriptionChanges(oldSchema, oldSchema)).to.eql([]);
expect(findDescriptionChanges(newSchema, newSchema)).to.eql([]);
});

it('should detect if a type with a description was added', () => {
const type = new GraphQLObjectType({
name: 'Type',
description: 'Something rather',
fields: {
field1: { type: GraphQLString },
},
});

const oldSchema = new GraphQLSchema({
query: queryType,
types: [],
});
const newSchema = new GraphQLSchema({
query: queryType,
types: [type],
});
expect(findDescriptionChanges(oldSchema, newSchema)).to.eql([
'Description added on new type Type.',
]);
expect(findDescriptionChanges(oldSchema, oldSchema)).to.eql([]);
expect(findDescriptionChanges(newSchema, newSchema)).to.eql([]);
});
});
142 changes: 142 additions & 0 deletions src/utilities/findDescriptionChanges.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/* eslint-disable no-restricted-syntax */
// @flow

import {
GraphQLInterfaceType,
GraphQLObjectType,
GraphQLEnumType,
GraphQLInputObjectType,
} from '../type/definition';
import type { GraphQLFieldMap } from '../type/definition';
import { GraphQLSchema } from '../type/schema';

/**
* Given two schemas, returns an Array containing descriptions of any
* descriptions that are new or changed and need review.
*/
export function findDescriptionChanges(
oldSchema: GraphQLSchema,
newSchema: GraphQLSchema,
): Array<string> {
const oldTypeMap = oldSchema.getTypeMap();
const newTypeMap = newSchema.getTypeMap();

const descriptionChanges: Array<string> = [];

Object.keys(newTypeMap).forEach(typeName => {
const oldType = oldTypeMap[typeName];
const newType = newTypeMap[typeName];

if (newType.description) {
if (!oldType) {
descriptionChanges.push(
`Description added on new type ${newType.name}.`,
);
} else if (!oldType.description) {
descriptionChanges.push(`Description added on type ${newType.name}.`);
} else if (oldType.description !== newType.description) {
descriptionChanges.push(`Description changed on type ${newType.name}.`);
}
}

if (oldType && !(newType instanceof oldType.constructor)) {
return;
}

if (
newType instanceof GraphQLObjectType ||
newType instanceof GraphQLInterfaceType ||
newType instanceof GraphQLInputObjectType
) {
const oldTypeFields: ?GraphQLFieldMap<*, *> = oldType
? oldType.getFields()
: null;
const newTypeFields: GraphQLFieldMap<*, *> = newType.getFields();

Object.keys(newTypeFields).forEach(fieldName => {
const oldField = oldTypeFields ? oldTypeFields[fieldName] : null;
const newField = newTypeFields[fieldName];

if (newField.description) {
if (!oldField) {
descriptionChanges.push(
`Description added on new field ${newType.name}.${newField.name}`,
);
} else if (!oldField.description) {
descriptionChanges.push(
`Description added on field ${newType.name}.${newField.name}.`,
);
} else if (oldField.description !== newField.description) {
descriptionChanges.push(
`Description changed on field ${newType.name}.${newField.name}.`,
);
}
}

if (!newField.args) {
return;
}

newField.args.forEach(newArg => {
const oldArg = oldField
? oldField.args.find(arg => arg.name === newArg.name)
: null;

if (newArg.description) {
if (!oldArg) {
descriptionChanges.push(
`Description added on new arg ${newType.name}.${
newField.name
}.${newArg.name}.`,
);
} else if (!oldArg.description) {
descriptionChanges.push(
`Description added on arg ${newType.name}.${newField.name}.${
newArg.name
}.`,
);
} else if (oldArg.description !== newArg.description) {
descriptionChanges.push(
`Description changed on arg ${newType.name}.${newField.name}.${
newArg.name
}.`,
);
}
}
});
});
} else if (newType instanceof GraphQLEnumType) {
const oldValues = oldType ? oldType.getValues() : null;
const newValues = newType.getValues();
newValues.forEach(newValue => {
const oldValue = oldValues
? oldValues.find(value => value.name === newValue.name)
: null;

if (newValue.description) {
if (!oldValue) {
descriptionChanges.push(
`Description added on enum value ${newType.name}.${
newValue.name
}.`,
);
} else if (!oldValue.description) {
descriptionChanges.push(
`Description added on enum value ${newType.name}.${
newValue.name
}.`,
);
} else if (oldValue.description !== newValue.description) {
descriptionChanges.push(
`Description changed on enum value ${newType.name}.${
newValue.name
}.`,
);
}
}
});
}
});

return descriptionChanges;
}

0 comments on commit ae3ba3a

Please sign in to comment.