Completed
Pull Request — master (#204)
by Ryan
11:34
created

ParserTest   C

Complexity

Total Complexity 19

Size/Duplication

Total Lines 859
Duplicated Lines 7.92 %

Coupling/Cohesion

Components 1
Dependencies 17

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 19
c 3
b 0
f 0
lcom 1
cbo 17
dl 68
loc 859
rs 5.2093

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Copyright (c) 2015–2018 Alexandr Viniychuk <http://youshido.com>.
4
 * Copyright (c) 2015–2018 Portey Vasil <https://github.com/portey>.
5
 * Copyright (c) 2018 Ryan Parman <https://github.com/skyzyx>.
6
 * Copyright (c) 2018 Ashley Hutson <https://github.com/asheliahut>.
7
 * Copyright (c) 2015–2018 Contributors.
8
 *
9
 * http://opensource.org/licenses/MIT
10
 */
11
12
declare(strict_types=1);
13
/**
14
 * Date: 01.12.15.
15
 */
16
17
namespace Youshido\Tests\Parser;
18
19
use Youshido\GraphQL\Parser\Ast\Argument;
20
use Youshido\GraphQL\Parser\Ast\ArgumentValue\InputList;
21
use Youshido\GraphQL\Parser\Ast\ArgumentValue\InputObject;
22
use Youshido\GraphQL\Parser\Ast\ArgumentValue\Literal;
23
use Youshido\GraphQL\Parser\Ast\ArgumentValue\Variable;
24
use Youshido\GraphQL\Parser\Ast\ArgumentValue\VariableReference;
25
use Youshido\GraphQL\Parser\Ast\Field;
26
use Youshido\GraphQL\Parser\Ast\Fragment;
27
use Youshido\GraphQL\Parser\Ast\FragmentReference;
28
use Youshido\GraphQL\Parser\Ast\Mutation;
29
use Youshido\GraphQL\Parser\Ast\Query;
30
use Youshido\GraphQL\Parser\Ast\TypedFragmentReference;
31
use Youshido\GraphQL\Parser\Location;
32
use Youshido\GraphQL\Parser\Parser;
33
use Youshido\GraphQL\Parser\Token;
34
35
class TokenizerTestingParser extends Parser
36
{
37
    public function initTokenizerForTesting($source): void
38
    {
39
        $this->initTokenizer($source);
40
    }
41
42
    public function getTokenForTesting()
43
    {
44
        return $this->lookAhead;
45
    }
46
}
47
48
class ParserTest extends \PHPUnit_Framework_TestCase
49
{
50
    public function testEmptyParser(): void
51
    {
52
        $parser = new Parser();
53
54
        $this->assertEquals([
55
            'queries'            => [],
56
            'mutations'          => [],
57
            'fragments'          => [],
58
            'fragmentReferences' => [],
59
            'variables'          => [],
60
            'variableReferences' => [],
61
        ], $parser->parse());
62
    }
63
64
65
    public function testInvalidSelection(): void
66
    {
67
        $this->expectException(\Youshido\GraphQL\Exception\Parser\SyntaxErrorException::class);
68
69
        $parser = new Parser();
70
        $data   = $parser->parse('
71
        {
72
            test {
73
                id
74
                image {
75
                    
76
                }
77
            }
78
        }
79
        ');
80
    }
81
82
    public function testComments(): void
83
    {
84
        $query = <<<'GRAPHQL'
85
# asdasd "asdasdasd"
86
# comment line 2
87
88
query {
89
    authors (category: "#2") { #asda asd
90
        _id
91
    }
92
}
93
GRAPHQL;
94
95
        $parser     = new Parser();
96
        $parsedData = $parser->parse($query);
97
98
        $this->assertEquals($parsedData, [
99
            'queries' => [
100
                new Query(
101
                    'authors',
102
                    null,
103
                    [
104
                        new Argument('category', new Literal('#2', new Location(5, 25)), new Location(5, 14)),
105
                    ],
106
                    [
107
                        new Field('_id', null, [], [], new Location(6, 9)),
108
                    ],
109
                    [],
110
                    new Location(5, 5)
111
                ),
112
            ],
113
            'mutations'          => [],
114
            'fragments'          => [],
115
            'fragmentReferences' => [],
116
            'variables'          => [],
117
            'variableReferences' => [],
118
        ]);
119
    }
120
121
    public function testEscapedStrings(): void
122
    {
123
        $this->assertEquals(
124
            [
125
                $this->tokenizeStringContents(''),
126
                $this->tokenizeStringContents('x'),
127
                $this->tokenizeStringContents('\\"'),
128
                $this->tokenizeStringContents('\\/'),
129
                $this->tokenizeStringContents('\\f'),
130
                $this->tokenizeStringContents('\\n'),
131
                $this->tokenizeStringContents('\\r'),
132
                $this->tokenizeStringContents('\\b'),
133
                $this->tokenizeStringContents('\\uABCD'),
134
            ],
135
            [
136
                new Token(Token::TYPE_STRING, 1, 1, ''),
137
                new Token(Token::TYPE_STRING, 1, 2, 'x'),
138
                new Token(Token::TYPE_STRING, 1, 3, '"'),
139
                new Token(Token::TYPE_STRING, 1, 3, '/'),
140
                new Token(Token::TYPE_STRING, 1, 3, "\f"),
141
                new Token(Token::TYPE_STRING, 1, 3, "\n"),
142
                new Token(Token::TYPE_STRING, 1, 3, "\r"),
143
                new Token(Token::TYPE_STRING, 1, 3, \sprintf('%c', 8)),
144
                new Token(Token::TYPE_STRING, 1, 7, \html_entity_decode('&#xABCD;', ENT_QUOTES, 'UTF-8')),
145
            ]
146
        );
147
    }
148
149
    /**
150
     * @param $query string
151
     *
152
     * @dataProvider wrongQueriesProvider
153
     */
154
    public function testWrongQueries($query): void
155
    {
156
        $this->expectException(\Youshido\GraphQL\Exception\Parser\SyntaxErrorException::class);
157
158
        $parser = new Parser();
159
160
        $parser->parse($query);
161
    }
162
163
    public function testCommas(): void
164
    {
165
        $parser = new Parser();
166
        $data   = $parser->parse('{ foo,       ,,  , bar  }');
167
        $this->assertEquals([
168
            new Query('foo', '', [], [], [], new Location(1, 3)),
169
            new Query('bar', '', [], [], [], new Location(1, 20)),
170
        ], $data['queries']);
171
    }
172
173
    public function testQueryWithNoFields(): void
174
    {
175
        $parser = new Parser();
176
        $data   = $parser->parse('{ name }');
177
        $this->assertEquals([
178
            'queries' => [
179
                new Query('name', '', [], [], [], new Location(1, 3)),
180
            ],
181
            'mutations'          => [],
182
            'fragments'          => [],
183
            'fragmentReferences' => [],
184
            'variables'          => [],
185
            'variableReferences' => [],
186
        ], $data);
187
    }
188
189
    public function testQueryWithFields(): void
190
    {
191
        $parser = new Parser();
192
        $data   = $parser->parse('{ post, user { name } }');
193
        $this->assertEquals([
194
            'queries' => [
195
                new Query('post', null, [], [], [], new Location(1, 3)),
196
                new Query('user', null, [], [
197
                    new Field('name', null, [], [], new Location(1, 16)),
198
                ], [], new Location(1, 9)),
199
            ],
200
            'mutations'          => [],
201
            'fragments'          => [],
202
            'fragmentReferences' => [],
203
            'variables'          => [],
204
            'variableReferences' => [],
205
        ], $data);
206
    }
207
208
    public function testFragmentWithFields(): void
209
    {
210
        $parser = new Parser();
211
        $data   = $parser->parse('
212
            fragment FullType on __Type {
213
                kind
214
                fields {
215
                    name
216
                }
217
            }');
218
        $this->assertEquals([
219
            'queries'   => [],
220
            'mutations' => [],
221
            'fragments' => [
222
                new Fragment('FullType', '__Type', [], [
223
                    new Field('kind', null, [], [], new Location(3, 17)),
224
                    new Query('fields', null, [], [
225
                        new Field('name', null, [], [], new Location(5, 21)),
226
                    ], [], new Location(4, 17)),
227
                ], new Location(2, 22)),
228
            ],
229
            'fragmentReferences' => [],
230
            'variables'          => [],
231
            'variableReferences' => [],
232
        ], $data);
233
    }
234
235
    public function testInspectionQuery(): void
236
    {
237
        $parser = new Parser();
238
239
        $data = $parser->parse('
240
            query IntrospectionQuery {
241
                __schema {
242
                    queryType { name }
243
                    mutationType { name }
244
                    types {
245
                        ...FullType
246
                    }
247
                    directives {
248
                        name
249
                        description
250
                        args {
251
                            ...InputValue
252
                        }
253
                        onOperation
254
                        onFragment
255
                        onField
256
                    }
257
                }
258
            }
259
260
            fragment FullType on __Type {
261
                kind
262
                name
263
                description
264
                fields {
265
                    name
266
                    description
267
                    args {
268
                        ...InputValue
269
                    }
270
                    type {
271
                        ...TypeRef
272
                    }
273
                    isDeprecated
274
                    deprecationReason
275
                }
276
                inputFields {
277
                    ...InputValue
278
                }
279
                interfaces {
280
                    ...TypeRef
281
                }
282
                enumValues {
283
                    name
284
                    description
285
                    isDeprecated
286
                    deprecationReason
287
                }
288
                possibleTypes {
289
                    ...TypeRef
290
                }
291
            }
292
293
            fragment InputValue on __InputValue {
294
                name
295
                description
296
                type { ...TypeRef }
297
                defaultValue
298
            }
299
300
            fragment TypeRef on __Type {
301
                kind
302
                name
303
                ofType {
304
                    kind
305
                    name
306
                    ofType {
307
                        kind
308
                        name
309
                        ofType {
310
                            kind
311
                            name
312
                        }
313
                    }
314
                }
315
            }
316
        ');
317
318
        $this->assertEquals([
319
            'queries' => [
320
                new Query('__schema', null, [], [
321
                    new Query('queryType', null, [], [
322
                        new Field('name', null, [], [], new Location(4, 33)),
323
                    ], [], new Location(4, 21)),
324
                    new Query('mutationType', null, [], [
325
                        new Field('name', null, [], [], new Location(5, 36)),
326
                    ], [], new Location(5, 21)),
327
                    new Query('types', null, [], [
328
                        new FragmentReference('FullType', new Location(7, 28)),
329
                    ], [], new Location(6, 21)),
330
                    new Query('directives', null, [], [
331
                        new Field('name', null, [], [], new Location(10, 25)),
332
                        new Field('description', null, [], [], new Location(11, 25)),
333
                        new Query('args', null, [], [
334
                            new FragmentReference('InputValue', new Location(13, 32)),
335
                        ], [], new Location(12, 25)),
336
                        new Field('onOperation', null, [], [], new Location(15, 25)),
337
                        new Field('onFragment', null, [], [], new Location(16, 25)),
338
                        new Field('onField', null, [], [], new Location(17, 25)),
339
                    ], [], new Location(9, 21)),
340
                ], [], new Location(3, 17)),
341
            ],
342
            'mutations' => [],
343
            'fragments' => [
344
                new Fragment('FullType', '__Type', [], [
345
                    new Field('kind', null, [], [], new Location(23, 17)),
346
                    new Field('name', null, [], [], new Location(24, 17)),
347
                    new Field('description', null, [], [], new Location(25, 17)),
348
                    new Query('fields', null, [], [
349
                        new Field('name', null, [], [], new Location(27, 21)),
350
                        new Field('description', null, [], [], new Location(28, 21)),
351
                        new Query('args', null, [], [
352
                            new FragmentReference('InputValue', new Location(30, 28)),
353
                        ], [], new Location(29, 21)),
354
                        new Query('type', null, [], [
355
                            new FragmentReference('TypeRef', new Location(33, 28)),
356
                        ], [], new Location(32, 21)),
357
                        new Field('isDeprecated', null, [], [], new Location(35, 21)),
358
                        new Field('deprecationReason', null, [], [], new Location(36, 21)),
359
                    ], [], new Location(26, 17)),
360
                    new Query('inputFields', null, [], [
361
                        new FragmentReference('InputValue', new Location(39, 24)),
362
                    ], [], new Location(38, 17)),
363
                    new Query('interfaces', null, [], [
364
                        new FragmentReference('TypeRef', new Location(42, 24)),
365
                    ], [], new Location(41, 17)),
366
                    new Query('enumValues', null, [], [
367
                        new Field('name', null, [], [], new Location(45, 21)),
368
                        new Field('description', null, [], [], new Location(46, 21)),
369
370
                        new Field('isDeprecated', null, [], [], new Location(47, 21)),
371
                        new Field('deprecationReason', null, [], [], new Location(48, 21)),
372
                    ], [], new Location(44, 17)),
373
                    new Query('possibleTypes', null, [], [
374
                        new FragmentReference('TypeRef', new Location(51, 24)),
375
                    ], [], new Location(50, 17)),
376
                ], new Location(22, 22)),
377
                new Fragment('InputValue', '__InputValue', [], [
378
                    new Field('name', null, [], [], new Location(56, 17)),
379
                    new Field('description', null, [], [], new Location(57, 17)),
380
                    new Query('type', null, [], [
381
                        new FragmentReference('TypeRef', new Location(58, 27)),
382
                    ], [], new Location(58, 17)),
383
                    new Field('defaultValue', null, [], [], new Location(59, 17)),
384
                ], new Location(55, 22)),
385
                new Fragment('TypeRef', '__Type', [], [
386
                    new Field('kind', null, [], [], new Location(63, 17)),
387
                    new Field('name', null, [], [], new Location(64, 17)),
388
                    new Query('ofType', null, [], [
389
                        new Field('kind', null, [], [], new Location(66, 21)),
390
                        new Field('name', null, [], [], new Location(67, 21)),
391
                        new Query('ofType', null, [], [
392
                            new Field('kind', null, [], [], new Location(69, 25)),
393
                            new Field('name', null, [], [], new Location(70, 25)),
394
                            new Query('ofType', null, [], [
395
                                new Field('kind', null, [], [], new Location(72, 29)),
396
                                new Field('name', null, [], [], new Location(73, 29)),
397
                            ], [], new Location(71, 25)),
398
                        ], [], new Location(68, 21)),
399
                    ], [], new Location(65, 17)),
400
                ], new Location(62, 22)),
401
            ],
402
            'fragmentReferences' => [
403
                new FragmentReference('FullType', new Location(7, 28)),
404
                new FragmentReference('InputValue', new Location(13, 32)),
405
                new FragmentReference('InputValue', new Location(30, 28)),
406
                new FragmentReference('TypeRef', new Location(33, 28)),
407
                new FragmentReference('InputValue', new Location(39, 24)),
408
                new FragmentReference('TypeRef', new Location(42, 24)),
409
                new FragmentReference('TypeRef', new Location(51, 24)),
410
                new FragmentReference('TypeRef', new Location(58, 27)),
411
            ],
412
            'variables'          => [],
413
            'variableReferences' => [],
414
        ], $data);
415
    }
416
417
    public function wrongQueriesProvider()
418
    {
419
        return [
420
            ['{ test (a: "asd", b: <basd>) { id }'],
421
            ['{ test (asd: [..., asd]) { id } }'],
422
            ['{ test (asd: { "a": 4, "m": null, "asd": false  "b": 5, "c" : { a }}) { id } }'],
423
            ['asdasd'],
424
            ['mutation { test(asd: ... ){ ...,asd, asd } }'],
425
            ['mutation { test{ . test on Test { id } } }'],
426
            ['mutation { test( a: "asdd'],
427
            ['mutation { test( a: { "asd": 12 12'],
428
            ['mutation { test( a: { "asd": 12'],
429
        ];
430
    }
431
432
    /**
433
     * @dataProvider mutationProvider
434
     *
435
     * @param mixed $query
436
     * @param mixed $structure
437
     */
438
    public function testMutations($query, $structure): void
439
    {
440
        $parser = new Parser();
441
442
        $parsedStructure = $parser->parse($query);
443
444
        $this->assertEquals($parsedStructure, $structure);
445
    }
446
447
    public function testTypedFragment(): void
448
    {
449
        $parser          = new Parser();
450
        $parsedStructure = $parser->parse('
451
            {
452
                test: test {
453
                    name,
454
                    ... on UnionType {
455
                        unionName
456
                    }
457
                }
458
            }
459
        ');
460
461
        $this->assertEquals($parsedStructure, [
462
            'queries' => [
463
                new Query(
464
                    'test',
465
                    'test',
466
                    [],
467
                    [
468
                        new Field('name', null, [], [], new Location(4, 21)),
469
                        new TypedFragmentReference('UnionType', [new Field('unionName', null, [], [], new Location(6, 25))], [], new Location(5, 28)),
470
                    ],
471
                    [],
472
                    new Location(3, 23)
473
                ),
474
            ],
475
            'mutations'          => [],
476
            'fragments'          => [],
477
            'fragmentReferences' => [],
478
            'variables'          => [],
479
            'variableReferences' => [],
480
        ]);
481
    }
482
483
    public function mutationProvider()
484
    {
485
        return [
486
            [
487
                'query ($variable: Int){ query ( teas: $variable ) { alias: name } }',
488
                [
489
                    'queries' => [
490
                        new Query(
491
                            'query',
492
                            null,
493
                            [
494
                                new Argument('teas', new VariableReference('variable', (new Variable('variable', 'Int', false, false, true, new Location(1, 8)))->setUsed(true), new Location(1, 39)), new Location(1, 33)),
495
                            ],
496
                            [
497
                                new Field('name', 'alias', [], [], new Location(1, 60)),
498
                            ],
499
                            [],
500
                            new Location(1, 25)
501
                        ),
502
                    ],
503
                    'mutations'          => [],
504
                    'fragments'          => [],
505
                    'fragmentReferences' => [],
506
                    'variables'          => [
507
                        (new Variable('variable', 'Int', false, false, true, new Location(1, 8)))->setUsed(true),
508
                    ],
509
                    'variableReferences' => [
510
                        new VariableReference('variable', (new Variable('variable', 'Int', false, false, true, new Location(1, 8)))->setUsed(true), new Location(1, 39)),
511
                    ],
512
                ],
513
            ],
514
            [
515
                '{ query { alias: name } }',
516
                [
517
                    'queries' => [
518
                        new Query('query', null, [], [new Field('name', 'alias', [], [], new Location(1, 18))], [], new Location(1, 3)),
519
                    ],
520
                    'mutations'          => [],
521
                    'fragments'          => [],
522
                    'fragmentReferences' => [],
523
                    'variables'          => [],
524
                    'variableReferences' => [],
525
                ],
526
            ],
527
            [
528
                'mutation { createUser ( email: "[email protected]", active: true ) { id } }',
529
                [
530
                    'queries'   => [],
531
                    'mutations' => [
532
                        new Mutation(
533
                            'createUser',
534
                            null,
535
                            [
536
                                new Argument('email', new Literal('[email protected]', new Location(1, 33)), new Location(1, 25)),
537
                                new Argument('active', new Literal(true, new Location(1, 57)), new Location(1, 49)),
538
                            ],
539
                            [
540
                                new Field('id', null, [], [], new Location(1, 66)),
541
                            ],
542
                            [],
543
                            new Location(1, 12)
544
                        ),
545
                    ],
546
                    'fragments'          => [],
547
                    'fragmentReferences' => [],
548
                    'variables'          => [],
549
                    'variableReferences' => [],
550
                ],
551
            ],
552
            [
553
                'mutation { test : createUser (id: 4) }',
554
                [
555
                    'queries'   => [],
556
                    'mutations' => [
557
                        new Mutation(
558
                            'createUser',
559
                            'test',
560
                            [
561
                                new Argument('id', new Literal(4, new Location(1, 35)), new Location(1, 31)),
562
                            ],
563
                            [],
564
                            [],
565
                            new Location(1, 19)
566
                        ),
567
                    ],
568
                    'fragments'          => [],
569
                    'fragmentReferences' => [],
570
                    'variables'          => [],
571
                    'variableReferences' => [],
572
                ],
573
            ],
574
        ];
575
    }
576
577
    /**
578
     * @dataProvider queryProvider
579
     *
580
     * @param mixed $query
581
     * @param mixed $structure
582
     */
583
    public function testParser($query, $structure): void
584
    {
585
        $parser          = new Parser();
586
        $parsedStructure = $parser->parse($query);
587
588
        $this->assertEquals($structure, $parsedStructure);
589
    }
590
591
    public function queryProvider()
592
    {
593
        return [
594
            [
595
                '{ film(id: 1 filmID: 2) { title } }',
596
                [
597
                    'queries' => [
598
                        new Query('film', null, [
599
                            new Argument('id', new Literal(1, new Location(1, 12)), new Location(1, 8)),
600
                            new Argument('filmID', new Literal(2, new Location(1, 22)), new Location(1, 14)),
601
                        ], [
602
                            new Field('title', null, [], [], new Location(1, 27)),
603
                        ], [], new Location(1, 3)),
604
                    ],
605
                    'mutations'          => [],
606
                    'fragments'          => [],
607
                    'fragmentReferences' => [],
608
                    'variables'          => [],
609
                    'variableReferences' => [],
610
                ],
611
            ],
612
            [
613
                '{ test (id: -5) { id } } ',
614
                [
615
                    'queries' => [
616
                        new Query('test', null, [
617
                            new Argument('id', new Literal(-5, new Location(1, 13)), new Location(1, 9)),
618
                        ], [
619
                            new Field('id', null, [], [], new Location(1, 19)),
620
                        ], [], new Location(1, 3)),
621
                    ],
622
                    'mutations'          => [],
623
                    'fragments'          => [],
624
                    'fragmentReferences' => [],
625
                    'variables'          => [],
626
                    'variableReferences' => [],
627
                ],
628
            ],
629
            [
630
                "{ test (id: -5) \r\n { id } } ",
631
                [
632
                    'queries' => [
633
                        new Query('test', null, [
634
                            new Argument('id', new Literal(-5, new Location(1, 13)), new Location(1, 9)),
635
                        ], [
636
                            new Field('id', null, [], [], new Location(2, 4)),
637
                        ], [], new Location(1, 3)),
638
                    ],
639
                    'mutations'          => [],
640
                    'fragments'          => [],
641
                    'fragmentReferences' => [],
642
                    'variables'          => [],
643
                    'variableReferences' => [],
644
                ],
645
            ],
646
            [
647
                'query CheckTypeOfLuke {
648
                  hero(episode: EMPIRE) {
649
                    __typename,
650
                    name
651
                  }
652
                }',
653
                [
654
                    'queries' => [
655
                        new Query('hero', null, [
656
                            new Argument('episode', new Literal('EMPIRE', new Location(2, 33)), new Location(2, 24)),
657
                        ], [
658
                            new Field('__typename', null, [], [], new Location(3, 21)),
659
                            new Field('name', null, [], [], new Location(4, 21)),
660
                        ], [], new Location(2, 19)),
661
                    ],
662
                    'mutations'          => [],
663
                    'fragments'          => [],
664
                    'fragmentReferences' => [],
665
                    'variables'          => [],
666
                    'variableReferences' => [],
667
                ],
668
            ],
669
            [
670
                '{ test { __typename, id } }',
671
                [
672
                    'queries' => [
673
                        new Query('test', null, [], [
674
                            new Field('__typename', null, [], [], new Location(1, 10)),
675
                            new Field('id', null, [], [], new Location(1, 22)),
676
                        ], [], new Location(1, 3)),
677
                    ],
678
                    'mutations'          => [],
679
                    'fragments'          => [],
680
                    'fragmentReferences' => [],
681
                    'variables'          => [],
682
                    'variableReferences' => [],
683
                ],
684
            ],
685
            [
686
                '{}',
687
                [
688
                    'queries'            => [],
689
                    'mutations'          => [],
690
                    'fragments'          => [],
691
                    'fragmentReferences' => [],
692
                    'variables'          => [],
693
                    'variableReferences' => [],
694
                ],
695
            ],
696
            [
697
                'query test {}',
698
                [
699
                    'queries'            => [],
700
                    'mutations'          => [],
701
                    'fragments'          => [],
702
                    'fragmentReferences' => [],
703
                    'variables'          => [],
704
                    'variableReferences' => [],
705
                ],
706
            ],
707
            [
708
                'query {}',
709
                [
710
                    'queries'            => [],
711
                    'mutations'          => [],
712
                    'fragments'          => [],
713
                    'fragmentReferences' => [],
714
                    'variables'          => [],
715
                    'variableReferences' => [],
716
                ],
717
            ],
718
            [
719
                'mutation setName { setUserName }',
720
                [
721
                    'queries'            => [],
722
                    'mutations'          => [new Mutation('setUserName', null, [], [], [], new Location(1, 20))],
723
                    'fragments'          => [],
724
                    'fragmentReferences' => [],
725
                    'variables'          => [],
726
                    'variableReferences' => [],
727
                ],
728
            ],
729
            [
730
                '{ test { ...userDataFragment } } fragment userDataFragment on User { id, name, email }',
731
                [
732
                    'queries' => [
733
                        new Query('test', null, [], [new FragmentReference('userDataFragment', new Location(1, 13))], [], new Location(1, 3)),
734
                    ],
735
                    'mutations' => [],
736
                    'fragments' => [
737
                        new Fragment('userDataFragment', 'User', [], [
738
                            new Field('id', null, [], [], new Location(1, 70)),
739
                            new Field('name', null, [], [], new Location(1, 74)),
740
                            new Field('email', null, [], [], new Location(1, 80)),
741
                        ], new Location(1, 43)),
742
                    ],
743
                    'fragmentReferences' => [
744
                        new FragmentReference('userDataFragment', new Location(1, 13)),
745
                    ],
746
                    'variables'          => [],
747
                    'variableReferences' => [],
748
                ],
749
            ],
750
            [
751
                '{ user (id: 10, name: "max", float: 123.123 ) { id, name } }',
752
                [
753
                    'queries' => [
754
                        new Query(
755
                            'user',
756
                            null,
757
                            [
758
                                new Argument('id', new Literal('10', new Location(1, 13)), new Location(1, 9)),
759
                                new Argument('name', new Literal('max', new Location(1, 24)), new Location(1, 17)),
760
                                new Argument('float', new Literal('123.123', new Location(1, 37)), new Location(1, 30)),
761
                            ],
762
                            [
763
                                new Field('id', null, [], [], new Location(1, 49)),
764
                                new Field('name', null, [], [], new Location(1, 53)),
765
                            ],
766
                            [],
767
                            new Location(1, 3)
768
                        ),
769
                    ],
770
                    'mutations'          => [],
771
                    'fragments'          => [],
772
                    'fragmentReferences' => [],
773
                    'variables'          => [],
774
                    'variableReferences' => [],
775
                ],
776
            ],
777
            [
778
                '{ allUsers : users ( id: [ 1, 2, 3] ) { id } }',
779
                [
780
                    'queries' => [
781
                        new Query(
782
                            'users',
783
                            'allUsers',
784
                            [
785
                                new Argument('id', new InputList([1, 2, 3], new Location(1, 26)), new Location(1, 22)),
786
                            ],
787
                            [
788
                                new Field('id', null, [], [], new Location(1, 41)),
789
                            ],
790
                            [],
791
                            new Location(1, 14)
792
                        ),
793
                    ],
794
                    'mutations'          => [],
795
                    'fragments'          => [],
796
                    'fragmentReferences' => [],
797
                    'variables'          => [],
798
                    'variableReferences' => [],
799
                ],
800
            ],
801
            [
802
                '{ allUsers : users ( id: [ 1, "2", true, null] ) { id } }',
803
                [
804
                    'queries' => [
805
                        new Query(
806
                            'users',
807
                            'allUsers',
808
                            [
809
                                new Argument('id', new InputList([1, '2', true, null], new Location(1, 26)), new Location(1, 22)),
810
                            ],
811
                            [
812
                                new Field('id', null, [], [], new Location(1, 52)),
813
                            ],
814
                            [],
815
                            new Location(1, 14)
816
                        ),
817
                    ],
818
                    'mutations'          => [],
819
                    'fragments'          => [],
820
                    'fragmentReferences' => [],
821
                    'variables'          => [],
822
                    'variableReferences' => [],
823
                ],
824
            ],
825
            [
826
                '{ allUsers : users ( object: { "a": 123, "d": "asd",  "b" : [ 1, 2, 4 ], "c": { "a" : 123, "b":  "asd" } } ) { id } }',
827
                [
828
                    'queries' => [
829
                        new Query(
830
                            'users',
831
                            'allUsers',
832
                            [
833
                                new Argument('object', new InputObject([
834
                                    'a' => 123,
835
                                    'd' => 'asd',
836
                                    'b' => [1, 2, 4],
837
                                    'c' => new InputObject([
838
                                        'a' => 123,
839
                                        'b' => 'asd',
840
                                    ], new Location(1, 79)),
841
                                ], new Location(1, 30)), new Location(1, 22)),
842
                            ],
843
                            [
844
                                new Field('id', null, [], [], new Location(1, 112)),
845
                            ],
846
                            [],
847
                            new Location(1, 14)
848
                        ),
849
                    ],
850
                    'mutations'          => [],
851
                    'fragments'          => [],
852
                    'fragmentReferences' => [],
853
                    'variables'          => [],
854
                    'variableReferences' => [],
855
                ],
856
            ],
857
        ];
858
    }
859
860
    public function testVariablesInQuery(): void
861
    {
862
        $parser = new Parser();
863
864
        $data = $parser->parse('
865
            query StarWarsAppHomeRoute($names_0:[String!]!, $query: String) {
866
              factions(names:$names_0, test: $query) {
867
                id,
868
                ...F2
869
              }
870
            }
871
            fragment F0 on Ship {
872
              id,
873
              name
874
            }
875
            fragment F1 on Faction {
876
              id,
877
              factionId
878
            }
879
            fragment F2 on Faction {
880
              id,
881
              factionId,
882
              name,
883
              _shipsDRnzJ:ships(first:10) {
884
                edges {
885
                  node {
886
                    id,
887
                    ...F0
888
                  },
889
                  cursor
890
                },
891
                pageInfo {
892
                  hasNextPage,
893
                  hasPreviousPage
894
                }
895
              },
896
              ...F1
897
            }
898
        ');
899
900
        $this->assertArrayNotHasKey('errors', $data);
901
    }
902
903
    public function testVariableDefaultValue(): void
904
    {
905
        $parser          = new Parser();
906
        $parsedStructure = $parser->parse('
907
            query ($format: String = "small"){
908
              user {
909
                avatar(format: $format)
910
              }
911
            }
912
        ');
913
        /** @var Variable $var */
914
        $var = $parsedStructure['variables'][0];
915
        $this->assertTrue($var->hasDefaultValue());
916
        $this->assertEquals('small', $var->getDefaultValue()->getValue());
917
        $this->assertEquals('small', $var->getValue()->getValue());
918
    }
919
920
    private function tokenizeStringContents($graphQLString)
921
    {
922
        $parser = new TokenizerTestingParser();
923
        $parser->initTokenizerForTesting('"' . $graphQLString . '"');
924
925
        return $parser->getTokenForTesting();
926
    }
927
}
928