Skip to content

findDeprecatedUsages() #676

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 20, 2017
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
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ export {

// Compares two GraphQLSchemas and detects breaking changes.
findBreakingChanges,

// Report all deprecated usage within a GraphQL document.
findDeprecatedUsages,
} from './utilities';

export type {
Expand Down
84 changes: 84 additions & 0 deletions src/utilities/__tests__/findDeprecatedUsages-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* 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 { findDeprecatedUsages } from '../findDeprecatedUsages';
import { parse } from '../../language';
import {
GraphQLEnumType,
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
} from '../../type';

describe('findDeprecatedUsages', () => {

const enumType = new GraphQLEnumType({
name: 'EnumType',
values: {
ONE: {},
TWO: { deprecationReason: 'Some enum reason.' }
}
});

const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
normalField: {
args: {
enumArg: { type: enumType },
},
type: GraphQLString,
},
deprecatedField: {
type: GraphQLString,
deprecationReason: 'Some field reason.',
}
}
})
});

it('should report empty set for no deprecated usages', () => {
const errors = findDeprecatedUsages(
schema,
parse('{ normalField(enumArg: ONE) }')
);

expect(errors.length).to.equal(0);
});

it('should report usage of deprecated fields', () => {
const errors = findDeprecatedUsages(
schema,
parse('{ normalField, deprecatedField }')
);

const errorMessages = errors.map(err => err.message);

expect(errorMessages).to.deep.equal([
'The field Query.deprecatedField is deprecated. Some field reason.'
]);
});

it('should report usage of deprecated enums', () => {
const errors = findDeprecatedUsages(
schema,
parse('{ normalField(enumArg: TWO) }')
);

const errorMessages = errors.map(err => err.message);

expect(errorMessages).to.deep.equal([
'The enum value EnumType.TWO is deprecated. Some enum reason.'
]);
});

});
62 changes: 62 additions & 0 deletions src/utilities/findDeprecatedUsages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* @flow */
/**
* Copyright (c) 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 { GraphQLError } from '../error/GraphQLError';
import { visit, visitWithTypeInfo } from '../language/visitor';
import type { DocumentNode } from '../language/ast';
import { getNamedType } from '../type/definition';
import { GraphQLSchema } from '../type/schema';
import { TypeInfo } from './TypeInfo';

/**
* A validation rule which reports deprecated usages.
*
* Returns a list of GraphQLError instances describing each deprecated use.
*/
export function findDeprecatedUsages(
schema: GraphQLSchema,
ast: DocumentNode,
): Array<GraphQLError> {
const errors = [];
const typeInfo = new TypeInfo(schema);

visit(ast, visitWithTypeInfo(typeInfo, {
Field(node) {
const fieldDef = typeInfo.getFieldDef();
if (fieldDef && fieldDef.isDeprecated) {
const parentType = typeInfo.getParentType();
if (parentType) {
const reason = fieldDef.deprecationReason;
errors.push(new GraphQLError(
`The field ${parentType.name}.${fieldDef.name} is deprecated.` +
(reason ? ' ' + reason : ''),
[ node ]
));
}
}
},
EnumValue(node) {
const enumVal = typeInfo.getEnumValue();
if (enumVal && enumVal.isDeprecated) {
const type = getNamedType(typeInfo.getInputType());
if (type) {
const reason = enumVal.deprecationReason;
errors.push(new GraphQLError(
`The enum value ${type.name}.${enumVal.name} is deprecated.` +
(reason ? ' ' + reason : ''),
[ node ]
));
}
}
}
}));

return errors;
}
3 changes: 3 additions & 0 deletions src/utilities/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,6 @@ export { assertValidName } from './assertValidName';
// Compares two GraphQLSchemas and detects breaking changes.
export { findBreakingChanges } from './findBreakingChanges';
export type { BreakingChange } from './findBreakingChanges';

// Report all deprecated usage within a GraphQL document.
export { findDeprecatedUsages } from './findDeprecatedUsages';