mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-24 13:56:04 +03:00
Provide a path with a correct list index to resolveType
callback of the union and interface types (fixes #396)
This commit is contained in:
parent
261f8f5ebd
commit
84a52c6c76
@ -949,6 +949,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
||||
foreach ($result as $item) {
|
||||
$fieldPath = $path;
|
||||
$fieldPath[] = $i++;
|
||||
$info->path = $fieldPath;
|
||||
$completedItem = $this->completeValueCatchingError($itemType, $fieldNodes, $info, $fieldPath, $item);
|
||||
if (! $containsPromise && $this->getPromise($completedItem)) {
|
||||
$containsPromise = true;
|
||||
|
@ -620,8 +620,9 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation
|
||||
foreach ($value as $itemValue) {
|
||||
++$index;
|
||||
|
||||
$itemPath = $path;
|
||||
$itemPath[] = $index; // !!! use arrays COW semantics
|
||||
$itemPath = $path;
|
||||
$itemPath[] = $index; // !!! use arrays COW semantics
|
||||
$ctx->resolveInfo->path = $itemPath;
|
||||
|
||||
try {
|
||||
if (! $this->completeValueFast($ctx, $itemType, $itemValue, $itemPath, $itemReturnValue)) {
|
||||
|
156
tests/Regression/Issue396Test.php
Normal file
156
tests/Regression/Issue396Test.php
Normal file
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace GraphQL\Tests\Regression;
|
||||
|
||||
use GraphQL\GraphQL;
|
||||
use GraphQL\Type\Definition\InterfaceType;
|
||||
use GraphQL\Type\Definition\ObjectType;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use GraphQL\Type\Definition\UnionType;
|
||||
use GraphQL\Type\Schema;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use function stristr;
|
||||
|
||||
/**
|
||||
* @see https://github.com/webonyx/graphql-php/issues/396
|
||||
*/
|
||||
class Issue396Test extends TestCase
|
||||
{
|
||||
public function testUnionResolveType()
|
||||
{
|
||||
$a = new ObjectType(['name' => 'A', 'fields' => ['name' => Type::string()]]);
|
||||
$b = new ObjectType(['name' => 'B', 'fields' => ['name' => Type::string()]]);
|
||||
$c = new ObjectType(['name' => 'C', 'fields' => ['name' => Type::string()]]);
|
||||
|
||||
$log = [];
|
||||
|
||||
$unionResult = new UnionType([
|
||||
'name' => 'UnionResult',
|
||||
'types' => [$a, $b, $c],
|
||||
'resolveType' => static function ($result, $root, ResolveInfo $info) use ($a, $b, $c, &$log) : Type {
|
||||
$log[] = [$result, $info->path];
|
||||
if (stristr($result['name'], 'A')) {
|
||||
return $a;
|
||||
}
|
||||
if (stristr($result['name'], 'B')) {
|
||||
return $b;
|
||||
}
|
||||
if (stristr($result['name'], 'C')) {
|
||||
return $c;
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
$exampleType = new ObjectType([
|
||||
'name' => 'Example',
|
||||
'fields' => [
|
||||
'field' => [
|
||||
'type' => Type::nonNull(Type::listOf(Type::nonNull($unionResult))),
|
||||
'resolve' => static function () : array {
|
||||
return [
|
||||
['name' => 'A 1'],
|
||||
['name' => 'B 2'],
|
||||
['name' => 'C 3'],
|
||||
];
|
||||
},
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$schema = new Schema(['query' => $exampleType]);
|
||||
|
||||
$query = '
|
||||
query {
|
||||
field {
|
||||
... on A {
|
||||
name
|
||||
}
|
||||
... on B {
|
||||
name
|
||||
}
|
||||
... on C {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
';
|
||||
|
||||
GraphQL::executeQuery($schema, $query);
|
||||
|
||||
$expected = [
|
||||
[['name' => 'A 1'], ['field', 0]],
|
||||
[['name' => 'B 2'], ['field', 1]],
|
||||
[['name' => 'C 3'], ['field', 2]],
|
||||
];
|
||||
self::assertEquals($expected, $log);
|
||||
}
|
||||
|
||||
public function testInterfaceResolveType()
|
||||
{
|
||||
$log = [];
|
||||
|
||||
$interfaceResult = new InterfaceType([
|
||||
'name' => 'InterfaceResult',
|
||||
'fields' => [
|
||||
'name' => Type::string(),
|
||||
],
|
||||
'resolveType' => static function ($result, $root, ResolveInfo $info) use (&$a, &$b, &$c, &$log) : Type {
|
||||
$log[] = [$result, $info->path];
|
||||
if (stristr($result['name'], 'A')) {
|
||||
return $a;
|
||||
}
|
||||
if (stristr($result['name'], 'B')) {
|
||||
return $b;
|
||||
}
|
||||
if (stristr($result['name'], 'C')) {
|
||||
return $c;
|
||||
}
|
||||
},
|
||||
]);
|
||||
|
||||
$a = new ObjectType(['name' => 'A', 'fields' => ['name' => Type::string()], 'interfaces' => [$interfaceResult]]);
|
||||
$b = new ObjectType(['name' => 'B', 'fields' => ['name' => Type::string()], 'interfaces' => [$interfaceResult]]);
|
||||
$c = new ObjectType(['name' => 'C', 'fields' => ['name' => Type::string()], 'interfaces' => [$interfaceResult]]);
|
||||
|
||||
$exampleType = new ObjectType([
|
||||
'name' => 'Example',
|
||||
'fields' => [
|
||||
'field' => [
|
||||
'type' => Type::nonNull(Type::listOf(Type::nonNull($interfaceResult))),
|
||||
'resolve' => static function () : array {
|
||||
return [
|
||||
['name' => 'A 1'],
|
||||
['name' => 'B 2'],
|
||||
['name' => 'C 3'],
|
||||
];
|
||||
},
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$schema = new Schema([
|
||||
'query' => $exampleType,
|
||||
'types' => [$a, $b, $c],
|
||||
]);
|
||||
|
||||
$query = '
|
||||
query {
|
||||
field {
|
||||
name
|
||||
}
|
||||
}
|
||||
';
|
||||
|
||||
GraphQL::executeQuery($schema, $query);
|
||||
|
||||
$expected = [
|
||||
[['name' => 'A 1'], ['field', 0]],
|
||||
[['name' => 'B 2'], ['field', 1]],
|
||||
[['name' => 'C 3'], ['field', 2]],
|
||||
];
|
||||
self::assertEquals($expected, $log);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user