3
3
import { expect } from 'chai' ;
4
4
import { describe , it } from 'mocha' ;
5
5
6
+ import type { ObjMap } from '../../jsutils/ObjMap' ;
7
+ import { invariant } from '../../jsutils/invariant' ;
8
+ import { identityFunc } from '../../jsutils/identityFunc' ;
9
+
6
10
import { parseValue } from '../../language/parser' ;
7
- import { GraphQLBoolean } from '../../type/scalars' ;
11
+
12
+ import type { GraphQLInputType } from '../../type/definition' ;
13
+ import {
14
+ GraphQLInt ,
15
+ GraphQLFloat ,
16
+ GraphQLString ,
17
+ GraphQLBoolean ,
18
+ GraphQLID ,
19
+ } from '../../type/scalars' ;
20
+ import {
21
+ GraphQLList ,
22
+ GraphQLNonNull ,
23
+ GraphQLScalarType ,
24
+ GraphQLEnumType ,
25
+ GraphQLInputObjectType ,
26
+ } from '../../type/definition' ;
27
+
8
28
import { valueFromAST } from '../valueFromAST' ;
9
29
10
30
import { expectWarning } from './expectWarning' ;
11
31
12
32
describe ( 'valueFromAST' , ( ) => {
33
+ function expectValueFrom (
34
+ valueText : string ,
35
+ type : GraphQLInputType ,
36
+ variables ?: ObjMap < mixed > ,
37
+ ) {
38
+ const ast = parseValue ( valueText ) ;
39
+ const value = valueFromAST ( ast , type , variables ) ;
40
+ return expect ( value ) ;
41
+ }
42
+
13
43
it ( 'warns about deprecation' , ( ) => {
14
44
expectWarning ( ( ) =>
15
45
valueFromAST ( parseValue ( 'true' ) , GraphQLBoolean ) ,
@@ -21,4 +51,227 @@ describe('valueFromAST', () => {
21
51
it ( 'rejects empty input' , ( ) => {
22
52
expect ( valueFromAST ( null , GraphQLBoolean ) ) . to . deep . equal ( undefined ) ;
23
53
} ) ;
54
+
55
+ it ( 'converts according to input coercion rules' , ( ) => {
56
+ expectValueFrom ( 'true' , GraphQLBoolean ) . to . equal ( true ) ;
57
+ expectValueFrom ( 'false' , GraphQLBoolean ) . to . equal ( false ) ;
58
+ expectValueFrom ( '123' , GraphQLInt ) . to . equal ( 123 ) ;
59
+ expectValueFrom ( '123' , GraphQLFloat ) . to . equal ( 123 ) ;
60
+ expectValueFrom ( '123.456' , GraphQLFloat ) . to . equal ( 123.456 ) ;
61
+ expectValueFrom ( '"abc123"' , GraphQLString ) . to . equal ( 'abc123' ) ;
62
+ expectValueFrom ( '123456' , GraphQLID ) . to . equal ( '123456' ) ;
63
+ expectValueFrom ( '"123456"' , GraphQLID ) . to . equal ( '123456' ) ;
64
+ } ) ;
65
+
66
+ it ( 'does not convert when input coercion rules reject a value' , ( ) => {
67
+ expectValueFrom ( '123' , GraphQLBoolean ) . to . equal ( undefined ) ;
68
+ expectValueFrom ( '123.456' , GraphQLInt ) . to . equal ( undefined ) ;
69
+ expectValueFrom ( 'true' , GraphQLInt ) . to . equal ( undefined ) ;
70
+ expectValueFrom ( '"123"' , GraphQLInt ) . to . equal ( undefined ) ;
71
+ expectValueFrom ( '"123"' , GraphQLFloat ) . to . equal ( undefined ) ;
72
+ expectValueFrom ( '123' , GraphQLString ) . to . equal ( undefined ) ;
73
+ expectValueFrom ( 'true' , GraphQLString ) . to . equal ( undefined ) ;
74
+ expectValueFrom ( '123.456' , GraphQLString ) . to . equal ( undefined ) ;
75
+ } ) ;
76
+
77
+ it ( 'convert using parseLiteral from a custom scalar type' , ( ) => {
78
+ const passthroughScalar = new GraphQLScalarType ( {
79
+ name : 'PassthroughScalar' ,
80
+ parseLiteral ( node ) {
81
+ invariant ( node . kind === 'StringValue' ) ;
82
+ return node . value ;
83
+ } ,
84
+ parseValue : identityFunc ,
85
+ } ) ;
86
+
87
+ expectValueFrom ( '"value"' , passthroughScalar ) . to . equal ( 'value' ) ;
88
+
89
+ const throwScalar = new GraphQLScalarType ( {
90
+ name : 'ThrowScalar' ,
91
+ parseLiteral ( ) {
92
+ throw new Error ( 'Test' ) ;
93
+ } ,
94
+ parseValue : identityFunc ,
95
+ } ) ;
96
+
97
+ expectValueFrom ( 'value' , throwScalar ) . to . equal ( undefined ) ;
98
+
99
+ const returnUndefinedScalar = new GraphQLScalarType ( {
100
+ name : 'ReturnUndefinedScalar' ,
101
+ parseLiteral ( ) {
102
+ return undefined ;
103
+ } ,
104
+ parseValue : identityFunc ,
105
+ } ) ;
106
+
107
+ expectValueFrom ( 'value' , returnUndefinedScalar ) . to . equal ( undefined ) ;
108
+ } ) ;
109
+
110
+ it ( 'converts enum values according to input coercion rules' , ( ) => {
111
+ const testEnum = new GraphQLEnumType ( {
112
+ name : 'TestColor' ,
113
+ values : {
114
+ RED : { value : 1 } ,
115
+ GREEN : { value : 2 } ,
116
+ BLUE : { value : 3 } ,
117
+ NULL : { value : null } ,
118
+ NAN : { value : NaN } ,
119
+ NO_CUSTOM_VALUE : { value : undefined } ,
120
+ } ,
121
+ } ) ;
122
+
123
+ expectValueFrom ( 'RED' , testEnum ) . to . equal ( 1 ) ;
124
+ expectValueFrom ( 'BLUE' , testEnum ) . to . equal ( 3 ) ;
125
+ expectValueFrom ( '3' , testEnum ) . to . equal ( undefined ) ;
126
+ expectValueFrom ( '"BLUE"' , testEnum ) . to . equal ( undefined ) ;
127
+ expectValueFrom ( 'null' , testEnum ) . to . equal ( null ) ;
128
+ expectValueFrom ( 'NULL' , testEnum ) . to . equal ( null ) ;
129
+ expectValueFrom ( 'NULL' , new GraphQLNonNull ( testEnum ) ) . to . equal ( null ) ;
130
+ expectValueFrom ( 'NAN' , testEnum ) . to . deep . equal ( NaN ) ;
131
+ expectValueFrom ( 'NO_CUSTOM_VALUE' , testEnum ) . to . equal ( 'NO_CUSTOM_VALUE' ) ;
132
+ } ) ;
133
+
134
+ // Boolean!
135
+ const nonNullBool = new GraphQLNonNull ( GraphQLBoolean ) ;
136
+ // [Boolean]
137
+ const listOfBool = new GraphQLList ( GraphQLBoolean ) ;
138
+ // [Boolean!]
139
+ const listOfNonNullBool = new GraphQLList ( nonNullBool ) ;
140
+ // [Boolean]!
141
+ const nonNullListOfBool = new GraphQLNonNull ( listOfBool ) ;
142
+ // [Boolean!]!
143
+ const nonNullListOfNonNullBool = new GraphQLNonNull ( listOfNonNullBool ) ;
144
+
145
+ it ( 'coerces to null unless non-null' , ( ) => {
146
+ expectValueFrom ( 'null' , GraphQLBoolean ) . to . equal ( null ) ;
147
+ expectValueFrom ( 'null' , nonNullBool ) . to . equal ( undefined ) ;
148
+ } ) ;
149
+
150
+ it ( 'coerces lists of values' , ( ) => {
151
+ expectValueFrom ( 'true' , listOfBool ) . to . deep . equal ( [ true ] ) ;
152
+ expectValueFrom ( '123' , listOfBool ) . to . equal ( undefined ) ;
153
+ expectValueFrom ( 'null' , listOfBool ) . to . equal ( null ) ;
154
+ expectValueFrom ( '[true, false]' , listOfBool ) . to . deep . equal ( [ true , false ] ) ;
155
+ expectValueFrom ( '[true, 123]' , listOfBool ) . to . equal ( undefined ) ;
156
+ expectValueFrom ( '[true, null]' , listOfBool ) . to . deep . equal ( [ true , null ] ) ;
157
+ expectValueFrom ( '{ true: true }' , listOfBool ) . to . equal ( undefined ) ;
158
+ } ) ;
159
+
160
+ it ( 'coerces non-null lists of values' , ( ) => {
161
+ expectValueFrom ( 'true' , nonNullListOfBool ) . to . deep . equal ( [ true ] ) ;
162
+ expectValueFrom ( '123' , nonNullListOfBool ) . to . equal ( undefined ) ;
163
+ expectValueFrom ( 'null' , nonNullListOfBool ) . to . equal ( undefined ) ;
164
+ expectValueFrom ( '[true, false]' , nonNullListOfBool ) . to . deep . equal ( [
165
+ true ,
166
+ false ,
167
+ ] ) ;
168
+ expectValueFrom ( '[true, 123]' , nonNullListOfBool ) . to . equal ( undefined ) ;
169
+ expectValueFrom ( '[true, null]' , nonNullListOfBool ) . to . deep . equal ( [
170
+ true ,
171
+ null ,
172
+ ] ) ;
173
+ } ) ;
174
+
175
+ it ( 'coerces lists of non-null values' , ( ) => {
176
+ expectValueFrom ( 'true' , listOfNonNullBool ) . to . deep . equal ( [ true ] ) ;
177
+ expectValueFrom ( '123' , listOfNonNullBool ) . to . equal ( undefined ) ;
178
+ expectValueFrom ( 'null' , listOfNonNullBool ) . to . equal ( null ) ;
179
+ expectValueFrom ( '[true, false]' , listOfNonNullBool ) . to . deep . equal ( [
180
+ true ,
181
+ false ,
182
+ ] ) ;
183
+ expectValueFrom ( '[true, 123]' , listOfNonNullBool ) . to . equal ( undefined ) ;
184
+ expectValueFrom ( '[true, null]' , listOfNonNullBool ) . to . equal ( undefined ) ;
185
+ } ) ;
186
+
187
+ it ( 'coerces non-null lists of non-null values' , ( ) => {
188
+ expectValueFrom ( 'true' , nonNullListOfNonNullBool ) . to . deep . equal ( [ true ] ) ;
189
+ expectValueFrom ( '123' , nonNullListOfNonNullBool ) . to . equal ( undefined ) ;
190
+ expectValueFrom ( 'null' , nonNullListOfNonNullBool ) . to . equal ( undefined ) ;
191
+ expectValueFrom ( '[true, false]' , nonNullListOfNonNullBool ) . to . deep . equal ( [
192
+ true ,
193
+ false ,
194
+ ] ) ;
195
+ expectValueFrom ( '[true, 123]' , nonNullListOfNonNullBool ) . to . equal (
196
+ undefined ,
197
+ ) ;
198
+ expectValueFrom ( '[true, null]' , nonNullListOfNonNullBool ) . to . equal (
199
+ undefined ,
200
+ ) ;
201
+ } ) ;
202
+
203
+ const testInputObj = new GraphQLInputObjectType ( {
204
+ name : 'TestInput' ,
205
+ fields : {
206
+ int : { type : GraphQLInt , defaultValue : 42 } ,
207
+ bool : { type : GraphQLBoolean } ,
208
+ requiredBool : { type : nonNullBool } ,
209
+ } ,
210
+ } ) ;
211
+
212
+ it ( 'coerces input objects according to input coercion rules' , ( ) => {
213
+ expectValueFrom ( 'null' , testInputObj ) . to . equal ( null ) ;
214
+ expectValueFrom ( '123' , testInputObj ) . to . equal ( undefined ) ;
215
+ expectValueFrom ( '[]' , testInputObj ) . to . equal ( undefined ) ;
216
+ expectValueFrom (
217
+ '{ int: 123, requiredBool: false }' ,
218
+ testInputObj ,
219
+ ) . to . deep . equal ( {
220
+ int : 123 ,
221
+ requiredBool : false ,
222
+ } ) ;
223
+ expectValueFrom (
224
+ '{ bool: true, requiredBool: false }' ,
225
+ testInputObj ,
226
+ ) . to . deep . equal ( {
227
+ int : 42 ,
228
+ bool : true ,
229
+ requiredBool : false ,
230
+ } ) ;
231
+ expectValueFrom ( '{ int: true, requiredBool: true }' , testInputObj ) . to . equal (
232
+ undefined ,
233
+ ) ;
234
+ expectValueFrom ( '{ requiredBool: null }' , testInputObj ) . to . equal ( undefined ) ;
235
+ expectValueFrom ( '{ bool: true }' , testInputObj ) . to . equal ( undefined ) ;
236
+ } ) ;
237
+
238
+ it ( 'accepts variable values assuming already coerced' , ( ) => {
239
+ expectValueFrom ( '$var' , GraphQLBoolean , { } ) . to . equal ( undefined ) ;
240
+ expectValueFrom ( '$var' , GraphQLBoolean , { var : true } ) . to . equal ( true ) ;
241
+ expectValueFrom ( '$var' , GraphQLBoolean , { var : null } ) . to . equal ( null ) ;
242
+ expectValueFrom ( '$var' , nonNullBool , { var : null } ) . to . equal ( undefined ) ;
243
+ } ) ;
244
+
245
+ it ( 'asserts variables are provided as items in lists' , ( ) => {
246
+ expectValueFrom ( '[ $foo ]' , listOfBool , { } ) . to . deep . equal ( [ null ] ) ;
247
+ expectValueFrom ( '[ $foo ]' , listOfNonNullBool , { } ) . to . equal ( undefined ) ;
248
+ expectValueFrom ( '[ $foo ]' , listOfNonNullBool , {
249
+ foo : true ,
250
+ } ) . to . deep . equal ( [ true ] ) ;
251
+ // Note: variables are expected to have already been coerced, so we
252
+ // do not expect the singleton wrapping behavior for variables.
253
+ expectValueFrom ( '$foo' , listOfNonNullBool , { foo : true } ) . to . equal ( true ) ;
254
+ expectValueFrom ( '$foo' , listOfNonNullBool , { foo : [ true ] } ) . to . deep . equal ( [
255
+ true ,
256
+ ] ) ;
257
+ } ) ;
258
+
259
+ it ( 'omits input object fields for unprovided variables' , ( ) => {
260
+ expectValueFrom (
261
+ '{ int: $foo, bool: $foo, requiredBool: true }' ,
262
+ testInputObj ,
263
+ { } ,
264
+ ) . to . deep . equal ( { int : 42 , requiredBool : true } ) ;
265
+
266
+ expectValueFrom ( '{ requiredBool: $foo }' , testInputObj , { } ) . to . equal (
267
+ undefined ,
268
+ ) ;
269
+
270
+ expectValueFrom ( '{ requiredBool: $foo }' , testInputObj , {
271
+ foo : true ,
272
+ } ) . to . deep . equal ( {
273
+ int : 42 ,
274
+ requiredBool : true ,
275
+ } ) ;
276
+ } ) ;
24
277
} ) ;
0 commit comments