5
5
* LICENSE file in the root directory of this source tree.
6
6
*/
7
7
8
+ import { inspect } from 'util' ;
9
+ import { readFileSync } from 'fs' ;
10
+ import { join } from 'path' ;
11
+
8
12
import { Kind } from '../kinds' ;
9
13
import { expect } from 'chai' ;
10
14
import { describe , it } from 'mocha' ;
11
15
import { parse , parseValue , parseType } from '../parser' ;
12
16
import { Source } from '../source' ;
13
- import { readFileSync } from 'fs' ;
14
- import { join } from 'path' ;
15
17
import dedent from '../../jsutils/dedent' ;
18
+ import toJSONDeep from './toJSONDeep' ;
16
19
17
20
function expectSyntaxError ( text , message , location ) {
18
- try {
19
- parse ( text ) ;
20
- expect . fail ( 'Expected to throw syntax error' ) ;
21
- } catch ( error ) {
22
- expect ( error . message ) . to . contain ( message ) ;
23
- expect ( error . locations ) . to . deep . equal ( [ location ] ) ;
24
- }
21
+ expect ( ( ) => parse ( text ) )
22
+ . to . throw ( message )
23
+ . with . deep . property ( 'locations' , [ location ] ) ;
25
24
}
26
25
27
26
describe ( 'Parser' , ( ) => {
@@ -43,21 +42,19 @@ describe('Parser', () => {
43
42
caughtError = error ;
44
43
}
45
44
46
- expect ( caughtError . message ) . to . equal (
47
- 'Syntax Error: Expected Name, found <EOF>' ,
48
- ) ;
45
+ expect ( caughtError ) . to . deep . contain ( {
46
+ message : 'Syntax Error: Expected Name, found <EOF>' ,
47
+ positions : [ 1 ] ,
48
+ locations : [ { line : 1 , column : 2 } ] ,
49
+ } ) ;
49
50
50
51
expect ( String ( caughtError ) ) . to . equal ( dedent `
51
52
Syntax Error: Expected Name, found <EOF>
52
53
53
54
GraphQL request (1:2)
54
55
1: {
55
56
^
56
- ` ) ;
57
-
58
- expect ( caughtError . positions ) . to . deep . equal ( [ 1 ] ) ;
59
-
60
- expect ( caughtError . locations ) . to . deep . equal ( [ { line : 1 , column : 2 } ] ) ;
57
+ ` ) ;
61
58
62
59
expectSyntaxError (
63
60
`
@@ -127,31 +124,15 @@ describe('Parser', () => {
127
124
128
125
it ( 'parses multi-byte characters' , ( ) => {
129
126
// Note: \u0A0A could be naively interpretted as two line-feed chars.
130
- expect (
131
- parse ( `
132
- # This comment has a \u0A0A multi-byte character.
133
- { field(arg: "Has a \u0A0A multi-byte character.") }
134
- ` ) ,
135
- ) . to . containSubset ( {
136
- definitions : [
137
- {
138
- selectionSet : {
139
- selections : [
140
- {
141
- arguments : [
142
- {
143
- value : {
144
- kind : Kind . STRING ,
145
- value : 'Has a \u0A0A multi-byte character.' ,
146
- } ,
147
- } ,
148
- ] ,
149
- } ,
150
- ] ,
151
- } ,
152
- } ,
153
- ] ,
154
- } ) ;
127
+ const ast = parse ( `
128
+ # This comment has a \u0A0A multi-byte character.
129
+ { field(arg: "Has a \u0A0A multi-byte character.") }
130
+ ` ) ;
131
+
132
+ expect ( ast ) . to . have . nested . property (
133
+ 'definitions[0].selectionSet.selections[0].arguments[0].value.value' ,
134
+ 'Has a \u0A0A multi-byte character.' ,
135
+ ) ;
155
136
} ) ;
156
137
157
138
const kitchenSink = readFileSync ( join ( __dirname , '/kitchen-sink.graphql' ) , {
@@ -173,22 +154,20 @@ describe('Parser', () => {
173
154
'false' ,
174
155
] ;
175
156
nonKeywords . forEach ( keyword => {
176
- let fragmentName = keyword ;
177
157
// You can't define or reference a fragment named `on`.
178
- if ( keyword === 'on' ) {
179
- fragmentName = 'a' ;
180
- }
181
- expect ( ( ) => {
182
- parse ( dedent `
183
- query ${ keyword } {
184
- ... ${ fragmentName }
185
- ... on ${ keyword } { field }
186
- }
187
- fragment ${ fragmentName } on Type {
188
- ${ keyword } (${ keyword } : $${ keyword } )
189
- @${ keyword } (${ keyword } : ${ keyword } )
190
- }` ) ;
191
- } ) . to . not . throw ( ) ;
158
+ const fragmentName = keyword !== 'on' ? keyword : 'a' ;
159
+ const document = `
160
+ query ${ keyword } {
161
+ ... ${ fragmentName }
162
+ ... on ${ keyword } { field }
163
+ }
164
+ fragment ${ fragmentName } on Type {
165
+ ${ keyword } (${ keyword } : $${ keyword } )
166
+ @${ keyword } (${ keyword } : ${ keyword } )
167
+ }
168
+ ` ;
169
+
170
+ expect ( ( ) => parse ( document ) ) . to . not . throw ( ) ;
192
171
} ) ;
193
172
} ) ;
194
173
@@ -233,16 +212,16 @@ describe('Parser', () => {
233
212
} ) ;
234
213
235
214
it ( 'creates ast' , ( ) => {
236
- const source = new Source ( `{
237
- node(id: 4) {
238
- id,
239
- name
240
- }
241
- }
242
- ` ) ;
243
- const result = parse ( source ) ;
215
+ const result = parse ( dedent `
216
+ {
217
+ node(id: 4) {
218
+ id,
219
+ name
220
+ }
221
+ }
222
+ ` ) ;
244
223
245
- expect ( result ) . to . containSubset ( {
224
+ expect ( toJSONDeep ( result ) ) . to . deep . equal ( {
246
225
kind : Kind . DOCUMENT ,
247
226
loc : { start : 0 , end : 41 } ,
248
227
definitions : [
@@ -324,15 +303,15 @@ describe('Parser', () => {
324
303
} ) ;
325
304
326
305
it ( 'creates ast from nameless query without variables' , ( ) => {
327
- const source = new Source ( `query {
328
- node {
329
- id
330
- }
331
- }
332
- ` ) ;
333
- const result = parse ( source ) ;
306
+ const result = parse ( dedent `
307
+ query {
308
+ node {
309
+ id
310
+ }
311
+ }
312
+ ` ) ;
334
313
335
- expect ( result ) . to . containSubset ( {
314
+ expect ( toJSONDeep ( result ) ) . to . deep . equal ( {
336
315
kind : Kind . DOCUMENT ,
337
316
loc : { start : 0 , end : 30 } ,
338
317
definitions : [
@@ -386,56 +365,52 @@ describe('Parser', () => {
386
365
} ) ;
387
366
388
367
it ( 'allows parsing without source location information' , ( ) => {
389
- const source = new Source ( '{ id }' ) ;
390
- const result = parse ( source , { noLocation : true } ) ;
368
+ const result = parse ( '{ id }' , { noLocation : true } ) ;
391
369
expect ( result . loc ) . to . equal ( undefined ) ;
392
370
} ) ;
393
371
394
372
it ( 'Experimental: allows parsing fragment defined variables' , ( ) => {
395
- const source = new Source (
396
- 'fragment a($v: Boolean = false) on t { f(v: $v) }' ,
397
- ) ;
373
+ const document = 'fragment a($v: Boolean = false) on t { f(v: $v) }' ;
374
+
398
375
expect ( ( ) =>
399
- parse ( source , { experimentalFragmentVariables : true } ) ,
376
+ parse ( document , { experimentalFragmentVariables : true } ) ,
400
377
) . to . not . throw ( ) ;
401
- expect ( ( ) => parse ( source ) ) . to . throw ( 'Syntax Error' ) ;
378
+ expect ( ( ) => parse ( document ) ) . to . throw ( 'Syntax Error' ) ;
402
379
} ) ;
403
380
404
381
it ( 'contains location information that only stringifys start/end' , ( ) => {
405
- const source = new Source ( '{ id }' ) ;
406
- const result = parse ( source ) ;
382
+ const result = parse ( '{ id }' ) ;
383
+
407
384
expect ( JSON . stringify ( result . loc ) ) . to . equal ( '{"start":0,"end":6}' ) ;
408
- // NB: util.inspect used to suck
409
- if ( parseFloat ( process . version . slice ( 1 ) ) > 0.1 ) {
410
- expect ( require ( 'util' ) . inspect ( result . loc ) ) . to . equal (
411
- '{ start: 0, end: 6 }' ,
412
- ) ;
413
- }
385
+ expect ( inspect ( result . loc ) ) . to . equal ( '{ start: 0, end: 6 }' ) ;
414
386
} ) ;
415
387
416
388
it ( 'contains references to source' , ( ) => {
417
389
const source = new Source ( '{ id }' ) ;
418
390
const result = parse ( source ) ;
391
+
419
392
expect ( result . loc . source ) . to . equal ( source ) ;
420
393
} ) ;
421
394
422
395
it ( 'contains references to start and end tokens' , ( ) => {
423
- const source = new Source ( '{ id }' ) ;
424
- const result = parse ( source ) ;
396
+ const result = parse ( '{ id }' ) ;
397
+
425
398
expect ( result . loc . startToken . kind ) . to . equal ( '<SOF>' ) ;
426
399
expect ( result . loc . endToken . kind ) . to . equal ( '<EOF>' ) ;
427
400
} ) ;
428
401
429
402
describe ( 'parseValue' , ( ) => {
430
403
it ( 'parses null value' , ( ) => {
431
- expect ( parseValue ( 'null' ) ) . to . containSubset ( {
404
+ const result = parseValue ( 'null' ) ;
405
+ expect ( toJSONDeep ( result ) ) . to . deep . equal ( {
432
406
kind : Kind . NULL ,
433
407
loc : { start : 0 , end : 4 } ,
434
408
} ) ;
435
409
} ) ;
436
410
437
411
it ( 'parses list values' , ( ) => {
438
- expect ( parseValue ( '[123 "abc"]' ) ) . to . containSubset ( {
412
+ const result = parseValue ( '[123 "abc"]' ) ;
413
+ expect ( toJSONDeep ( result ) ) . to . deep . equal ( {
439
414
kind : Kind . LIST ,
440
415
loc : { start : 0 , end : 11 } ,
441
416
values : [
@@ -448,13 +423,15 @@ describe('Parser', () => {
448
423
kind : Kind . STRING ,
449
424
loc : { start : 5 , end : 10 } ,
450
425
value : 'abc' ,
426
+ block : false ,
451
427
} ,
452
428
] ,
453
429
} ) ;
454
430
} ) ;
455
431
456
432
it ( 'parses block strings' , ( ) => {
457
- expect ( parseValue ( '["""long""" "short"]' ) ) . to . containSubset ( {
433
+ const result = parseValue ( '["""long""" "short"]' ) ;
434
+ expect ( toJSONDeep ( result ) ) . to . deep . equal ( {
458
435
kind : Kind . LIST ,
459
436
loc : { start : 0 , end : 20 } ,
460
437
values : [
@@ -477,7 +454,8 @@ describe('Parser', () => {
477
454
478
455
describe ( 'parseType' , ( ) => {
479
456
it ( 'parses well known types' , ( ) => {
480
- expect ( parseType ( 'String' ) ) . to . containSubset ( {
457
+ const result = parseType ( 'String' ) ;
458
+ expect ( toJSONDeep ( result ) ) . to . deep . equal ( {
481
459
kind : Kind . NAMED_TYPE ,
482
460
loc : { start : 0 , end : 6 } ,
483
461
name : {
@@ -489,7 +467,8 @@ describe('Parser', () => {
489
467
} ) ;
490
468
491
469
it ( 'parses custom types' , ( ) => {
492
- expect ( parseType ( 'MyType' ) ) . to . containSubset ( {
470
+ const result = parseType ( 'MyType' ) ;
471
+ expect ( toJSONDeep ( result ) ) . to . deep . equal ( {
493
472
kind : Kind . NAMED_TYPE ,
494
473
loc : { start : 0 , end : 6 } ,
495
474
name : {
@@ -501,7 +480,8 @@ describe('Parser', () => {
501
480
} ) ;
502
481
503
482
it ( 'parses list types' , ( ) => {
504
- expect ( parseType ( '[MyType]' ) ) . to . containSubset ( {
483
+ const result = parseType ( '[MyType]' ) ;
484
+ expect ( toJSONDeep ( result ) ) . to . deep . equal ( {
505
485
kind : Kind . LIST_TYPE ,
506
486
loc : { start : 0 , end : 8 } ,
507
487
type : {
@@ -517,7 +497,8 @@ describe('Parser', () => {
517
497
} ) ;
518
498
519
499
it ( 'parses non-null types' , ( ) => {
520
- expect ( parseType ( 'MyType!' ) ) . to . containSubset ( {
500
+ const result = parseType ( 'MyType!' ) ;
501
+ expect ( toJSONDeep ( result ) ) . to . deep . equal ( {
521
502
kind : Kind . NON_NULL_TYPE ,
522
503
loc : { start : 0 , end : 7 } ,
523
504
type : {
@@ -533,7 +514,8 @@ describe('Parser', () => {
533
514
} ) ;
534
515
535
516
it ( 'parses nested types' , ( ) => {
536
- expect ( parseType ( '[MyType!]' ) ) . to . containSubset ( {
517
+ const result = parseType ( '[MyType!]' ) ;
518
+ expect ( toJSONDeep ( result ) ) . to . deep . equal ( {
537
519
kind : Kind . LIST_TYPE ,
538
520
loc : { start : 0 , end : 9 } ,
539
521
type : {
0 commit comments