Passed
Pull Request — master (#314)
by Jakub
08:46 queued 02:41
created

CollectorTest::provideForTestCollectFields()

Size

Total Lines 251
Code Lines 195

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 195
dl 0
loc 251
c 0
b 0
f 0
nc 4
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\Experimental\Executor;
6
7
use GraphQL\Error\FormattedError;
8
use GraphQL\Experimental\Executor\Collector;
9
use GraphQL\Experimental\Executor\Runtime;
10
use GraphQL\Language\AST\DocumentNode;
11
use GraphQL\Language\AST\Node;
12
use GraphQL\Language\AST\NodeKind;
13
use GraphQL\Language\AST\OperationDefinitionNode;
14
use GraphQL\Language\AST\ValueNode;
15
use GraphQL\Language\Parser;
16
use GraphQL\Tests\StarWarsSchema;
17
use GraphQL\Type\Definition\InputType;
18
use GraphQL\Type\Schema;
19
use GraphQL\Utils\AST;
20
use PHPUnit\Framework\TestCase;
21
use stdClass;
22
use Throwable;
23
use function array_map;
24
use function basename;
25
use function file_exists;
26
use function file_put_contents;
27
use function json_encode;
28
use function strlen;
29
use function strncmp;
30
use const DIRECTORY_SEPARATOR;
31
use const JSON_PRETTY_PRINT;
32
use const JSON_UNESCAPED_SLASHES;
33
use const JSON_UNESCAPED_UNICODE;
34
35
class CollectorTest extends TestCase
36
{
37
    /**
38
     * @param mixed[]|null $variableValues
39
     *
40
     * @dataProvider provideForTestCollectFields
41
     */
42
    public function testCollectFields(Schema $schema, DocumentNode $documentNode, string $operationName, ?array $variableValues)
43
    {
44
        $runtime = new class($variableValues) implements Runtime
45
        {
46
            /** @var Throwable[] */
47
            public $errors = [];
48
49
            /** @var mixed[]|null */
50
            public $variableValues;
51
52
            public function __construct($variableValues)
53
            {
54
                $this->variableValues = $variableValues;
55
            }
56
57
            public function evaluate(ValueNode $valueNode, InputType $type)
58
            {
59
                return AST::valueFromAST($valueNode, $type, $this->variableValues);
60
            }
61
62
            public function addError($error)
63
            {
64
                $this->errors[] = $error;
65
            }
66
        };
67
68
        $collector = new Collector($schema, $runtime);
69
        $collector->initialize($documentNode, $operationName);
70
71
        $pipeline = [];
72
        foreach ($collector->collectFields($collector->rootType, $collector->operation->selectionSet) as $shared) {
0 ignored issues
show
Bug introduced by
It seems like $collector->rootType can also be of type null; however, parameter $runtimeType of GraphQL\Experimental\Exe...lector::collectFields() does only seem to accept GraphQL\Type\Definition\ObjectType, maybe add an additional type check? ( Ignorable by Annotation )

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

72
        foreach ($collector->collectFields(/** @scrutinizer ignore-type */ $collector->rootType, $collector->operation->selectionSet) as $shared) {
Loading history...
73
            $execution = new stdClass();
74
            if (! empty($shared->fieldNodes)) {
75
                $execution->fieldNodes = array_map(static function (Node $node) {
76
                    return $node->toArray(true);
77
                }, $shared->fieldNodes);
78
            }
79
            if (! empty($shared->fieldName)) {
80
                $execution->fieldName = $shared->fieldName;
81
            }
82
            if (! empty($shared->resultName)) {
83
                $execution->resultName = $shared->resultName;
84
            }
85
            if (! empty($shared->argumentValueMap)) {
86
                $execution->argumentValueMap = [];
87
                foreach ($shared->argumentValueMap as $argumentName => $valueNode) {
88
                    /** @var Node $valueNode */
89
                    $execution->argumentValueMap[$argumentName] = $valueNode->toArray(true);
90
                }
91
            }
92
93
            $pipeline[] = $execution;
94
        }
95
        if (strncmp($operationName, 'ShouldEmitError', strlen('ShouldEmitError')) === 0) {
96
            self::assertNotEmpty($runtime->errors, 'There should be errors.');
97
        } else {
98
            self::assertEmpty($runtime->errors, 'There must be no errors. Got: ' . json_encode($runtime->errors, JSON_PRETTY_PRINT));
99
100
            if (strncmp($operationName, 'ShouldNotEmit', strlen('ShouldNotEmit')) === 0) {
101
                self::assertEmpty($pipeline, 'No instructions should be emitted.');
102
            } else {
103
                self::assertNotEmpty($pipeline, 'There should be some instructions emitted.');
104
            }
105
        }
106
107
        $result = [];
108
        if (! empty($runtime->errors)) {
109
            $result['errors'] = array_map(
110
                FormattedError::prepareFormatter(null, false),
111
                $runtime->errors
112
            );
113
        }
114
        if (! empty($pipeline)) {
115
            $result['pipeline'] = $pipeline;
116
        }
117
118
        $json = json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
119
120
        $fileName = __DIR__ . DIRECTORY_SEPARATOR . basename(__FILE__, '.php') . 'Snapshots' . DIRECTORY_SEPARATOR . $operationName . '.json';
121
        if (! file_exists($fileName)) {
122
            file_put_contents($fileName, $json);
123
        }
124
125
        self::assertStringEqualsFile($fileName, $json);
126
    }
127
128
    public function provideForTestCollectFields()
129
    {
130
        $testCases = [
131
            [
132
                StarWarsSchema::build(),
133
                'query ShouldEmitFieldWithoutArguments {
134
                    human {
135
                        name                    
136
                    }
137
                }',
138
                null,
139
            ],
140
            [
141
                StarWarsSchema::build(),
142
                'query ShouldEmitFieldThatHasArguments($id: ID!) {
143
                    human(id: $id) {
144
                        name
145
                    }
146
                }',
147
                null,
148
            ],
149
            [
150
                StarWarsSchema::build(),
151
                'query ShouldEmitForInlineFragment($id: ID!) {
152
                    ...HumanById
153
                }
154
                fragment HumanById on Query {
155
                    human(id: $id) {
156
                        ... on Human {
157
                            name
158
                        }
159
                    }
160
                }',
161
                null,
162
            ],
163
            [
164
                StarWarsSchema::build(),
165
                'query ShouldEmitObjectFieldForFragmentSpread($id: ID!) {
166
                    human(id: $id) {
167
                        ...HumanName
168
                    }
169
                }
170
                fragment HumanName on Human {
171
                    name
172
                }',
173
                null,
174
            ],
175
            [
176
                StarWarsSchema::build(),
177
                'query ShouldEmitTypeName {
178
                    queryTypeName: __typename
179
                    __typename
180
                }',
181
                null,
182
            ],
183
            [
184
                StarWarsSchema::build(),
185
                'query ShouldEmitIfIncludeConditionTrue($id: ID!, $condition: Boolean!) {
186
                    droid(id: $id) @include(if: $condition) {
187
                        id
188
                    }
189
                }',
190
                ['condition' => true],
191
            ],
192
            [
193
                StarWarsSchema::build(),
194
                'query ShouldNotEmitIfIncludeConditionFalse($id: ID!, $condition: Boolean!) {
195
                    droid(id: $id) @include(if: $condition) {
196
                        id
197
                    }
198
                }',
199
                ['condition' => false],
200
            ],
201
            [
202
                StarWarsSchema::build(),
203
                'query ShouldNotEmitIfSkipConditionTrue($id: ID!, $condition: Boolean!) {
204
                    droid(id: $id) @skip(if: $condition) {
205
                        id
206
                    }
207
                }',
208
                ['condition' => true],
209
            ],
210
            [
211
                StarWarsSchema::build(),
212
                'query ShouldEmitIfSkipConditionFalse($id: ID!, $condition: Boolean!) {
213
                    droid(id: $id) @skip(if: $condition) {
214
                        id
215
                    }
216
                }',
217
                ['condition' => false],
218
            ],
219
            [
220
                StarWarsSchema::build(),
221
                'query ShouldNotEmitIncludeSkipTT($id: ID!, $includeCondition: Boolean!, $skipCondition: Boolean!) {
222
                    droid(id: $id) @include(if: $includeCondition) @skip(if: $skipCondition) {
223
                        id
224
                    }
225
                }',
226
                ['includeCondition' => true, 'skipCondition' => true],
227
            ],
228
            [
229
                StarWarsSchema::build(),
230
                'query ShouldEmitIncludeSkipTF($id: ID!, $includeCondition: Boolean!, $skipCondition: Boolean!) {
231
                    droid(id: $id) @include(if: $includeCondition) @skip(if: $skipCondition) {
232
                        id
233
                    }
234
                }',
235
                ['includeCondition' => true, 'skipCondition' => false],
236
            ],
237
            [
238
                StarWarsSchema::build(),
239
                'query ShouldNotEmitIncludeSkipFT($id: ID!, $includeCondition: Boolean!, $skipCondition: Boolean!) {
240
                    droid(id: $id) @include(if: $includeCondition) @skip(if: $skipCondition) {
241
                        id
242
                    }
243
                }',
244
                ['includeCondition' => false, 'skipCondition' => true],
245
            ],
246
            [
247
                StarWarsSchema::build(),
248
                'query ShouldNotEmitIncludeSkipFF($id: ID!, $includeCondition: Boolean!, $skipCondition: Boolean!) {
249
                    droid(id: $id) @include(if: $includeCondition) @skip(if: $skipCondition) {
250
                        id
251
                    }
252
                }',
253
                ['includeCondition' => false, 'skipCondition' => false],
254
            ],
255
            [
256
                StarWarsSchema::build(),
257
                'query ShouldNotEmitSkipAroundInlineFragment {
258
                    ... on Query @skip(if: true) {
259
                        hero(episode: 5) {
260
                            name
261
                        }
262
                    }
263
                }',
264
                null,
265
            ],
266
            [
267
                StarWarsSchema::build(),
268
                'query ShouldEmitSkipAroundInlineFragment {
269
                    ... on Query @skip(if: false) {
270
                        hero(episode: 5) {
271
                            name
272
                        }
273
                    }
274
                }',
275
                null,
276
            ],
277
            [
278
                StarWarsSchema::build(),
279
                'query ShouldEmitIncludeAroundInlineFragment {
280
                    ... on Query @include(if: true) {
281
                        hero(episode: 5) {
282
                            name
283
                        }
284
                    }
285
                }',
286
                null,
287
            ],
288
            [
289
                StarWarsSchema::build(),
290
                'query ShouldNotEmitIncludeAroundInlineFragment {
291
                    ... on Query @include(if: false) {
292
                        hero(episode: 5) {
293
                            name
294
                        }
295
                    }
296
                }',
297
                null,
298
            ],
299
            [
300
                StarWarsSchema::build(),
301
                'query ShouldNotEmitSkipFragmentSpread {
302
                    ...Hero @skip(if: true)
303
                }
304
                fragment Hero on Query {
305
                    hero(episode: 5) {
306
                        name
307
                    }
308
                }',
309
                null,
310
            ],
311
            [
312
                StarWarsSchema::build(),
313
                'query ShouldEmitSkipFragmentSpread {
314
                    ...Hero @skip(if: false)
315
                }
316
                fragment Hero on Query {
317
                    hero(episode: 5) {
318
                        name
319
                    }
320
                }',
321
                null,
322
            ],
323
            [
324
                StarWarsSchema::build(),
325
                'query ShouldEmitIncludeFragmentSpread {
326
                    ...Hero @include(if: true)
327
                }
328
                fragment Hero on Query {
329
                    hero(episode: 5) {
330
                        name
331
                    }
332
                }',
333
                null,
334
            ],
335
            [
336
                StarWarsSchema::build(),
337
                'query ShouldNotEmitIncludeFragmentSpread {
338
                    ...Hero @include(if: false)
339
                }
340
                fragment Hero on Query {
341
                    hero(episode: 5) {
342
                        name
343
                    }
344
                }',
345
                null,
346
            ],
347
            [
348
                StarWarsSchema::build(),
349
                'query ShouldEmitSingleInstrictionForSameResultName($id: ID!) {
350
                    human(id: $id) {
351
                        name
352
                        name: secretBackstory 
353
                    }
354
                }',
355
                null,
356
            ],
357
        ];
358
359
        $data = [];
360
        foreach ($testCases as [$schema, $query, $variableValues]) {
361
            $documentNode  = Parser::parse($query, ['noLocation' => true]);
362
            $operationName = null;
363
            foreach ($documentNode->definitions as $definitionNode) {
364
                /** @var Node $definitionNode */
365
                if ($definitionNode->kind === NodeKind::OPERATION_DEFINITION) {
366
                    /** @var OperationDefinitionNode $definitionNode */
367
                    self::assertNotNull($definitionNode->name);
368
                    $operationName = $definitionNode->name->value;
369
                    break;
370
                }
371
            }
372
373
            self::assertArrayNotHasKey($operationName, $data);
374
375
            $data[$operationName] = [$schema, $documentNode, $operationName, $variableValues];
376
        }
377
378
        return $data;
379
    }
380
}
381