Skip to content

Commit 2cf2f4c

Browse files
committed
Correctly parse enum values from variables
This adds a test suite to ensure the proper handling of enum types. In doing so, it fixed an issue where enum values were not being properly parsed when provided as variables. Fixes #123
1 parent ae4e0d9 commit 2cf2f4c

File tree

2 files changed

+230
-2
lines changed

2 files changed

+230
-2
lines changed

src/type/__tests__/enumType.js

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/**
2+
* Copyright (c) 2015, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
import { describe, it } from 'mocha';
11+
import { expect } from 'chai';
12+
import {
13+
graphql,
14+
GraphQLSchema,
15+
GraphQLEnumType,
16+
GraphQLObjectType,
17+
GraphQLInt,
18+
GraphQLString,
19+
} from '../../';
20+
21+
22+
describe('Type System: Enum Values', () => {
23+
24+
var ColorType = new GraphQLEnumType({
25+
name: 'Color',
26+
values: {
27+
RED: { value: 0 },
28+
GREEN: { value: 1 },
29+
BLUE: { value: 2 },
30+
}
31+
});
32+
33+
var QueryType = new GraphQLObjectType({
34+
name: 'Query',
35+
fields: {
36+
colorEnum: {
37+
type: ColorType,
38+
args: {
39+
fromEnum: { type: ColorType },
40+
fromInt: { type: GraphQLInt },
41+
fromString: { type: GraphQLString },
42+
},
43+
resolve(value, { fromEnum, fromInt, fromString }) {
44+
return fromInt !== undefined ? fromInt :
45+
fromString !== undefined ? fromString :
46+
fromEnum;
47+
}
48+
},
49+
colorInt: {
50+
type: GraphQLInt,
51+
args: {
52+
fromEnum: { type: ColorType },
53+
fromInt: { type: GraphQLInt },
54+
},
55+
resolve(value, { fromEnum, fromInt }) {
56+
return fromInt !== undefined ? fromInt : fromEnum;
57+
}
58+
}
59+
}
60+
});
61+
62+
var schema = new GraphQLSchema({ query: QueryType });
63+
64+
it('accepts enum literals as input', async () => {
65+
expect(
66+
await graphql(schema, '{ colorInt(fromEnum: GREEN) }')
67+
).to.deep.equal({
68+
data: {
69+
colorInt: 1
70+
}
71+
});
72+
});
73+
74+
it('enum may be output type', async () => {
75+
expect(
76+
await graphql(schema, '{ colorEnum(fromInt: 1) }')
77+
).to.deep.equal({
78+
data: {
79+
colorEnum: 'GREEN'
80+
}
81+
});
82+
});
83+
84+
it('enum may be both input and output type', async () => {
85+
expect(
86+
await graphql(schema, '{ colorEnum(fromEnum: GREEN) }')
87+
).to.deep.equal({
88+
data: {
89+
colorEnum: 'GREEN'
90+
}
91+
});
92+
});
93+
94+
it('does not accept string literals', async () => {
95+
expect(
96+
await graphql(schema, '{ colorEnum(fromEnum: "GREEN") }')
97+
).to.deep.equal({
98+
errors: [
99+
{ message:
100+
'Argument "fromEnum" expected type "Color" but got: "GREEN".' }
101+
]
102+
});
103+
});
104+
105+
it('does not accept incorrect internal value', async () => {
106+
expect(
107+
await graphql(schema, '{ colorEnum(fromString: "GREEN") }')
108+
).to.deep.equal({
109+
data: {
110+
colorEnum: null
111+
}
112+
});
113+
});
114+
115+
it('does not accept internal value in place of enum literal', async () => {
116+
expect(
117+
await graphql(schema, '{ colorEnum(fromEnum: 1) }')
118+
).to.deep.equal({
119+
errors: [
120+
{ message: 'Argument "fromEnum" expected type "Color" but got: 1.' }
121+
]
122+
});
123+
});
124+
125+
it('does not accept enum literal in place of int', async () => {
126+
expect(
127+
await graphql(schema, '{ colorEnum(fromInt: GREEN) }')
128+
).to.deep.equal({
129+
errors: [
130+
{ message: 'Argument "fromInt" expected type "Int" but got: GREEN.' }
131+
]
132+
});
133+
});
134+
135+
it('accepts JSON string as enum variable', async () => {
136+
expect(
137+
await graphql(
138+
schema,
139+
'query test($color: Color!) { colorEnum(fromEnum: $color) }',
140+
null,
141+
{ color: 'BLUE' }
142+
)
143+
).to.deep.equal({
144+
data: {
145+
colorEnum: 'BLUE'
146+
}
147+
});
148+
});
149+
150+
it('does not accept internal value as enum variable', async () => {
151+
expect(
152+
await graphql(
153+
schema,
154+
'query test($color: Color!) { colorEnum(fromEnum: $color) }',
155+
null,
156+
{ color: 2 }
157+
)
158+
).to.deep.equal({
159+
errors: [
160+
{ message:
161+
'Variable "$color" expected value of type "Color!" but got: 2.' }
162+
]
163+
});
164+
});
165+
166+
it('does not accept string variables as enum input', async () => {
167+
expect(
168+
await graphql(
169+
schema,
170+
'query test($color: String!) { colorEnum(fromEnum: $color) }',
171+
null,
172+
{ color: 'BLUE' }
173+
)
174+
).to.deep.equal({
175+
errors: [
176+
{ message: 'Variable "$color" of type "String!" used in position ' +
177+
'expecting type "Color".' }
178+
]
179+
});
180+
});
181+
182+
it('does not accept internal value variable as enum input', async () => {
183+
expect(
184+
await graphql(
185+
schema,
186+
'query test($color: Int!) { colorEnum(fromEnum: $color) }',
187+
null,
188+
{ color: 2 }
189+
)
190+
).to.deep.equal({
191+
errors: [
192+
{ message: 'Variable "$color" of type "Int!" used in position ' +
193+
'expecting type "Color".' }
194+
]
195+
});
196+
});
197+
198+
it('enum value may have an internal value of 0', async () => {
199+
expect(
200+
await graphql(schema, `{
201+
colorEnum(fromEnum: RED)
202+
colorInt(fromEnum: RED)
203+
}`)
204+
).to.deep.equal({
205+
data: {
206+
colorEnum: 'RED',
207+
colorInt: 0
208+
}
209+
});
210+
});
211+
212+
it('enum inputs may be nullable', async () => {
213+
expect(
214+
await graphql(schema, `{
215+
colorEnum
216+
colorInt
217+
}`)
218+
).to.deep.equal({
219+
data: {
220+
colorEnum: null,
221+
colorInt: null
222+
}
223+
});
224+
});
225+
226+
});

src/type/definition.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,8 +652,10 @@ export class GraphQLEnumType/* <T> */ {
652652
}
653653

654654
parseValue(value: any): ?any/* T */ {
655-
var enumValue = this._getValueLookup().get((value: any));
656-
return enumValue ? enumValue.name : null;
655+
var enumValue = this._getNameLookup().get(value);
656+
if (enumValue) {
657+
return enumValue.value;
658+
}
657659
}
658660

659661
parseLiteral(valueAST: Value): ?any/* T */ {

0 commit comments

Comments
 (0)