Passed
Pull Request — master (#586)
by Šimon
12:52
created

ValidatorTestCase::getTestSchema()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 347
Code Lines 238

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 238
c 1
b 0
f 0
dl 0
loc 347
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\Validator;
6
7
use Exception;
8
use GraphQL\Language\Parser;
9
use GraphQL\Type\Definition\CustomScalarType;
10
use GraphQL\Type\Definition\Directive;
11
use GraphQL\Type\Definition\EnumType;
12
use GraphQL\Type\Definition\InputObjectType;
13
use GraphQL\Type\Definition\InterfaceType;
14
use GraphQL\Type\Definition\ObjectType;
15
use GraphQL\Type\Definition\Type;
16
use GraphQL\Type\Definition\UnionType;
17
use GraphQL\Type\Schema;
18
use GraphQL\Validator\DocumentValidator;
19
use PHPUnit\Framework\TestCase;
20
use function array_map;
21
22
abstract class ValidatorTestCase extends TestCase
23
{
24
    protected function expectPassesRule($rule, $queryString, $options = []) : void
25
    {
26
        $this->expectValid(self::getTestSchema(), [$rule], $queryString, $options);
27
    }
28
29
    protected function expectValid($schema, $rules, $queryString, $options = []) : void
30
    {
31
        self::assertEquals(
32
            [],
33
            DocumentValidator::validate($schema, Parser::parse($queryString, $options), $rules),
34
            'Should validate'
35
        );
36
    }
37
38
    /**
39
     * @return Schema
40
     */
41
    public static function getTestSchema()
42
    {
43
        $FurColor = null;
44
45
        $Being = new InterfaceType([
46
            'name'   => 'Being',
47
            'fields' => [
48
                'name' => [
49
                    'type' => Type::string(),
50
                    'args' => ['surname' => ['type' => Type::boolean()]],
51
                ],
52
            ],
53
        ]);
54
55
        $Pet = new InterfaceType([
56
            'name'   => 'Pet',
57
            'fields' => [
58
                'name' => [
59
                    'type' => Type::string(),
60
                    'args' => ['surname' => ['type' => Type::boolean()]],
61
                ],
62
            ],
63
        ]);
64
65
        $Canine = new InterfaceType([
66
            'name'   => 'Canine',
67
            'fields' => static function () {
68
                return [
69
                    'name' => [
70
                        'type' => Type::string(),
71
                        'args' => ['surname' => ['type' => Type::boolean()]],
72
                    ],
73
                ];
74
            },
75
        ]);
76
77
        $DogCommand = new EnumType([
78
            'name'   => 'DogCommand',
79
            'values' => [
80
                'SIT'  => ['value' => 0],
81
                'HEEL' => ['value' => 1],
82
                'DOWN' => ['value' => 2],
83
            ],
84
        ]);
85
86
        $Dog = new ObjectType([
87
            'name'       => 'Dog',
88
            'fields'     => [
89
                'name'            => [
90
                    'type' => Type::string(),
91
                    'args' => ['surname' => ['type' => Type::boolean()]],
92
                ],
93
                'nickname'        => ['type' => Type::string()],
94
                'barkVolume'      => ['type' => Type::int()],
95
                'barks'           => ['type' => Type::boolean()],
96
                'doesKnowCommand' => [
97
                    'type' => Type::boolean(),
98
                    'args' => ['dogCommand' => ['type' => $DogCommand]],
99
                ],
100
                'isHousetrained'  => [
101
                    'type' => Type::boolean(),
102
                    'args' => ['atOtherHomes' => ['type' => Type::boolean(), 'defaultValue' => true]],
103
                ],
104
                'isAtLocation'    => [
105
                    'type' => Type::boolean(),
106
                    'args' => ['x' => ['type' => Type::int()], 'y' => ['type' => Type::int()]],
107
                ],
108
            ],
109
            'interfaces' => [$Being, $Pet, $Canine],
110
        ]);
111
112
        $Cat = new ObjectType([
113
            'name'       => 'Cat',
114
            'fields'     => static function () use (&$FurColor) {
115
                return [
116
                    'name'       => [
117
                        'type' => Type::string(),
118
                        'args' => ['surname' => ['type' => Type::boolean()]],
119
                    ],
120
                    'nickname'   => ['type' => Type::string()],
121
                    'meows'      => ['type' => Type::boolean()],
122
                    'meowVolume' => ['type' => Type::int()],
123
                    'furColor'   => $FurColor,
124
                ];
125
            },
126
            'interfaces' => [$Being, $Pet],
127
        ]);
128
129
        $CatOrDog = new UnionType([
130
            'name'  => 'CatOrDog',
131
            'types' => [$Dog, $Cat],
132
        ]);
133
134
        $Intelligent = new InterfaceType([
135
            'name'   => 'Intelligent',
136
            'fields' => [
137
                'iq' => ['type' => Type::int()],
138
            ],
139
        ]);
140
141
        $Human = null;
142
        $Human = new ObjectType([
143
            'name'       => 'Human',
144
            'interfaces' => [$Being, $Intelligent],
145
            'fields'     => static function () use (&$Human, $Pet) {
146
                return [
147
                    'name'      => [
148
                        'type' => Type::string(),
149
                        'args' => ['surname' => ['type' => Type::boolean()]],
150
                    ],
151
                    'pets'      => ['type' => Type::listOf($Pet)],
152
                    'relatives' => ['type' => Type::listOf($Human)],
153
                    'iq'        => ['type' => Type::int()],
154
                ];
155
            },
156
        ]);
157
158
        $Alien = new ObjectType([
159
            'name'       => 'Alien',
160
            'interfaces' => [$Being, $Intelligent],
161
            'fields'     => [
162
                'iq'      => ['type' => Type::int()],
163
                'name'    => [
164
                    'type' => Type::string(),
165
                    'args' => ['surname' => ['type' => Type::boolean()]],
166
                ],
167
                'numEyes' => ['type' => Type::int()],
168
            ],
169
        ]);
170
171
        $DogOrHuman = new UnionType([
172
            'name'  => 'DogOrHuman',
173
            'types' => [$Dog, $Human],
174
        ]);
175
176
        $HumanOrAlien = new UnionType([
177
            'name'  => 'HumanOrAlien',
178
            'types' => [$Human, $Alien],
179
        ]);
180
181
        $FurColor = new EnumType([
182
            'name'   => 'FurColor',
183
            'values' => [
184
                'BROWN'   => ['value' => 0],
185
                'BLACK'   => ['value' => 1],
186
                'TAN'     => ['value' => 2],
187
                'SPOTTED' => ['value' => 3],
188
                'NO_FUR'  => ['value' => null],
189
            ],
190
        ]);
191
192
        $ComplexInput = new InputObjectType([
193
            'name'   => 'ComplexInput',
194
            'fields' => [
195
                'requiredField'   => ['type' => Type::nonNull(Type::boolean())],
196
                'nonNullField'    => ['type' => Type::nonNull(Type::boolean()), 'defaultValue' => false],
197
                'intField'        => ['type' => Type::int()],
198
                'stringField'     => ['type' => Type::string()],
199
                'booleanField'    => ['type' => Type::boolean()],
200
                'stringListField' => ['type' => Type::listOf(Type::string())],
201
            ],
202
        ]);
203
204
        $ComplicatedArgs = new ObjectType([
205
            'name'   => 'ComplicatedArgs',
206
            // TODO List
207
            // TODO Coercion
208
            // TODO NotNulls
209
            'fields' => [
210
                'intArgField'               => [
211
                    'type' => Type::string(),
212
                    'args' => ['intArg' => ['type' => Type::int()]],
213
                ],
214
                'nonNullIntArgField'        => [
215
                    'type' => Type::string(),
216
                    'args' => ['nonNullIntArg' => ['type' => Type::nonNull(Type::int())]],
217
                ],
218
                'stringArgField'            => [
219
                    'type' => Type::string(),
220
                    'args' => ['stringArg' => ['type' => Type::string()]],
221
                ],
222
                'booleanArgField'           => [
223
                    'type' => Type::string(),
224
                    'args' => ['booleanArg' => ['type' => Type::boolean()]],
225
                ],
226
                'enumArgField'              => [
227
                    'type' => Type::string(),
228
                    'args' => ['enumArg' => ['type' => $FurColor]],
229
                ],
230
                'floatArgField'             => [
231
                    'type' => Type::string(),
232
                    'args' => ['floatArg' => ['type' => Type::float()]],
233
                ],
234
                'idArgField'                => [
235
                    'type' => Type::string(),
236
                    'args' => ['idArg' => ['type' => Type::id()]],
237
                ],
238
                'stringListArgField'        => [
239
                    'type' => Type::string(),
240
                    'args' => ['stringListArg' => ['type' => Type::listOf(Type::string())]],
241
                ],
242
                'stringListNonNullArgField' => [
243
                    'type' => Type::string(),
244
                    'args' => [
245
                        'stringListNonNullArg' => [
246
                            'type' => Type::listOf(Type::nonNull(Type::string())),
247
                        ],
248
                    ],
249
                ],
250
                'complexArgField'           => [
251
                    'type' => Type::string(),
252
                    'args' => ['complexArg' => ['type' => $ComplexInput]],
253
                ],
254
                'multipleReqs'              => [
255
                    'type' => Type::string(),
256
                    'args' => [
257
                        'req1' => ['type' => Type::nonNull(Type::int())],
258
                        'req2' => ['type' => Type::nonNull(Type::int())],
259
                    ],
260
                ],
261
                'nonNullFieldWithDefault' => [
262
                    'type' => Type::string(),
263
                    'args' => [
264
                        'arg' => [ 'type' => Type::nonNull(Type::int()), 'defaultValue' => 0 ],
265
                    ],
266
                ],
267
                'multipleOpts'              => [
268
                    'type' => Type::string(),
269
                    'args' => [
270
                        'opt1' => [
271
                            'type'         => Type::int(),
272
                            'defaultValue' => 0,
273
                        ],
274
                        'opt2' => [
275
                            'type'         => Type::int(),
276
                            'defaultValue' => 0,
277
                        ],
278
                    ],
279
                ],
280
                'multipleOptAndReq'         => [
281
                    'type' => Type::string(),
282
                    'args' => [
283
                        'req1' => ['type' => Type::nonNull(Type::int())],
284
                        'req2' => ['type' => Type::nonNull(Type::int())],
285
                        'opt1' => [
286
                            'type'         => Type::int(),
287
                            'defaultValue' => 0,
288
                        ],
289
                        'opt2' => [
290
                            'type'         => Type::int(),
291
                            'defaultValue' => 0,
292
                        ],
293
                    ],
294
                ],
295
            ],
296
        ]);
297
298
        $invalidScalar = new CustomScalarType([
299
            'name'         => 'Invalid',
300
            'serialize'    => static function ($value) {
301
                return $value;
302
            },
303
            'parseLiteral' => static function ($node) {
304
                throw new Exception('Invalid scalar is always invalid: ' . $node->value);
305
            },
306
            'parseValue'   => static function ($node) {
307
                throw new Exception('Invalid scalar is always invalid: ' . $node);
308
            },
309
        ]);
310
311
        $anyScalar = new CustomScalarType([
312
            'name'         => 'Any',
313
            'serialize'    => static function ($value) {
314
                return $value;
315
            },
316
            'parseLiteral' => static function ($node) {
317
                return $node;
318
            }, // Allows any value
319
            'parseValue'   => static function ($value) {
320
                return $value;
321
            }, // Allows any value
322
        ]);
323
324
        $queryRoot = new ObjectType([
325
            'name'   => 'QueryRoot',
326
            'fields' => [
327
                'human'           => [
328
                    'args' => ['id' => ['type' => Type::id()]],
329
                    'type' => $Human,
330
                ],
331
                'alien'           => ['type' => $Alien],
332
                'dog'             => ['type' => $Dog],
333
                'cat'             => ['type' => $Cat],
334
                'pet'             => ['type' => $Pet],
335
                'catOrDog'        => ['type' => $CatOrDog],
336
                'dogOrHuman'      => ['type' => $DogOrHuman],
337
                'humanOrAlien'    => ['type' => $HumanOrAlien],
338
                'complicatedArgs' => ['type' => $ComplicatedArgs],
339
                'invalidArg'      => [
340
                    'args' => [
341
                        'arg' => ['type' => $invalidScalar],
342
                    ],
343
                    'type' => Type::string(),
344
                ],
345
                'anyArg'          => [
346
                    'args' => ['arg' => ['type' => $anyScalar]],
347
                    'type' => Type::string(),
348
                ],
349
            ],
350
        ]);
351
352
        return new Schema([
353
            'query'      => $queryRoot,
354
            'directives' => [
355
                Directive::includeDirective(),
356
                Directive::skipDirective(),
357
                new Directive([
358
                    'name'      => 'onQuery',
359
                    'locations' => ['QUERY'],
360
                ]),
361
                new Directive([
362
                    'name'      => 'onMutation',
363
                    'locations' => ['MUTATION'],
364
                ]),
365
                new Directive([
366
                    'name'      => 'onSubscription',
367
                    'locations' => ['SUBSCRIPTION'],
368
                ]),
369
                new Directive([
370
                    'name'      => 'onField',
371
                    'locations' => ['FIELD'],
372
                ]),
373
                new Directive([
374
                    'name'      => 'onFragmentDefinition',
375
                    'locations' => ['FRAGMENT_DEFINITION'],
376
                ]),
377
                new Directive([
378
                    'name'      => 'onFragmentSpread',
379
                    'locations' => ['FRAGMENT_SPREAD'],
380
                ]),
381
                new Directive([
382
                    'name'      => 'onInlineFragment',
383
                    'locations' => ['INLINE_FRAGMENT'],
384
                ]),
385
                new Directive([
386
                    'name'      => 'onVariableDefinition',
387
                    'locations' => ['VARIABLE_DEFINITION'],
388
                ]),
389
            ],
390
        ]);
391
    }
392
393
    protected function expectFailsRule($rule, $queryString, $errors, $options = [])
394
    {
395
        return $this->expectInvalid(self::getTestSchema(), [$rule], $queryString, $errors, $options);
396
    }
397
398
    protected function expectInvalid($schema, $rules, $queryString, $expectedErrors, $options = [])
399
    {
400
        $errors = DocumentValidator::validate($schema, Parser::parse($queryString, $options), $rules);
401
402
        self::assertNotEmpty($errors, 'GraphQL should not validate');
403
        self::assertEquals($expectedErrors, array_map(['GraphQL\Error\Error', 'formatError'], $errors));
404
405
        return $errors;
406
    }
407
408
    protected function expectPassesRuleWithSchema($schema, $rule, $queryString) : void
409
    {
410
        $this->expectValid($schema, [$rule], $queryString);
411
    }
412
413
    protected function expectFailsRuleWithSchema($schema, $rule, $queryString, $errors) : void
414
    {
415
        $this->expectInvalid($schema, [$rule], $queryString, $errors);
416
    }
417
418
    protected function expectPassesCompleteValidation($queryString) : void
419
    {
420
        $this->expectValid(self::getTestSchema(), DocumentValidator::allRules(), $queryString);
421
    }
422
423
    protected function expectFailsCompleteValidation($queryString, $errors) : void
424
    {
425
        $this->expectInvalid(self::getTestSchema(), DocumentValidator::allRules(), $queryString, $errors);
426
    }
427
428
    protected function expectSDLErrorsFromRule($rule, $sdlString, ?Schema $schema = null, $errors = [])
429
    {
430
        $actualErrors = DocumentValidator::validateSDL(Parser::parse($sdlString), $schema, [$rule]);
431
        self::assertEquals(
432
            $errors,
433
            array_map(['GraphQL\Error\Error', 'formatError'], $actualErrors)
434
        );
435
    }
436
}
437