Skip to content

Commit ccbbb29

Browse files
CitoIvanGoncharov
authored andcommitted
isSpecifiedDirective should not assume Directive type (#1837)
These can now both be used as standalone tests. Also added some unit tests for these predicates.
1 parent d6c973a commit ccbbb29

File tree

3 files changed

+98
-34
lines changed

3 files changed

+98
-34
lines changed

src/type/__tests__/predicate-test.js

Lines changed: 88 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,25 @@ import { expect } from 'chai';
1212

1313
import {
1414
GraphQLScalarType,
15+
GraphQLBoolean,
16+
GraphQLID,
17+
GraphQLInt,
18+
GraphQLFloat,
19+
GraphQLString,
1520
GraphQLEnumType,
1621
GraphQLInputObjectType,
1722
GraphQLInterfaceType,
1823
GraphQLObjectType,
1924
GraphQLUnionType,
2025
GraphQLList,
2126
GraphQLNonNull,
22-
GraphQLString,
2327
GraphQLDirective,
2428
GraphQLIncludeDirective,
2529
GraphQLSkipDirective,
2630
GraphQLDeprecatedDirective,
2731
isType,
2832
isScalarType,
33+
isSpecifiedScalarType,
2934
isObjectType,
3035
isInterfaceType,
3136
isUnionType,
@@ -82,6 +87,10 @@ const ScalarType = new GraphQLScalarType({
8287
name: 'Scalar',
8388
serialize() {},
8489
});
90+
const Directive = new GraphQLDirective({
91+
name: 'Directive',
92+
locations: ['QUERY'],
93+
});
8594

8695
describe('Type predicates', () => {
8796
describe('isType', () => {
@@ -119,6 +128,11 @@ describe('Type predicates', () => {
119128
expect(() => assertScalarType(ScalarType)).not.to.throw();
120129
});
121130

131+
it('returns false for scalar class (rather than instance)', () => {
132+
expect(isScalarType(GraphQLScalarType)).to.equal(false);
133+
expect(() => assertScalarType(GraphQLScalarType)).to.throw();
134+
});
135+
122136
it('returns false for wrapped scalar', () => {
123137
expect(isScalarType(GraphQLList(ScalarType))).to.equal(false);
124138
expect(() => assertScalarType(GraphQLList(ScalarType))).to.throw();
@@ -127,6 +141,56 @@ describe('Type predicates', () => {
127141
it('returns false for non-scalar', () => {
128142
expect(isScalarType(EnumType)).to.equal(false);
129143
expect(() => assertScalarType(EnumType)).to.throw();
144+
expect(isScalarType(Directive)).to.equal(false);
145+
expect(() => assertScalarType(Directive)).to.throw();
146+
});
147+
148+
it('returns false for random garbage', () => {
149+
expect(isScalarType({ what: 'is this' })).to.equal(false);
150+
expect(() => assertScalarType({ what: 'is this' })).to.throw();
151+
});
152+
});
153+
154+
describe('isSpecifiedScalarType', () => {
155+
it('returns true for specified scalars', () => {
156+
expect(isSpecifiedScalarType(GraphQLString)).to.equal(true);
157+
expect(isSpecifiedScalarType(GraphQLInt)).to.equal(true);
158+
expect(isSpecifiedScalarType(GraphQLFloat)).to.equal(true);
159+
expect(isSpecifiedScalarType(GraphQLBoolean)).to.equal(true);
160+
expect(isSpecifiedScalarType(GraphQLID)).to.equal(true);
161+
});
162+
163+
it('returns false for custom scalar', () => {
164+
expect(isSpecifiedScalarType(ScalarType)).to.equal(false);
165+
});
166+
167+
it('returns false for scalar class (rather than specified instance)', () => {
168+
expect(isSpecifiedScalarType(GraphQLScalarType)).to.equal(false);
169+
});
170+
171+
it('returns false for wrapped specified scalar', () => {
172+
expect(isSpecifiedScalarType(GraphQLList(GraphQLString))).to.equal(false);
173+
});
174+
175+
it('returns false for non-scalar', () => {
176+
expect(isSpecifiedScalarType(EnumType)).to.equal(false);
177+
expect(isSpecifiedScalarType(Directive)).to.equal(false);
178+
});
179+
180+
it('returns false for spec defined directive', () => {
181+
expect(isSpecifiedScalarType(GraphQLSkipDirective)).to.equal(false);
182+
});
183+
184+
it('returns false for object type named like specified scalar', () => {
185+
const ObjectNamedLikeScalar = new GraphQLObjectType({
186+
name: 'String',
187+
fields: { serialize: { type: GraphQLString } },
188+
});
189+
expect(isSpecifiedScalarType(ObjectNamedLikeScalar)).to.equal(false);
190+
});
191+
192+
it('returns false for random garbage', () => {
193+
expect(isSpecifiedScalarType({ what: 'is this' })).to.equal(false);
130194
});
131195
});
132196

@@ -593,30 +657,26 @@ describe('Type predicates', () => {
593657

594658
describe('Directive predicates', () => {
595659
describe('isDirective', () => {
596-
it('returns true for directives', () => {
597-
const directive = new GraphQLDirective({
598-
name: 'Foo',
599-
locations: ['QUERY'],
600-
});
601-
expect(isDirective(directive)).to.equal(true);
602-
expect(() => assertDirective(directive)).not.to.throw();
660+
it('returns true for spec defined directive', () => {
603661
expect(isDirective(GraphQLSkipDirective)).to.equal(true);
604662
expect(() => assertDirective(GraphQLSkipDirective)).not.to.throw();
605663
});
606664

665+
it('returns true for custom directive', () => {
666+
expect(isDirective(Directive)).to.equal(true);
667+
expect(() => assertDirective(Directive)).not.to.throw();
668+
});
669+
607670
it('returns false for directive class (rather than instance)', () => {
608671
expect(isDirective(GraphQLDirective)).to.equal(false);
609672
expect(() => assertDirective(GraphQLDirective)).to.throw();
610673
});
611674

612-
it('returns false for object type', () => {
613-
expect(isDirective(ObjectType)).to.equal(false);
614-
expect(() => assertDirective(ObjectType)).to.throw();
615-
});
616-
617-
it('returns false for scalar type', () => {
618-
expect(isDirective(GraphQLString)).to.equal(false);
619-
expect(() => assertDirective(GraphQLString)).to.throw();
675+
it('returns false for non-directive', () => {
676+
expect(isDirective(EnumType)).to.equal(false);
677+
expect(() => assertDirective(EnumType)).to.throw();
678+
expect(isDirective(ScalarType)).to.equal(false);
679+
expect(() => assertDirective(ScalarType)).to.throw();
620680
});
621681

622682
it('returns false for random garbage', () => {
@@ -632,30 +692,31 @@ describe('Directive predicates', () => {
632692
});
633693

634694
it('returns false for custom directive', () => {
635-
const directive = new GraphQLDirective({
636-
name: 'Foo',
637-
locations: ['QUERY'],
638-
});
639-
expect(isSpecifiedDirective(directive)).to.equal(false);
695+
expect(isSpecifiedDirective(Directive)).to.equal(false);
640696
});
641697

642698
it('returns false for directive class (rather than specified instance)', () => {
643-
// $DisableFlowOnNegativeTest
644699
expect(isSpecifiedDirective(GraphQLDirective)).to.equal(false);
645700
});
646701

647-
it('returns false for object type', () => {
648-
// $DisableFlowOnNegativeTest
649-
expect(isSpecifiedDirective(ObjectType)).to.equal(false);
702+
it('returns false for non-directive', () => {
703+
expect(isSpecifiedDirective(EnumType)).to.equal(false);
704+
expect(isSpecifiedDirective(ScalarType)).to.equal(false);
650705
});
651706

652707
it('returns false for spec defined scalar type', () => {
653-
// $DisableFlowOnNegativeTest
654708
expect(isSpecifiedDirective(GraphQLString)).to.equal(false);
655709
});
656710

711+
it('returns false for scalar type named like specified directive', () => {
712+
const ScalarNamedLikeDirective = new GraphQLScalarType({
713+
name: 'deprecated',
714+
serialize: () => null,
715+
});
716+
expect(isSpecifiedDirective(ScalarNamedLikeDirective)).to.equal(false);
717+
});
718+
657719
it('returns false for random garbage', () => {
658-
// $DisableFlowOnNegativeTest
659720
expect(isSpecifiedDirective({ what: 'is this' })).to.equal(false);
660721
});
661722
});

src/type/directives.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,13 @@ export const specifiedDirectives: $ReadOnlyArray<*> = [
187187
GraphQLDeprecatedDirective,
188188
];
189189

190-
export function isSpecifiedDirective(
191-
directive: GraphQLDirective,
192-
): boolean %checks {
193-
return specifiedDirectives.some(
194-
specifiedDirective => specifiedDirective.name === directive.name,
190+
export function isSpecifiedDirective(directive: mixed): boolean %checks {
191+
return (
192+
isDirective(directive) &&
193+
// Would prefer to use specifiedDirectives.some(), however %checks needs
194+
// a simple expression.
195+
(directive.name === GraphQLIncludeDirective.name ||
196+
directive.name === GraphQLSkipDirective.name ||
197+
directive.name === GraphQLDeprecatedDirective.name)
195198
);
196199
}

src/type/scalars.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import isFinite from '../polyfills/isFinite';
1111
import isInteger from '../polyfills/isInteger';
1212
import inspect from '../jsutils/inspect';
13-
import { GraphQLScalarType, isNamedType } from './definition';
13+
import { GraphQLScalarType, isScalarType } from './definition';
1414
import { Kind } from '../language/kinds';
1515

1616
// As per the GraphQL Spec, Integers are only treated as valid when a valid
@@ -255,7 +255,7 @@ export const specifiedScalarTypes: $ReadOnlyArray<*> = [
255255

256256
export function isSpecifiedScalarType(type: mixed): boolean %checks {
257257
return (
258-
isNamedType(type) &&
258+
isScalarType(type) &&
259259
// Would prefer to use specifiedScalarTypes.some(), however %checks needs
260260
// a simple expression.
261261
(type.name === GraphQLString.name ||

0 commit comments

Comments
 (0)