variableValues = $variableValues; } public function evaluate(ValueNode $valueNode, InputType $type) { return AST::valueFromAST($valueNode, $type, $this->variableValues); } public function addError($error) { $this->errors[] = $error; } }; $collector = new Collector($schema, $runtime); $collector->initialize($documentNode, $operationName); $pipeline = []; foreach ($collector->collectFields($collector->rootType, $collector->operation->selectionSet) as $shared) { $execution = new stdClass(); if (! empty($shared->fieldNodes)) { $execution->fieldNodes = array_map(static function (Node $node) { return $node->toArray(true); }, $shared->fieldNodes); } if (! empty($shared->fieldName)) { $execution->fieldName = $shared->fieldName; } if (! empty($shared->resultName)) { $execution->resultName = $shared->resultName; } if (! empty($shared->argumentValueMap)) { $execution->argumentValueMap = []; foreach ($shared->argumentValueMap as $argumentName => $valueNode) { /** @var Node $valueNode */ $execution->argumentValueMap[$argumentName] = $valueNode->toArray(true); } } $pipeline[] = $execution; } if (strncmp($operationName, 'ShouldEmitError', strlen('ShouldEmitError')) === 0) { self::assertNotEmpty($runtime->errors, 'There should be errors.'); } else { self::assertEmpty($runtime->errors, 'There must be no errors. Got: ' . json_encode($runtime->errors, JSON_PRETTY_PRINT)); if (strncmp($operationName, 'ShouldNotEmit', strlen('ShouldNotEmit')) === 0) { self::assertEmpty($pipeline, 'No instructions should be emitted.'); } else { self::assertNotEmpty($pipeline, 'There should be some instructions emitted.'); } } $result = []; if (! empty($runtime->errors)) { $result['errors'] = array_map( FormattedError::prepareFormatter(null, false), $runtime->errors ); } if (! empty($pipeline)) { $result['pipeline'] = $pipeline; } $json = json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n"; $fileName = __DIR__ . DIRECTORY_SEPARATOR . basename(__FILE__, '.php') . 'Snapshots' . DIRECTORY_SEPARATOR . $operationName . '.json'; if (! file_exists($fileName)) { file_put_contents($fileName, $json); } self::assertStringEqualsFile($fileName, $json); } public function provideForTestCollectFields() { $testCases = [ [ StarWarsSchema::build(), 'query ShouldEmitFieldWithoutArguments { human { name } }', null, ], [ StarWarsSchema::build(), 'query ShouldEmitFieldThatHasArguments($id: ID!) { human(id: $id) { name } }', null, ], [ StarWarsSchema::build(), 'query ShouldEmitForInlineFragment($id: ID!) { ...HumanById } fragment HumanById on Query { human(id: $id) { ... on Human { name } } }', null, ], [ StarWarsSchema::build(), 'query ShouldEmitObjectFieldForFragmentSpread($id: ID!) { human(id: $id) { ...HumanName } } fragment HumanName on Human { name }', null, ], [ StarWarsSchema::build(), 'query ShouldEmitTypeName { queryTypeName: __typename __typename }', null, ], [ StarWarsSchema::build(), 'query ShouldEmitIfIncludeConditionTrue($id: ID!, $condition: Boolean!) { droid(id: $id) @include(if: $condition) { id } }', ['condition' => true], ], [ StarWarsSchema::build(), 'query ShouldNotEmitIfIncludeConditionFalse($id: ID!, $condition: Boolean!) { droid(id: $id) @include(if: $condition) { id } }', ['condition' => false], ], [ StarWarsSchema::build(), 'query ShouldNotEmitIfSkipConditionTrue($id: ID!, $condition: Boolean!) { droid(id: $id) @skip(if: $condition) { id } }', ['condition' => true], ], [ StarWarsSchema::build(), 'query ShouldEmitIfSkipConditionFalse($id: ID!, $condition: Boolean!) { droid(id: $id) @skip(if: $condition) { id } }', ['condition' => false], ], [ StarWarsSchema::build(), 'query ShouldNotEmitIncludeSkipTT($id: ID!, $includeCondition: Boolean!, $skipCondition: Boolean!) { droid(id: $id) @include(if: $includeCondition) @skip(if: $skipCondition) { id } }', ['includeCondition' => true, 'skipCondition' => true], ], [ StarWarsSchema::build(), 'query ShouldEmitIncludeSkipTF($id: ID!, $includeCondition: Boolean!, $skipCondition: Boolean!) { droid(id: $id) @include(if: $includeCondition) @skip(if: $skipCondition) { id } }', ['includeCondition' => true, 'skipCondition' => false], ], [ StarWarsSchema::build(), 'query ShouldNotEmitIncludeSkipFT($id: ID!, $includeCondition: Boolean!, $skipCondition: Boolean!) { droid(id: $id) @include(if: $includeCondition) @skip(if: $skipCondition) { id } }', ['includeCondition' => false, 'skipCondition' => true], ], [ StarWarsSchema::build(), 'query ShouldNotEmitIncludeSkipFF($id: ID!, $includeCondition: Boolean!, $skipCondition: Boolean!) { droid(id: $id) @include(if: $includeCondition) @skip(if: $skipCondition) { id } }', ['includeCondition' => false, 'skipCondition' => false], ], [ StarWarsSchema::build(), 'query ShouldNotEmitSkipAroundInlineFragment { ... on Query @skip(if: true) { hero(episode: 5) { name } } }', null, ], [ StarWarsSchema::build(), 'query ShouldEmitSkipAroundInlineFragment { ... on Query @skip(if: false) { hero(episode: 5) { name } } }', null, ], [ StarWarsSchema::build(), 'query ShouldEmitIncludeAroundInlineFragment { ... on Query @include(if: true) { hero(episode: 5) { name } } }', null, ], [ StarWarsSchema::build(), 'query ShouldNotEmitIncludeAroundInlineFragment { ... on Query @include(if: false) { hero(episode: 5) { name } } }', null, ], [ StarWarsSchema::build(), 'query ShouldNotEmitSkipFragmentSpread { ...Hero @skip(if: true) } fragment Hero on Query { hero(episode: 5) { name } }', null, ], [ StarWarsSchema::build(), 'query ShouldEmitSkipFragmentSpread { ...Hero @skip(if: false) } fragment Hero on Query { hero(episode: 5) { name } }', null, ], [ StarWarsSchema::build(), 'query ShouldEmitIncludeFragmentSpread { ...Hero @include(if: true) } fragment Hero on Query { hero(episode: 5) { name } }', null, ], [ StarWarsSchema::build(), 'query ShouldNotEmitIncludeFragmentSpread { ...Hero @include(if: false) } fragment Hero on Query { hero(episode: 5) { name } }', null, ], [ StarWarsSchema::build(), 'query ShouldEmitSingleInstrictionForSameResultName($id: ID!) { human(id: $id) { name name: secretBackstory } }', null, ], ]; $data = []; foreach ($testCases as [$schema, $query, $variableValues]) { $documentNode = Parser::parse($query, ['noLocation' => true]); $operationName = null; foreach ($documentNode->definitions as $definitionNode) { /** @var Node $definitionNode */ if ($definitionNode instanceof OperationDefinitionNode) { /** @var OperationDefinitionNode $definitionNode */ self::assertNotNull($definitionNode->name); $operationName = $definitionNode->name->value; break; } } self::assertArrayNotHasKey($operationName, $data); $data[$operationName] = [$schema, $documentNode, $operationName, $variableValues]; } return $data; } }