Completed
Push — master ( ea011c...446fa9 )
by Vladimir
55s queued 51s
created

SchemaPrinterTest::testPrintIntrospectionSchema()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 240
Code Lines 235

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 235
c 3
b 0
f 0
dl 0
loc 240
rs 8
cc 1
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Tests\Utils;
6
7
use GraphQL\Language\DirectiveLocation;
8
use GraphQL\Type\Definition\CustomScalarType;
9
use GraphQL\Type\Definition\Directive;
10
use GraphQL\Type\Definition\EnumType;
11
use GraphQL\Type\Definition\InputObjectType;
12
use GraphQL\Type\Definition\InterfaceType;
13
use GraphQL\Type\Definition\ObjectType;
14
use GraphQL\Type\Definition\Type;
15
use GraphQL\Type\Definition\UnionType;
16
use GraphQL\Type\Schema;
17
use GraphQL\Utils\BuildSchema;
18
use GraphQL\Utils\SchemaPrinter;
19
use PHPUnit\Framework\TestCase;
20
21
class SchemaPrinterTest extends TestCase
22
{
23
    // Describe: Type System Printer
24
    /**
25
     * @see it('Prints String Field')
26
     */
27
    public function testPrintsStringField() : void
28
    {
29
        $output = $this->printSingleFieldSchema([
30
            'type' => Type::string(),
31
        ]);
32
        self::assertEquals(
33
            '
34
type Query {
35
  singleField: String
36
}
37
',
38
            $output
39
        );
40
    }
41
42
    private function printSingleFieldSchema($fieldConfig)
43
    {
44
        $query = new ObjectType([
45
            'name'   => 'Query',
46
            'fields' => ['singleField' => $fieldConfig],
47
        ]);
48
49
        return $this->printForTest(new Schema(['query' => $query]));
50
    }
51
52
    private function printForTest($schema)
53
    {
54
        $schemaText = SchemaPrinter::doPrint($schema);
55
        self::assertEquals($schemaText, SchemaPrinter::doPrint(BuildSchema::build($schemaText)));
56
57
        return "\n" . $schemaText;
58
    }
59
60
    /**
61
     * @see it('Prints [String] Field')
62
     */
63
    public function testPrintArrayStringField() : void
64
    {
65
        $output = $this->printSingleFieldSchema([
66
            'type' => Type::listOf(Type::string()),
67
        ]);
68
        self::assertEquals(
69
            '
70
type Query {
71
  singleField: [String]
72
}
73
',
74
            $output
75
        );
76
    }
77
78
    /**
79
     * @see it('Prints String! Field')
80
     */
81
    public function testPrintNonNullStringField() : void
82
    {
83
        $output = $this->printSingleFieldSchema([
84
            'type' => Type::nonNull(Type::string()),
85
        ]);
86
        self::assertEquals(
87
            '
88
type Query {
89
  singleField: String!
90
}
91
',
92
            $output
93
        );
94
    }
95
96
    /**
97
     * @see it('Prints [String]! Field')
98
     */
99
    public function testPrintNonNullArrayStringField() : void
100
    {
101
        $output = $this->printSingleFieldSchema([
102
            'type' => Type::nonNull(Type::listOf(Type::string())),
103
        ]);
104
        self::assertEquals(
105
            '
106
type Query {
107
  singleField: [String]!
108
}
109
',
110
            $output
111
        );
112
    }
113
114
    /**
115
     * @see it('Prints [String!] Field')
116
     */
117
    public function testPrintArrayNonNullStringField() : void
118
    {
119
        $output = $this->printSingleFieldSchema([
120
            'type' => Type::listOf(Type::nonNull(Type::string())),
121
        ]);
122
        self::assertEquals(
123
            '
124
type Query {
125
  singleField: [String!]
126
}
127
',
128
            $output
129
        );
130
    }
131
132
    /**
133
     * @see it('Prints [String!]! Field')
134
     */
135
    public function testPrintNonNullArrayNonNullStringField() : void
136
    {
137
        $output = $this->printSingleFieldSchema([
138
            'type' => Type::nonNull(Type::listOf(Type::nonNull(Type::string()))),
139
        ]);
140
        self::assertEquals(
141
            '
142
type Query {
143
  singleField: [String!]!
144
}
145
',
146
            $output
147
        );
148
    }
149
150
    /**
151
     * @see it('Print Object Field')
152
     */
153
    public function testPrintObjectField() : void
154
    {
155
        $fooType = new ObjectType([
156
            'name'   => 'Foo',
157
            'fields' => ['str' => ['type' => Type::string()]],
158
        ]);
159
160
        $root = new ObjectType([
161
            'name'   => 'Query',
162
            'fields' => ['foo' => ['type' => $fooType]],
163
        ]);
164
165
        $schema = new Schema(['query' => $root]);
166
        $output = $this->printForTest($schema);
167
        self::assertEquals(
168
            '
169
type Foo {
170
  str: String
171
}
172
173
type Query {
174
  foo: Foo
175
}
176
',
177
            $output
178
        );
179
    }
180
181
    /**
182
     * @see it('Prints String Field With Int Arg')
183
     */
184
    public function testPrintsStringFieldWithIntArg() : void
185
    {
186
        $output = $this->printSingleFieldSchema([
187
            'type' => Type::string(),
188
            'args' => ['argOne' => ['type' => Type::int()]],
189
        ]);
190
        self::assertEquals(
191
            '
192
type Query {
193
  singleField(argOne: Int): String
194
}
195
',
196
            $output
197
        );
198
    }
199
200
    /**
201
     * @see it('Prints String Field With Int Arg With Default')
202
     */
203
    public function testPrintsStringFieldWithIntArgWithDefault() : void
204
    {
205
        $output = $this->printSingleFieldSchema([
206
            'type' => Type::string(),
207
            'args' => ['argOne' => ['type' => Type::int(), 'defaultValue' => 2]],
208
        ]);
209
        self::assertEquals(
210
            '
211
type Query {
212
  singleField(argOne: Int = 2): String
213
}
214
',
215
            $output
216
        );
217
    }
218
219
    /**
220
     * @see it('Prints String Field With String Arg With Default')
221
     */
222
    public function testPrintsStringFieldWithStringArgWithDefault() : void
223
    {
224
        $output = $this->printSingleFieldSchema([
225
            'type' => Type::string(),
226
            'args' => ['argOne' => ['type' => Type::string(), 'defaultValue' => "tes\t de\fault"]],
227
        ]);
228
        self::assertEquals(
229
            '
230
type Query {
231
  singleField(argOne: String = "tes\t de\fault"): String
232
}
233
',
234
            $output
235
        );
236
    }
237
238
    /**
239
     * @see it('Prints String Field With Int Arg With Default Null')
240
     */
241
    public function testPrintsStringFieldWithIntArgWithDefaultNull() : void
242
    {
243
        $output = $this->printSingleFieldSchema([
244
            'type' => Type::string(),
245
            'args' => ['argOne' => ['type' => Type::int(), 'defaultValue' => null]],
246
        ]);
247
        self::assertEquals(
248
            '
249
type Query {
250
  singleField(argOne: Int = null): String
251
}
252
',
253
            $output
254
        );
255
    }
256
257
    /**
258
     * @see it('Prints String Field With Int! Arg')
259
     */
260
    public function testPrintsStringFieldWithNonNullIntArg() : void
261
    {
262
        $output = $this->printSingleFieldSchema([
263
            'type' => Type::string(),
264
            'args' => ['argOne' => ['type' => Type::nonNull(Type::int())]],
265
        ]);
266
        self::assertEquals(
267
            '
268
type Query {
269
  singleField(argOne: Int!): String
270
}
271
',
272
            $output
273
        );
274
    }
275
276
    /**
277
     * @see it('Prints String Field With Multiple Args')
278
     */
279
    public function testPrintsStringFieldWithMultipleArgs() : void
280
    {
281
        $output = $this->printSingleFieldSchema([
282
            'type' => Type::string(),
283
            'args' => [
284
                'argOne' => ['type' => Type::int()],
285
                'argTwo' => ['type' => Type::string()],
286
            ],
287
        ]);
288
        self::assertEquals(
289
            '
290
type Query {
291
  singleField(argOne: Int, argTwo: String): String
292
}
293
',
294
            $output
295
        );
296
    }
297
298
    /**
299
     * @see it('Prints String Field With Multiple Args, First is Default')
300
     */
301
    public function testPrintsStringFieldWithMultipleArgsFirstIsDefault() : void
302
    {
303
        $output = $this->printSingleFieldSchema([
304
            'type' => Type::string(),
305
            'args' => [
306
                'argOne'   => ['type' => Type::int(), 'defaultValue' => 1],
307
                'argTwo'   => ['type' => Type::string()],
308
                'argThree' => ['type' => Type::boolean()],
309
            ],
310
        ]);
311
        self::assertEquals(
312
            '
313
type Query {
314
  singleField(argOne: Int = 1, argTwo: String, argThree: Boolean): String
315
}
316
',
317
            $output
318
        );
319
    }
320
321
    /**
322
     * @see it('Prints String Field With Multiple Args, Second is Default')
323
     */
324
    public function testPrintsStringFieldWithMultipleArgsSecondIsDefault() : void
325
    {
326
        $output = $this->printSingleFieldSchema([
327
            'type' => Type::string(),
328
            'args' => [
329
                'argOne'   => ['type' => Type::int()],
330
                'argTwo'   => ['type' => Type::string(), 'defaultValue' => 'foo'],
331
                'argThree' => ['type' => Type::boolean()],
332
            ],
333
        ]);
334
        self::assertEquals(
335
            '
336
type Query {
337
  singleField(argOne: Int, argTwo: String = "foo", argThree: Boolean): String
338
}
339
',
340
            $output
341
        );
342
    }
343
344
    /**
345
     * @see it('Prints String Field With Multiple Args, Last is Default')
346
     */
347
    public function testPrintsStringFieldWithMultipleArgsLastIsDefault() : void
348
    {
349
        $output = $this->printSingleFieldSchema([
350
            'type' => Type::string(),
351
            'args' => [
352
                'argOne'   => ['type' => Type::int()],
353
                'argTwo'   => ['type' => Type::string()],
354
                'argThree' => ['type' => Type::boolean(), 'defaultValue' => false],
355
            ],
356
        ]);
357
        self::assertEquals(
358
            '
359
type Query {
360
  singleField(argOne: Int, argTwo: String, argThree: Boolean = false): String
361
}
362
',
363
            $output
364
        );
365
    }
366
367
    /**
368
     * @see it('Prints custom query root type')
369
     */
370
    public function testPrintsCustomQueryRootType() : void
371
    {
372
        $customQueryType = new ObjectType([
373
            'name'   => 'CustomQueryType',
374
            'fields' => ['bar' => ['type' => Type::string()]],
375
        ]);
376
377
        $schema   = new Schema(['query' => $customQueryType]);
378
        $output   = $this->printForTest($schema);
379
        $expected = '
380
schema {
381
  query: CustomQueryType
382
}
383
384
type CustomQueryType {
385
  bar: String
386
}
387
';
388
        self::assertEquals($expected, $output);
389
    }
390
391
    /**
392
     * @see it('Print Interface')
393
     */
394
    public function testPrintInterface() : void
395
    {
396
        $fooType = new InterfaceType([
397
            'name'   => 'Foo',
398
            'fields' => ['str' => ['type' => Type::string()]],
399
        ]);
400
401
        $barType = new ObjectType([
402
            'name'       => 'Bar',
403
            'fields'     => ['str' => ['type' => Type::string()]],
404
            'interfaces' => [$fooType],
405
        ]);
406
407
        $query = new ObjectType([
408
            'name'   => 'Query',
409
            'fields' => ['bar' => ['type' => $barType]],
410
        ]);
411
412
        $schema = new Schema([
413
            'query' => $query,
414
            'types' => [$barType],
415
        ]);
416
        $output = $this->printForTest($schema);
417
        self::assertEquals(
418
            '
419
type Bar implements Foo {
420
  str: String
421
}
422
423
interface Foo {
424
  str: String
425
}
426
427
type Query {
428
  bar: Bar
429
}
430
',
431
            $output
432
        );
433
    }
434
435
    /**
436
     * @see it('Print Multiple Interface')
437
     */
438
    public function testPrintMultipleInterface() : void
439
    {
440
        $fooType = new InterfaceType([
441
            'name'   => 'Foo',
442
            'fields' => ['str' => ['type' => Type::string()]],
443
        ]);
444
445
        $baazType = new InterfaceType([
446
            'name'   => 'Baaz',
447
            'fields' => ['int' => ['type' => Type::int()]],
448
        ]);
449
450
        $barType = new ObjectType([
451
            'name'       => 'Bar',
452
            'fields'     => [
453
                'str' => ['type' => Type::string()],
454
                'int' => ['type' => Type::int()],
455
            ],
456
            'interfaces' => [$fooType, $baazType],
457
        ]);
458
459
        $query = new ObjectType([
460
            'name'   => 'Query',
461
            'fields' => ['bar' => ['type' => $barType]],
462
        ]);
463
464
        $schema = new Schema([
465
            'query' => $query,
466
            'types' => [$barType],
467
        ]);
468
        $output = $this->printForTest($schema);
469
        self::assertEquals(
470
            '
471
interface Baaz {
472
  int: Int
473
}
474
475
type Bar implements Foo & Baaz {
476
  str: String
477
  int: Int
478
}
479
480
interface Foo {
481
  str: String
482
}
483
484
type Query {
485
  bar: Bar
486
}
487
',
488
            $output
489
        );
490
    }
491
492
    /**
493
     * @see it('Print Unions')
494
     */
495
    public function testPrintUnions() : void
496
    {
497
        $fooType = new ObjectType([
498
            'name'   => 'Foo',
499
            'fields' => ['bool' => ['type' => Type::boolean()]],
500
        ]);
501
502
        $barType = new ObjectType([
503
            'name'   => 'Bar',
504
            'fields' => ['str' => ['type' => Type::string()]],
505
        ]);
506
507
        $singleUnion = new UnionType([
508
            'name'  => 'SingleUnion',
509
            'types' => [$fooType],
510
        ]);
511
512
        $multipleUnion = new UnionType([
513
            'name'  => 'MultipleUnion',
514
            'types' => [$fooType, $barType],
515
        ]);
516
517
        $query = new ObjectType([
518
            'name'   => 'Query',
519
            'fields' => [
520
                'single'   => ['type' => $singleUnion],
521
                'multiple' => ['type' => $multipleUnion],
522
            ],
523
        ]);
524
525
        $schema = new Schema(['query' => $query]);
526
        $output = $this->printForTest($schema);
527
        self::assertEquals(
528
            '
529
type Bar {
530
  str: String
531
}
532
533
type Foo {
534
  bool: Boolean
535
}
536
537
union MultipleUnion = Foo | Bar
538
539
type Query {
540
  single: SingleUnion
541
  multiple: MultipleUnion
542
}
543
544
union SingleUnion = Foo
545
',
546
            $output
547
        );
548
    }
549
550
    /**
551
     * @see it('Print Input Type')
552
     */
553
    public function testInputType() : void
554
    {
555
        $inputType = new InputObjectType([
556
            'name'   => 'InputType',
557
            'fields' => ['int' => ['type' => Type::int()]],
558
        ]);
559
560
        $query = new ObjectType([
561
            'name'   => 'Query',
562
            'fields' => [
563
                'str' => [
564
                    'type' => Type::string(),
565
                    'args' => ['argOne' => ['type' => $inputType]],
566
                ],
567
            ],
568
        ]);
569
570
        $schema = new Schema(['query' => $query]);
571
        $output = $this->printForTest($schema);
572
        self::assertEquals(
573
            '
574
input InputType {
575
  int: Int
576
}
577
578
type Query {
579
  str(argOne: InputType): String
580
}
581
',
582
            $output
583
        );
584
    }
585
586
    /**
587
     * @see it('Custom Scalar')
588
     */
589
    public function testCustomScalar() : void
590
    {
591
        $oddType = new CustomScalarType([
592
            'name'      => 'Odd',
593
            'serialize' => static function ($value) {
594
                return $value % 2 === 1 ? $value : null;
595
            },
596
        ]);
597
598
        $query = new ObjectType([
599
            'name'   => 'Query',
600
            'fields' => [
601
                'odd' => ['type' => $oddType],
602
            ],
603
        ]);
604
605
        $schema = new Schema(['query' => $query]);
606
        $output = $this->printForTest($schema);
607
        self::assertEquals(
608
            '
609
scalar Odd
610
611
type Query {
612
  odd: Odd
613
}
614
',
615
            $output
616
        );
617
    }
618
619
    /**
620
     * @see it('Enum')
621
     */
622
    public function testEnum() : void
623
    {
624
        $RGBType = new EnumType([
625
            'name'   => 'RGB',
626
            'values' => [
627
                'RED'   => ['value' => 0],
628
                'GREEN' => ['value' => 1],
629
                'BLUE'  => ['value' => 2],
630
            ],
631
        ]);
632
633
        $query = new ObjectType([
634
            'name'   => 'Query',
635
            'fields' => [
636
                'rgb' => ['type' => $RGBType],
637
            ],
638
        ]);
639
640
        $schema = new Schema(['query' => $query]);
641
        $output = $this->printForTest($schema);
642
        self::assertEquals(
643
            '
644
type Query {
645
  rgb: RGB
646
}
647
648
enum RGB {
649
  RED
650
  GREEN
651
  BLUE
652
}
653
',
654
            $output
655
        );
656
    }
657
658
    /**
659
     * @see it('Prints custom directives')
660
     */
661
    public function testPrintsCustomDirectives() : void
662
    {
663
        $query = new ObjectType([
664
            'name'   => 'Query',
665
            'fields' => [
666
                'field' => ['type' => Type::string()],
667
            ],
668
        ]);
669
670
        $customDirectives = new Directive([
671
            'name'      => 'customDirective',
672
            'locations' => [
673
                DirectiveLocation::FIELD,
674
            ],
675
        ]);
676
677
        $schema = new Schema([
678
            'query'      => $query,
679
            'directives' => [$customDirectives],
680
        ]);
681
682
        $output = $this->printForTest($schema);
683
        self::assertEquals(
684
            '
685
directive @customDirective on FIELD
686
687
type Query {
688
  field: String
689
}
690
',
691
            $output
692
        );
693
    }
694
695
    /**
696
     * @see it('One-line prints a short description')
697
     */
698
    public function testOneLinePrintsAShortDescription() : void
699
    {
700
        $description = 'This field is awesome';
701
        $output      = $this->printSingleFieldSchema([
702
            'type'        => Type::string(),
703
            'description' => $description,
704
        ]);
705
706
        self::assertEquals(
707
            '
708
type Query {
709
  """This field is awesome"""
710
  singleField: String
711
}
712
',
713
            $output
714
        );
715
716
        /** @var ObjectType $recreatedRoot */
717
        $recreatedRoot  = BuildSchema::build($output)->getTypeMap()['Query'];
718
        $recreatedField = $recreatedRoot->getFields()['singleField'];
719
        self::assertEquals($description, $recreatedField->description);
720
    }
721
722
    /**
723
     * @see it('Does not one-line print a description that ends with a quote')
724
     */
725
    public function testDoesNotOneLinePrintADescriptionThatEndsWithAQuote() : void
726
    {
727
        $description = 'This field is "awesome"';
728
        $output      = $this->printSingleFieldSchema([
729
            'type'        => Type::string(),
730
            'description' => $description,
731
        ]);
732
733
        self::assertEquals(
734
            '
735
type Query {
736
  """
737
  This field is "awesome"
738
  """
739
  singleField: String
740
}
741
',
742
            $output
743
        );
744
745
        /** @var ObjectType $recreatedRoot */
746
        $recreatedRoot  = BuildSchema::build($output)->getTypeMap()['Query'];
747
        $recreatedField = $recreatedRoot->getFields()['singleField'];
748
        self::assertEquals($description, $recreatedField->description);
749
    }
750
751
    /**
752
     * @see it('Preserves leading spaces when printing a description')
753
     */
754
    public function testPReservesLeadingSpacesWhenPrintingADescription() : void
755
    {
756
        $description = '    This field is "awesome"';
757
        $output      = $this->printSingleFieldSchema([
758
            'type'        => Type::string(),
759
            'description' => $description,
760
        ]);
761
762
        self::assertEquals(
763
            '
764
type Query {
765
  """    This field is "awesome"
766
  """
767
  singleField: String
768
}
769
',
770
            $output
771
        );
772
773
        /** @var ObjectType $recreatedRoot */
774
        $recreatedRoot  = BuildSchema::build($output)->getTypeMap()['Query'];
775
        $recreatedField = $recreatedRoot->getFields()['singleField'];
776
        self::assertEquals($description, $recreatedField->description);
777
    }
778
779
    /**
780
     * @see it('Print Introspection Schema')
781
     */
782
    public function testPrintIntrospectionSchema() : void
783
    {
784
        $query = new ObjectType([
785
            'name'   => 'Query',
786
            'fields' => [
787
                'onlyField' => ['type' => Type::string()],
788
            ],
789
        ]);
790
791
        $schema              = new Schema(['query' => $query]);
792
        $output              = SchemaPrinter::printIntrospectionSchema($schema);
793
        $introspectionSchema = <<<'EOT'
794
"""
795
Directs the executor to include this field or fragment only when the `if` argument is true.
796
"""
797
directive @include(
798
  """Included when true."""
799
  if: Boolean!
800
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
801
802
"""
803
Directs the executor to skip this field or fragment when the `if` argument is true.
804
"""
805
directive @skip(
806
  """Skipped when true."""
807
  if: Boolean!
808
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
809
810
"""Marks an element of a GraphQL schema as no longer supported."""
811
directive @deprecated(
812
  """
813
  Explains why this element was deprecated, usually also including a suggestion
814
  for how to access supported similar data. Formatted in
815
  [Markdown](https://daringfireball.net/projects/markdown/).
816
  """
817
  reason: String = "No longer supported"
818
) on FIELD_DEFINITION | ENUM_VALUE
819
820
"""
821
A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.
822
823
In some cases, you need to provide options to alter GraphQL's execution behavior
824
in ways field arguments will not suffice, such as conditionally including or
825
skipping a field. Directives provide this by describing additional information
826
to the executor.
827
"""
828
type __Directive {
829
  name: String!
830
  description: String
831
  locations: [__DirectiveLocation!]!
832
  args: [__InputValue!]!
833
}
834
835
"""
836
A Directive can be adjacent to many parts of the GraphQL language, a
837
__DirectiveLocation describes one such possible adjacencies.
838
"""
839
enum __DirectiveLocation {
840
  """Location adjacent to a query operation."""
841
  QUERY
842
843
  """Location adjacent to a mutation operation."""
844
  MUTATION
845
846
  """Location adjacent to a subscription operation."""
847
  SUBSCRIPTION
848
849
  """Location adjacent to a field."""
850
  FIELD
851
852
  """Location adjacent to a fragment definition."""
853
  FRAGMENT_DEFINITION
854
855
  """Location adjacent to a fragment spread."""
856
  FRAGMENT_SPREAD
857
858
  """Location adjacent to an inline fragment."""
859
  INLINE_FRAGMENT
860
861
  """Location adjacent to a variable definition."""
862
  VARIABLE_DEFINITION
863
864
  """Location adjacent to a schema definition."""
865
  SCHEMA
866
867
  """Location adjacent to a scalar definition."""
868
  SCALAR
869
870
  """Location adjacent to an object type definition."""
871
  OBJECT
872
873
  """Location adjacent to a field definition."""
874
  FIELD_DEFINITION
875
876
  """Location adjacent to an argument definition."""
877
  ARGUMENT_DEFINITION
878
879
  """Location adjacent to an interface definition."""
880
  INTERFACE
881
882
  """Location adjacent to a union definition."""
883
  UNION
884
885
  """Location adjacent to an enum definition."""
886
  ENUM
887
888
  """Location adjacent to an enum value definition."""
889
  ENUM_VALUE
890
891
  """Location adjacent to an input object type definition."""
892
  INPUT_OBJECT
893
894
  """Location adjacent to an input object field definition."""
895
  INPUT_FIELD_DEFINITION
896
}
897
898
"""
899
One possible value for a given Enum. Enum values are unique values, not a
900
placeholder for a string or numeric value. However an Enum value is returned in
901
a JSON response as a string.
902
"""
903
type __EnumValue {
904
  name: String!
905
  description: String
906
  isDeprecated: Boolean!
907
  deprecationReason: String
908
}
909
910
"""
911
Object and Interface types are described by a list of Fields, each of which has
912
a name, potentially a list of arguments, and a return type.
913
"""
914
type __Field {
915
  name: String!
916
  description: String
917
  args: [__InputValue!]!
918
  type: __Type!
919
  isDeprecated: Boolean!
920
  deprecationReason: String
921
}
922
923
"""
924
Arguments provided to Fields or Directives and the input fields of an
925
InputObject are represented as Input Values which describe their type and
926
optionally a default value.
927
"""
928
type __InputValue {
929
  name: String!
930
  description: String
931
  type: __Type!
932
933
  """
934
  A GraphQL-formatted string representing the default value for this input value.
935
  """
936
  defaultValue: String
937
}
938
939
"""
940
A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all
941
available types and directives on the server, as well as the entry points for
942
query, mutation, and subscription operations.
943
"""
944
type __Schema {
945
  """A list of all types supported by this server."""
946
  types: [__Type!]!
947
948
  """The type that query operations will be rooted at."""
949
  queryType: __Type!
950
951
  """
952
  If this server supports mutation, the type that mutation operations will be rooted at.
953
  """
954
  mutationType: __Type
955
956
  """
957
  If this server support subscription, the type that subscription operations will be rooted at.
958
  """
959
  subscriptionType: __Type
960
961
  """A list of all directives supported by this server."""
962
  directives: [__Directive!]!
963
}
964
965
"""
966
The fundamental unit of any GraphQL Schema is the type. There are many kinds of
967
types in GraphQL as represented by the `__TypeKind` enum.
968
969
Depending on the kind of a type, certain fields describe information about that
970
type. Scalar types provide no information beyond a name and description, while
971
Enum types provide their values. Object and Interface types provide the fields
972
they describe. Abstract types, Union and Interface, provide the Object types
973
possible at runtime. List and NonNull types compose other types.
974
"""
975
type __Type {
976
  kind: __TypeKind!
977
  name: String
978
  description: String
979
  fields(includeDeprecated: Boolean = false): [__Field!]
980
  interfaces: [__Type!]
981
  possibleTypes: [__Type!]
982
  enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
983
  inputFields: [__InputValue!]
984
  ofType: __Type
985
}
986
987
"""An enum describing what kind of type a given `__Type` is."""
988
enum __TypeKind {
989
  """Indicates this type is a scalar."""
990
  SCALAR
991
992
  """
993
  Indicates this type is an object. `fields` and `interfaces` are valid fields.
994
  """
995
  OBJECT
996
997
  """
998
  Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.
999
  """
1000
  INTERFACE
1001
1002
  """Indicates this type is a union. `possibleTypes` is a valid field."""
1003
  UNION
1004
1005
  """Indicates this type is an enum. `enumValues` is a valid field."""
1006
  ENUM
1007
1008
  """
1009
  Indicates this type is an input object. `inputFields` is a valid field.
1010
  """
1011
  INPUT_OBJECT
1012
1013
  """Indicates this type is a list. `ofType` is a valid field."""
1014
  LIST
1015
1016
  """Indicates this type is a non-null. `ofType` is a valid field."""
1017
  NON_NULL
1018
}
1019
1020
EOT;
1021
        self::assertEquals($introspectionSchema, $output);
1022
    }
1023
1024
    /**
1025
     * @see it('Print Introspection Schema with comment descriptions')
1026
     */
1027
    public function testPrintIntrospectionSchemaWithCommentDescriptions() : void
1028
    {
1029
        $query = new ObjectType([
1030
            'name'   => 'Query',
1031
            'fields' => [
1032
                'onlyField' => ['type' => Type::string()],
1033
            ],
1034
        ]);
1035
1036
        $schema              = new Schema(['query' => $query]);
1037
        $output              = SchemaPrinter::printIntrospectionSchema(
1038
            $schema,
1039
            ['commentDescriptions' => true]
1040
        );
1041
        $introspectionSchema = <<<'EOT'
1042
# Directs the executor to include this field or fragment only when the `if` argument is true.
1043
directive @include(
1044
  # Included when true.
1045
  if: Boolean!
1046
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
1047
1048
# Directs the executor to skip this field or fragment when the `if` argument is true.
1049
directive @skip(
1050
  # Skipped when true.
1051
  if: Boolean!
1052
) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
1053
1054
# Marks an element of a GraphQL schema as no longer supported.
1055
directive @deprecated(
1056
  # Explains why this element was deprecated, usually also including a suggestion
1057
  # for how to access supported similar data. Formatted in
1058
  # [Markdown](https://daringfireball.net/projects/markdown/).
1059
  reason: String = "No longer supported"
1060
) on FIELD_DEFINITION | ENUM_VALUE
1061
1062
# A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.
1063
#
1064
# In some cases, you need to provide options to alter GraphQL's execution behavior
1065
# in ways field arguments will not suffice, such as conditionally including or
1066
# skipping a field. Directives provide this by describing additional information
1067
# to the executor.
1068
type __Directive {
1069
  name: String!
1070
  description: String
1071
  locations: [__DirectiveLocation!]!
1072
  args: [__InputValue!]!
1073
}
1074
1075
# A Directive can be adjacent to many parts of the GraphQL language, a
1076
# __DirectiveLocation describes one such possible adjacencies.
1077
enum __DirectiveLocation {
1078
  # Location adjacent to a query operation.
1079
  QUERY
1080
1081
  # Location adjacent to a mutation operation.
1082
  MUTATION
1083
1084
  # Location adjacent to a subscription operation.
1085
  SUBSCRIPTION
1086
1087
  # Location adjacent to a field.
1088
  FIELD
1089
1090
  # Location adjacent to a fragment definition.
1091
  FRAGMENT_DEFINITION
1092
1093
  # Location adjacent to a fragment spread.
1094
  FRAGMENT_SPREAD
1095
1096
  # Location adjacent to an inline fragment.
1097
  INLINE_FRAGMENT
1098
1099
  # Location adjacent to a variable definition.
1100
  VARIABLE_DEFINITION
1101
1102
  # Location adjacent to a schema definition.
1103
  SCHEMA
1104
1105
  # Location adjacent to a scalar definition.
1106
  SCALAR
1107
1108
  # Location adjacent to an object type definition.
1109
  OBJECT
1110
1111
  # Location adjacent to a field definition.
1112
  FIELD_DEFINITION
1113
1114
  # Location adjacent to an argument definition.
1115
  ARGUMENT_DEFINITION
1116
1117
  # Location adjacent to an interface definition.
1118
  INTERFACE
1119
1120
  # Location adjacent to a union definition.
1121
  UNION
1122
1123
  # Location adjacent to an enum definition.
1124
  ENUM
1125
1126
  # Location adjacent to an enum value definition.
1127
  ENUM_VALUE
1128
1129
  # Location adjacent to an input object type definition.
1130
  INPUT_OBJECT
1131
1132
  # Location adjacent to an input object field definition.
1133
  INPUT_FIELD_DEFINITION
1134
}
1135
1136
# One possible value for a given Enum. Enum values are unique values, not a
1137
# placeholder for a string or numeric value. However an Enum value is returned in
1138
# a JSON response as a string.
1139
type __EnumValue {
1140
  name: String!
1141
  description: String
1142
  isDeprecated: Boolean!
1143
  deprecationReason: String
1144
}
1145
1146
# Object and Interface types are described by a list of Fields, each of which has
1147
# a name, potentially a list of arguments, and a return type.
1148
type __Field {
1149
  name: String!
1150
  description: String
1151
  args: [__InputValue!]!
1152
  type: __Type!
1153
  isDeprecated: Boolean!
1154
  deprecationReason: String
1155
}
1156
1157
# Arguments provided to Fields or Directives and the input fields of an
1158
# InputObject are represented as Input Values which describe their type and
1159
# optionally a default value.
1160
type __InputValue {
1161
  name: String!
1162
  description: String
1163
  type: __Type!
1164
1165
  # A GraphQL-formatted string representing the default value for this input value.
1166
  defaultValue: String
1167
}
1168
1169
# A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all
1170
# available types and directives on the server, as well as the entry points for
1171
# query, mutation, and subscription operations.
1172
type __Schema {
1173
  # A list of all types supported by this server.
1174
  types: [__Type!]!
1175
1176
  # The type that query operations will be rooted at.
1177
  queryType: __Type!
1178
1179
  # If this server supports mutation, the type that mutation operations will be rooted at.
1180
  mutationType: __Type
1181
1182
  # If this server support subscription, the type that subscription operations will be rooted at.
1183
  subscriptionType: __Type
1184
1185
  # A list of all directives supported by this server.
1186
  directives: [__Directive!]!
1187
}
1188
1189
# The fundamental unit of any GraphQL Schema is the type. There are many kinds of
1190
# types in GraphQL as represented by the `__TypeKind` enum.
1191
#
1192
# Depending on the kind of a type, certain fields describe information about that
1193
# type. Scalar types provide no information beyond a name and description, while
1194
# Enum types provide their values. Object and Interface types provide the fields
1195
# they describe. Abstract types, Union and Interface, provide the Object types
1196
# possible at runtime. List and NonNull types compose other types.
1197
type __Type {
1198
  kind: __TypeKind!
1199
  name: String
1200
  description: String
1201
  fields(includeDeprecated: Boolean = false): [__Field!]
1202
  interfaces: [__Type!]
1203
  possibleTypes: [__Type!]
1204
  enumValues(includeDeprecated: Boolean = false): [__EnumValue!]
1205
  inputFields: [__InputValue!]
1206
  ofType: __Type
1207
}
1208
1209
# An enum describing what kind of type a given `__Type` is.
1210
enum __TypeKind {
1211
  # Indicates this type is a scalar.
1212
  SCALAR
1213
1214
  # Indicates this type is an object. `fields` and `interfaces` are valid fields.
1215
  OBJECT
1216
1217
  # Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.
1218
  INTERFACE
1219
1220
  # Indicates this type is a union. `possibleTypes` is a valid field.
1221
  UNION
1222
1223
  # Indicates this type is an enum. `enumValues` is a valid field.
1224
  ENUM
1225
1226
  # Indicates this type is an input object. `inputFields` is a valid field.
1227
  INPUT_OBJECT
1228
1229
  # Indicates this type is a list. `ofType` is a valid field.
1230
  LIST
1231
1232
  # Indicates this type is a non-null. `ofType` is a valid field.
1233
  NON_NULL
1234
}
1235
1236
EOT;
1237
        self::assertEquals($introspectionSchema, $output);
1238
    }
1239
}
1240