Completed
Push — master ( d80d23...dbf644 )
by David
18s queued 11s
created

EndToEndTest::testEndToEnd2Iterators()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 56
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 18
dl 0
loc 56
rs 9.6666
c 0
b 0
f 0
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
namespace TheCodingMachine\GraphQL\Controllers\Integration;
4
5
use function class_exists;
6
use Doctrine\Common\Annotations\AnnotationReader as DoctrineAnnotationReader;
7
use Exception;
8
use GraphQL\Error\Debug;
9
use GraphQL\GraphQL;
10
use GraphQL\Type\Definition\InputType;
11
use Mouf\Picotainer\Picotainer;
12
use PhpParser\Comment\Doc;
13
use PHPUnit\Framework\TestCase;
14
use PHPUnit\Util\Type;
15
use function print_r;
16
use Psr\Container\ContainerInterface;
17
use Psr\Container\NotFoundExceptionInterface;
18
use Symfony\Component\Cache\Simple\ArrayCache;
19
use TheCodingMachine\GraphQL\Controllers\AnnotationReader;
20
use TheCodingMachine\GraphQL\Controllers\FieldsBuilderFactory;
21
use TheCodingMachine\GraphQL\Controllers\Fixtures\Integration\Models\Contact;
22
use TheCodingMachine\GraphQL\Controllers\GlobControllerQueryProvider;
23
use TheCodingMachine\GraphQL\Controllers\Hydrators\HydratorInterface;
24
use TheCodingMachine\GraphQL\Controllers\Hydrators\FactoryHydrator;
25
use TheCodingMachine\GraphQL\Controllers\InputTypeGenerator;
26
use TheCodingMachine\GraphQL\Controllers\InputTypeUtils;
27
use TheCodingMachine\GraphQL\Controllers\Mappers\CompositeTypeMapper;
28
use TheCodingMachine\GraphQL\Controllers\Mappers\GlobTypeMapper;
29
use TheCodingMachine\GraphQL\Controllers\Mappers\PorpaginasTypeMapper;
30
use TheCodingMachine\GraphQL\Controllers\Mappers\RecursiveTypeMapper;
31
use TheCodingMachine\GraphQL\Controllers\Mappers\RecursiveTypeMapperInterface;
32
use TheCodingMachine\GraphQL\Controllers\Mappers\TypeMapperInterface;
33
use TheCodingMachine\GraphQL\Controllers\NamingStrategy;
34
use TheCodingMachine\GraphQL\Controllers\NamingStrategyInterface;
35
use TheCodingMachine\GraphQL\Controllers\QueryProviderInterface;
36
use TheCodingMachine\GraphQL\Controllers\Containers\BasicAutoWiringContainer;
37
use TheCodingMachine\GraphQL\Controllers\Containers\EmptyContainer;
38
use TheCodingMachine\GraphQL\Controllers\Reflection\CachedDocBlockFactory;
39
use TheCodingMachine\GraphQL\Controllers\Schema;
40
use TheCodingMachine\GraphQL\Controllers\Security\AuthenticationServiceInterface;
41
use TheCodingMachine\GraphQL\Controllers\Security\AuthorizationServiceInterface;
42
use TheCodingMachine\GraphQL\Controllers\Security\VoidAuthenticationService;
43
use TheCodingMachine\GraphQL\Controllers\Security\VoidAuthorizationService;
44
use TheCodingMachine\GraphQL\Controllers\TypeGenerator;
45
use TheCodingMachine\GraphQL\Controllers\TypeRegistry;
46
use TheCodingMachine\GraphQL\Controllers\Types\TypeResolver;
47
use function var_dump;
48
use function var_export;
49
50
class EndToEndTest extends TestCase
51
{
52
    /**
53
     * @var ContainerInterface
54
     */
55
    private $mainContainer;
56
57
    public function setUp()
58
    {
59
        $this->mainContainer = new Picotainer([
60
            Schema::class => function(ContainerInterface $container) {
61
                return new Schema($container->get(QueryProviderInterface::class), $container->get(RecursiveTypeMapperInterface::class), $container->get(TypeResolver::class));
62
            },
63
            QueryProviderInterface::class => function(ContainerInterface $container) {
64
                return new GlobControllerQueryProvider('TheCodingMachine\\GraphQL\\Controllers\\Fixtures\\Integration\\Controllers', $container->get(FieldsBuilderFactory::class),
65
                    $container->get(RecursiveTypeMapperInterface::class), $container->get(BasicAutoWiringContainer::class), new ArrayCache());
66
            },
67
            FieldsBuilderFactory::class => function(ContainerInterface $container) {
68
                return new FieldsBuilderFactory(
69
                    $container->get(AnnotationReader::class),
70
                    $container->get(HydratorInterface::class),
71
                    $container->get(AuthenticationServiceInterface::class),
72
                    $container->get(AuthorizationServiceInterface::class),
73
                    $container->get(TypeResolver::class),
74
                    $container->get(CachedDocBlockFactory::class)
75
                );
76
            },
77
            TypeResolver::class => function(ContainerInterface $container) {
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

77
            TypeResolver::class => function(/** @scrutinizer ignore-unused */ ContainerInterface $container) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
78
                return new TypeResolver();
79
            },
80
            BasicAutoWiringContainer::class => function(ContainerInterface $container) {
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

80
            BasicAutoWiringContainer::class => function(/** @scrutinizer ignore-unused */ ContainerInterface $container) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
81
                return new BasicAutoWiringContainer(new EmptyContainer());
82
            },
83
            AuthorizationServiceInterface::class => function(ContainerInterface $container) {
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

83
            AuthorizationServiceInterface::class => function(/** @scrutinizer ignore-unused */ ContainerInterface $container) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
84
                return new VoidAuthorizationService();
85
            },
86
            AuthenticationServiceInterface::class => function(ContainerInterface $container) {
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

86
            AuthenticationServiceInterface::class => function(/** @scrutinizer ignore-unused */ ContainerInterface $container) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
87
                return new VoidAuthenticationService();
88
            },
89
            RecursiveTypeMapperInterface::class => function(ContainerInterface $container) {
90
                return new RecursiveTypeMapper(
91
                    $container->get(TypeMapperInterface::class),
92
                    $container->get(NamingStrategyInterface::class),
93
                    new ArrayCache(),
94
                    $container->get(TypeRegistry::class)
95
                );
96
            },
97
            TypeMapperInterface::class => function(ContainerInterface $container) {
98
                return new CompositeTypeMapper([
99
                    $container->get(GlobTypeMapper::class),
100
                    $container->get(GlobTypeMapper::class.'2'),
101
                    $container->get(PorpaginasTypeMapper::class),
102
                ]);
103
            },
104
            GlobTypeMapper::class => function(ContainerInterface $container) {
105
                return new GlobTypeMapper('TheCodingMachine\\GraphQL\\Controllers\\Fixtures\\Integration\\Types',
106
                    $container->get(TypeGenerator::class),
107
                    $container->get(InputTypeGenerator::class),
108
                    $container->get(InputTypeUtils::class),
109
                    $container->get(BasicAutoWiringContainer::class),
110
                    $container->get(AnnotationReader::class),
111
                    $container->get(NamingStrategyInterface::class),
112
                    new ArrayCache()
113
                    );
114
            },
115
            GlobTypeMapper::class.'2' => function(ContainerInterface $container) {
116
                return new GlobTypeMapper('TheCodingMachine\\GraphQL\\Controllers\\Fixtures\\Integration\\Models',
117
                    $container->get(TypeGenerator::class),
118
                    $container->get(InputTypeGenerator::class),
119
                    $container->get(InputTypeUtils::class),
120
                    $container->get(BasicAutoWiringContainer::class),
121
                    $container->get(AnnotationReader::class),
122
                    $container->get(NamingStrategyInterface::class),
123
                    new ArrayCache()
124
                );
125
            },
126
            PorpaginasTypeMapper::class => function() {
127
                return new PorpaginasTypeMapper();
128
            },
129
            TypeGenerator::class => function(ContainerInterface $container) {
130
                return new TypeGenerator(
131
                    $container->get(AnnotationReader::class),
132
                    $container->get(FieldsBuilderFactory::class),
133
                    $container->get(NamingStrategyInterface::class),
134
                    $container->get(TypeRegistry::class),
135
                    $container->get(BasicAutoWiringContainer::class)
136
                );
137
            },
138
            TypeRegistry::class => function() {
139
                return new TypeRegistry();
140
            },
141
            InputTypeGenerator::class => function(ContainerInterface $container) {
142
                return new InputTypeGenerator(
143
                    $container->get(InputTypeUtils::class),
144
                    $container->get(FieldsBuilderFactory::class),
145
                    $container->get(HydratorInterface::class)
146
                );
147
            },
148
            InputTypeUtils::class => function(ContainerInterface $container) {
149
                return new InputTypeUtils(
150
                    $container->get(AnnotationReader::class),
151
                    $container->get(NamingStrategyInterface::class)
152
                );
153
            },
154
            AnnotationReader::class => function(ContainerInterface $container) {
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

154
            AnnotationReader::class => function(/** @scrutinizer ignore-unused */ ContainerInterface $container) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
155
                return new AnnotationReader(new DoctrineAnnotationReader());
156
            },
157
            HydratorInterface::class => function(ContainerInterface $container) {
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

157
            HydratorInterface::class => function(/** @scrutinizer ignore-unused */ ContainerInterface $container) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
158
                return new FactoryHydrator();
159
            },
160
            NamingStrategyInterface::class => function() {
161
                return new NamingStrategy();
162
            },
163
            CachedDocBlockFactory::class => function() {
164
                return new CachedDocBlockFactory(new ArrayCache());
165
            }
166
        ]);
167
168
        $this->mainContainer->get(TypeResolver::class)->registerSchema($this->mainContainer->get(Schema::class));
169
    }
170
171
    public function testEndToEnd()
172
    {
173
        /**
174
         * @var Schema $schema
175
         */
176
        $schema = $this->mainContainer->get(Schema::class);
177
178
        $schema->assertValid();
179
180
        $queryString = '
181
        query {
182
            getContacts {
183
                name
184
                uppercaseName
185
                ... on User {
186
                    email
187
                }
188
            }
189
        }
190
        ';
191
192
        $result = GraphQL::executeQuery(
193
            $schema,
194
            $queryString
195
        );
196
197
        $this->assertSame([
198
            'getContacts' => [
199
                [
200
                    'name' => 'Joe',
201
                    'uppercaseName' => 'JOE'
202
                ],
203
                [
204
                    'name' => 'Bill',
205
                    'uppercaseName' => 'BILL',
206
                    'email' => '[email protected]'
207
                ]
208
209
            ]
210
        ], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
211
212
        // Let's redo this to test cache.
213
        $result = GraphQL::executeQuery(
214
            $schema,
215
            $queryString
216
        );
217
218
        $this->assertSame([
219
            'getContacts' => [
220
                [
221
                    'name' => 'Joe',
222
                    'uppercaseName' => 'JOE'
223
                ],
224
                [
225
                    'name' => 'Bill',
226
                    'uppercaseName' => 'BILL',
227
                    'email' => '[email protected]'
228
                ]
229
230
            ]
231
        ], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
232
    }
233
234
    public function testEndToEndInputType()
235
    {
236
        /**
237
         * @var Schema $schema
238
         */
239
        $schema = $this->mainContainer->get(Schema::class);
240
        $queryString = '
241
        mutation {
242
          saveContact(
243
            contact: {
244
                name: "foo",
245
                birthDate: "1942-12-24 00:00:00",
246
                relations: [
247
                    {
248
                        name: "bar"
249
                        birthDate: "1942-12-24 00:00:00",
250
                    }
251
                ]
252
            }
253
          ) {
254
            name,
255
            birthDate,
256
            relations {
257
              name,
258
              birthDate
259
            }
260
          }
261
        }
262
        ';
263
264
        $result = GraphQL::executeQuery(
265
            $schema,
266
            $queryString
267
        );
268
269
        $this->assertSame([
270
            'saveContact' => [
271
                'name' => 'foo',
272
                'birthDate' => '1942-12-24T00:00:00+00:00',
273
                'relations' => [
274
                    [
275
                        'name' => 'bar',
276
                        'birthDate' => '1942-12-24T00:00:00+00:00'
277
                    ]
278
                ]
279
            ]
280
        ], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
281
    }
282
283
    public function testEndToEndPorpaginas()
284
    {
285
        /**
286
         * @var Schema $schema
287
         */
288
        $schema = $this->mainContainer->get(Schema::class);
289
290
        $queryString = '
291
        query {
292
            getContactsIterator {
293
                items(limit: 1, offset: 1) {
294
                    name
295
                    uppercaseName
296
                    ... on User {
297
                        email
298
                    }
299
                }
300
                count
301
            }
302
        }
303
        ';
304
305
        $result = GraphQL::executeQuery(
306
            $schema,
307
            $queryString
308
        );
309
310
        $this->assertSame([
311
            'getContactsIterator' => [
312
                'items' => [
313
                    [
314
                        'name' => 'Bill',
315
                        'uppercaseName' => 'BILL',
316
                        'email' => '[email protected]'
317
                    ]
318
                ],
319
                'count' => 2
320
            ]
321
        ], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
322
323
        // Let's redo this to test cache.
324
        $result = GraphQL::executeQuery(
325
            $schema,
326
            $queryString
327
        );
328
329
        $this->assertSame([
330
            'getContactsIterator' => [
331
                'items' => [
332
                    [
333
                        'name' => 'Bill',
334
                        'uppercaseName' => 'BILL',
335
                        'email' => '[email protected]'
336
                    ]
337
                ],
338
                'count' => 2
339
            ]
340
        ], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
341
342
        // Let's run a query with no limit but an offset
343
        $invalidQueryString = '
344
        query {
345
            getContactsIterator {
346
                items(offset: 1) {
347
                    name
348
                    ... on User {
349
                        email
350
                    }
351
                }
352
                count
353
            }
354
        }
355
        ';
356
357
        $result = GraphQL::executeQuery(
358
            $schema,
359
            $invalidQueryString
360
        );
361
362
        $this->assertSame('In the items field of a result set, you cannot add a "offset" without also adding a "limit"', $result->toArray(Debug::RETHROW_UNSAFE_EXCEPTIONS)['errors'][0]['message']);
363
364
365
        // Let's run a query with no limit offset
366
        $invalidQueryString = '
367
        query {
368
            getContactsIterator {
369
                items {
370
                    name
371
                    ... on User {
372
                        email
373
                    }
374
                }
375
                count
376
            }
377
        }
378
        ';
379
380
        $result = GraphQL::executeQuery(
381
            $schema,
382
            $invalidQueryString
383
        );
384
385
        $this->assertSame([
386
            'getContactsIterator' => [
387
                'items' => [
388
                    [
389
                        'name' => 'Joe',
390
                    ],
391
                    [
392
                        'name' => 'Bill',
393
                        'email' => '[email protected]'
394
                    ]
395
                ],
396
                'count' => 2
397
            ]
398
        ], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
399
    }
400
401
    /**
402
     * This tests is used to be sure that the PorpaginasIterator types are not mixed up when cached (because it has a subtype)
403
     */
404
    public function testEndToEnd2Iterators()
405
    {
406
        /**
407
         * @var Schema $schema
408
         */
409
        $schema = $this->mainContainer->get(Schema::class);
410
411
        $queryString = '
412
        query {
413
            getContactsIterator {
414
                items(limit: 1, offset: 1) {
415
                    name
416
                    uppercaseName
417
                    ... on User {
418
                        email
419
                    }
420
                }
421
                count
422
            }
423
            
424
            getProducts {
425
                items {
426
                    name
427
                    price
428
                }
429
                count            
430
            }
431
        }
432
        ';
433
434
        $result = GraphQL::executeQuery(
435
            $schema,
436
            $queryString
437
        );
438
439
        $this->assertSame([
440
            'getContactsIterator' => [
441
                'items' => [
442
                    [
443
                        'name' => 'Bill',
444
                        'uppercaseName' => 'BILL',
445
                        'email' => '[email protected]'
446
                    ]
447
                ],
448
                'count' => 2
449
            ],
450
            'getProducts' => [
451
                'items' => [
452
                    [
453
                        'name' => 'Foo',
454
                        'price' => 42.0,
455
                    ]
456
                ],
457
                'count' => 1
458
            ]
459
        ], $result->toArray(Debug::RETHROW_INTERNAL_EXCEPTIONS)['data']);
460
461
    }
462
}
463