mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-29 00:25:17 +03:00
Support for union types when using buildSchema
* Adds support for resolving union/interface types when using a generated schema * Move resolveType __typename checking into defaultResolveType * Clean up existing tests and improve error messages ref: graphql/graphql-js#947 # Conflicts: # src/Utils/BuildSchema.php # tests/Utils/BuildSchemaTest.php
This commit is contained in:
parent
7705e50e44
commit
4e26de3588
@ -1053,15 +1053,6 @@ class Executor
|
|||||||
$runtimeType = $returnType->resolveType($result, $exeContext->contextValue, $info);
|
$runtimeType = $returnType->resolveType($result, $exeContext->contextValue, $info);
|
||||||
|
|
||||||
if (null === $runtimeType) {
|
if (null === $runtimeType) {
|
||||||
if ($returnType instanceof InterfaceType && $info->schema->getConfig()->typeLoader) {
|
|
||||||
Warning::warnOnce(
|
|
||||||
"GraphQL Interface Type `{$returnType->name}` returned `null` from it`s `resolveType` function ".
|
|
||||||
'for value: ' . Utils::printSafe($result) . '. Switching to slow resolution method using `isTypeOf` ' .
|
|
||||||
'of all possible implementations. It requires full schema scan and degrades query performance significantly. '.
|
|
||||||
' Make sure your `resolveType` always returns valid implementation or throws.',
|
|
||||||
Warning::WARNING_FULL_SCHEMA_SCAN
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$runtimeType = self::defaultTypeResolver($result, $exeContext->contextValue, $info, $returnType);
|
$runtimeType = self::defaultTypeResolver($result, $exeContext->contextValue, $info, $returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1122,9 +1113,11 @@ class Executor
|
|||||||
|
|
||||||
if (!$runtimeType instanceof ObjectType) {
|
if (!$runtimeType instanceof ObjectType) {
|
||||||
throw new InvariantViolation(
|
throw new InvariantViolation(
|
||||||
"Abstract type {$returnType} must resolve to an Object type at runtime " .
|
"Abstract type {$returnType} must resolve to an Object type at " .
|
||||||
"for field {$info->parentType}.{$info->fieldName} with " .
|
"runtime for field {$info->parentType}.{$info->fieldName} with " .
|
||||||
'value "' . Utils::printSafe($result) . '", received "'. Utils::printSafe($runtimeType) . '".'
|
'value "' . Utils::printSafe($result) . '", received "'. Utils::printSafe($runtimeType) . '".' .
|
||||||
|
'Either the ' . $returnType . ' type should provide a "resolveType" ' .
|
||||||
|
'function or each possible types should provide an "isTypeOf" function.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1307,7 +1300,12 @@ class Executor
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If a resolveType function is not given, then a default resolve behavior is
|
* If a resolveType function is not given, then a default resolve behavior is
|
||||||
* used which tests each possible type for the abstract type by calling
|
* used which attempts two strategies:
|
||||||
|
*
|
||||||
|
* First, See if the provided value has a `__typename` field defined, if so, use
|
||||||
|
* that value as name of the resolved type.
|
||||||
|
*
|
||||||
|
* Otherwise, test each possible type for the abstract type by calling
|
||||||
* isTypeOf for the object being coerced, returning the first type that matches.
|
* isTypeOf for the object being coerced, returning the first type that matches.
|
||||||
*
|
*
|
||||||
* @param $value
|
* @param $value
|
||||||
@ -1318,6 +1316,27 @@ class Executor
|
|||||||
*/
|
*/
|
||||||
private function defaultTypeResolver($value, $context, ResolveInfo $info, AbstractType $abstractType)
|
private function defaultTypeResolver($value, $context, ResolveInfo $info, AbstractType $abstractType)
|
||||||
{
|
{
|
||||||
|
// First, look for `__typename`.
|
||||||
|
if (
|
||||||
|
$value !== null &&
|
||||||
|
is_array($value) &&
|
||||||
|
isset($value['__typename']) &&
|
||||||
|
is_string($value['__typename'])
|
||||||
|
) {
|
||||||
|
return $value['__typename'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($abstractType instanceof InterfaceType && $info->schema->getConfig()->typeLoader) {
|
||||||
|
Warning::warnOnce(
|
||||||
|
"GraphQL Interface Type `{$abstractType->name}` returned `null` from it`s `resolveType` function ".
|
||||||
|
'for value: ' . Utils::printSafe($value) . '. Switching to slow resolution method using `isTypeOf` ' .
|
||||||
|
'of all possible implementations. It requires full schema scan and degrades query performance significantly. '.
|
||||||
|
' Make sure your `resolveType` always returns valid implementation or throws.',
|
||||||
|
Warning::WARNING_FULL_SCHEMA_SCAN
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, test each possible type.
|
||||||
$possibleTypes = $info->schema->getPossibleTypes($abstractType);
|
$possibleTypes = $info->schema->getPossibleTypes($abstractType);
|
||||||
$promisedIsTypeOfResults = [];
|
$promisedIsTypeOfResults = [];
|
||||||
|
|
||||||
|
@ -240,15 +240,6 @@ class ObjectType extends Type implements OutputType, CompositeType
|
|||||||
"{$this->name} may declare it implements {$iface->name} only once."
|
"{$this->name} may declare it implements {$iface->name} only once."
|
||||||
);
|
);
|
||||||
$implemented[$iface->name] = true;
|
$implemented[$iface->name] = true;
|
||||||
if (!isset($iface->config['resolveType'])) {
|
|
||||||
Utils::invariant(
|
|
||||||
isset($this->config['isTypeOf']),
|
|
||||||
"Interface Type {$iface->name} does not provide a \"resolveType\" " .
|
|
||||||
"function and implementing Type {$this->name} does not provide a " .
|
|
||||||
'"isTypeOf" function. There is no way to resolve this implementing ' .
|
|
||||||
'type during execution.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,15 +158,6 @@ class UnionType extends Type implements AbstractType, OutputType, CompositeType
|
|||||||
"{$this->name} can include {$objType->name} type only once."
|
"{$this->name} can include {$objType->name} type only once."
|
||||||
);
|
);
|
||||||
$includedTypeNames[$objType->name] = true;
|
$includedTypeNames[$objType->name] = true;
|
||||||
if (!isset($this->config['resolveType'])) {
|
|
||||||
Utils::invariant(
|
|
||||||
isset($objType->config['isTypeOf']) && is_callable($objType->config['isTypeOf']),
|
|
||||||
"Union type \"{$this->name}\" does not provide a \"resolveType\" " .
|
|
||||||
"function and possible type \"{$objType->name}\" does not provide an " .
|
|
||||||
'"isTypeOf" function. There is no way to resolve this possible type ' .
|
|
||||||
'during execution.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,21 +216,21 @@ class BuildSchema
|
|||||||
$directives = array_map([$this, 'getDirective'], $directiveDefs);
|
$directives = array_map([$this, 'getDirective'], $directiveDefs);
|
||||||
|
|
||||||
// If specified directives were not explicitly declared, add them.
|
// If specified directives were not explicitly declared, add them.
|
||||||
$skip = array_reduce($directives, function($hasSkip, $directive) {
|
$skip = array_reduce($directives, function ($hasSkip, $directive) {
|
||||||
return $hasSkip || $directive->name == 'skip';
|
return $hasSkip || $directive->name == 'skip';
|
||||||
});
|
});
|
||||||
if (!$skip) {
|
if (!$skip) {
|
||||||
$directives[] = Directive::skipDirective();
|
$directives[] = Directive::skipDirective();
|
||||||
}
|
}
|
||||||
|
|
||||||
$include = array_reduce($directives, function($hasInclude, $directive) {
|
$include = array_reduce($directives, function ($hasInclude, $directive) {
|
||||||
return $hasInclude || $directive->name == 'include';
|
return $hasInclude || $directive->name == 'include';
|
||||||
});
|
});
|
||||||
if (!$include) {
|
if (!$include) {
|
||||||
$directives[] = Directive::includeDirective();
|
$directives[] = Directive::includeDirective();
|
||||||
}
|
}
|
||||||
|
|
||||||
$deprecated = array_reduce($directives, function($hasDeprecated, $directive) {
|
$deprecated = array_reduce($directives, function ($hasDeprecated, $directive) {
|
||||||
return $hasDeprecated || $directive->name == 'deprecated';
|
return $hasDeprecated || $directive->name == 'deprecated';
|
||||||
});
|
});
|
||||||
if (!$deprecated) {
|
if (!$deprecated) {
|
||||||
@ -245,12 +245,12 @@ class BuildSchema
|
|||||||
'subscription' => $subscriptionTypeName ?
|
'subscription' => $subscriptionTypeName ?
|
||||||
$this->getObjectType($this->nodeMap[$subscriptionTypeName]) :
|
$this->getObjectType($this->nodeMap[$subscriptionTypeName]) :
|
||||||
null,
|
null,
|
||||||
'typeLoader' => function($name) {
|
'typeLoader' => function ($name) {
|
||||||
return $this->typeDefNamed($name);
|
return $this->typeDefNamed($name);
|
||||||
},
|
},
|
||||||
'directives' => $directives,
|
'directives' => $directives,
|
||||||
'astNode' => $schemaDef,
|
'astNode' => $schemaDef,
|
||||||
'types' => function() {
|
'types' => function () {
|
||||||
$types = [];
|
$types = [];
|
||||||
foreach ($this->nodeMap as $name => $def) {
|
foreach ($this->nodeMap as $name => $def) {
|
||||||
if (!isset($this->loadedTypeDefs[$name])) {
|
if (!isset($this->loadedTypeDefs[$name])) {
|
||||||
@ -269,7 +269,7 @@ class BuildSchema
|
|||||||
return new Directive([
|
return new Directive([
|
||||||
'name' => $directiveNode->name->value,
|
'name' => $directiveNode->name->value,
|
||||||
'description' => $this->getDescription($directiveNode),
|
'description' => $this->getDescription($directiveNode),
|
||||||
'locations' => Utils::map($directiveNode->locations, function($node) {
|
'locations' => Utils::map($directiveNode->locations, function ($node) {
|
||||||
return $node->value;
|
return $node->value;
|
||||||
}),
|
}),
|
||||||
'args' => $directiveNode->arguments ? FieldArgument::createMap($this->makeInputValues($directiveNode->arguments)) : null,
|
'args' => $directiveNode->arguments ? FieldArgument::createMap($this->makeInputValues($directiveNode->arguments)) : null,
|
||||||
@ -342,7 +342,7 @@ class BuildSchema
|
|||||||
$config = $fn($config, $this->nodeMap[$typeName], $this->nodeMap);
|
$config = $fn($config, $this->nodeMap[$typeName], $this->nodeMap);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Type config decorator passed to " . (static::class) . " threw an error ".
|
"Type config decorator passed to " . (static::class) . " threw an error " .
|
||||||
"when building $typeName type: {$e->getMessage()}",
|
"when building $typeName type: {$e->getMessage()}",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@ -352,7 +352,7 @@ class BuildSchema
|
|||||||
);
|
);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Type config decorator passed to " . (static::class) . " threw an error ".
|
"Type config decorator passed to " . (static::class) . " threw an error " .
|
||||||
"when building $typeName type: {$e->getMessage()}",
|
"when building $typeName type: {$e->getMessage()}",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@ -363,7 +363,7 @@ class BuildSchema
|
|||||||
}
|
}
|
||||||
if (!is_array($config) || isset($config[0])) {
|
if (!is_array($config) || isset($config[0])) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Type config decorator passed to " . (static::class) . " is expected to return an array, but got ".
|
"Type config decorator passed to " . (static::class) . " is expected to return an array, but got " .
|
||||||
Utils::getVariableType($config)
|
Utils::getVariableType($config)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -433,10 +433,10 @@ class BuildSchema
|
|||||||
return [
|
return [
|
||||||
'name' => $typeName,
|
'name' => $typeName,
|
||||||
'description' => $this->getDescription($def),
|
'description' => $this->getDescription($def),
|
||||||
'fields' => function() use ($def) {
|
'fields' => function () use ($def) {
|
||||||
return $this->makeFieldDefMap($def);
|
return $this->makeFieldDefMap($def);
|
||||||
},
|
},
|
||||||
'interfaces' => function() use ($def) {
|
'interfaces' => function () use ($def) {
|
||||||
return $this->makeImplementedInterfaces($def);
|
return $this->makeImplementedInterfaces($def);
|
||||||
},
|
},
|
||||||
'astNode' => $def
|
'astNode' => $def
|
||||||
@ -450,7 +450,7 @@ class BuildSchema
|
|||||||
function ($field) {
|
function ($field) {
|
||||||
return $field->name->value;
|
return $field->name->value;
|
||||||
},
|
},
|
||||||
function($field) {
|
function ($field) {
|
||||||
return [
|
return [
|
||||||
'type' => $this->produceOutputType($field->type),
|
'type' => $this->produceOutputType($field->type),
|
||||||
'description' => $this->getDescription($field),
|
'description' => $this->getDescription($field),
|
||||||
@ -479,7 +479,7 @@ class BuildSchema
|
|||||||
function ($value) {
|
function ($value) {
|
||||||
return $value->name->value;
|
return $value->name->value;
|
||||||
},
|
},
|
||||||
function($value) {
|
function ($value) {
|
||||||
$type = $this->produceInputType($value->type);
|
$type = $this->produceInputType($value->type);
|
||||||
$config = [
|
$config = [
|
||||||
'name' => $value->name->value,
|
'name' => $value->name->value,
|
||||||
@ -501,13 +501,10 @@ class BuildSchema
|
|||||||
return [
|
return [
|
||||||
'name' => $typeName,
|
'name' => $typeName,
|
||||||
'description' => $this->getDescription($def),
|
'description' => $this->getDescription($def),
|
||||||
'fields' => function() use ($def) {
|
'fields' => function () use ($def) {
|
||||||
return $this->makeFieldDefMap($def);
|
return $this->makeFieldDefMap($def);
|
||||||
},
|
},
|
||||||
'astNode' => $def,
|
'astNode' => $def
|
||||||
'resolveType' => function() {
|
|
||||||
$this->cannotExecuteSchema();
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,10 +516,10 @@ class BuildSchema
|
|||||||
'astNode' => $def,
|
'astNode' => $def,
|
||||||
'values' => Utils::keyValMap(
|
'values' => Utils::keyValMap(
|
||||||
$def->values,
|
$def->values,
|
||||||
function($enumValue) {
|
function ($enumValue) {
|
||||||
return $enumValue->name->value;
|
return $enumValue->name->value;
|
||||||
},
|
},
|
||||||
function($enumValue) {
|
function ($enumValue) {
|
||||||
return [
|
return [
|
||||||
'description' => $this->getDescription($enumValue),
|
'description' => $this->getDescription($enumValue),
|
||||||
'deprecationReason' => $this->getDeprecationReason($enumValue),
|
'deprecationReason' => $this->getDeprecationReason($enumValue),
|
||||||
@ -538,11 +535,10 @@ class BuildSchema
|
|||||||
return [
|
return [
|
||||||
'name' => $def->name->value,
|
'name' => $def->name->value,
|
||||||
'description' => $this->getDescription($def),
|
'description' => $this->getDescription($def),
|
||||||
'types' => Utils::map($def->types, function($typeNode) {
|
'types' => Utils::map($def->types, function ($typeNode) {
|
||||||
return $this->produceObjectType($typeNode);
|
return $this->produceObjectType($typeNode);
|
||||||
}),
|
}),
|
||||||
'astNode' => $def,
|
'astNode' => $def
|
||||||
'resolveType' => [$this, 'cannotExecuteSchema']
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,17 +548,17 @@ class BuildSchema
|
|||||||
'name' => $def->name->value,
|
'name' => $def->name->value,
|
||||||
'description' => $this->getDescription($def),
|
'description' => $this->getDescription($def),
|
||||||
'astNode' => $def,
|
'astNode' => $def,
|
||||||
'serialize' => function() {
|
'serialize' => function () {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
// Note: validation calls the parse functions to determine if a
|
// Note: validation calls the parse functions to determine if a
|
||||||
// literal value is correct. Returning null would cause use of custom
|
// literal value is correct. Returning null would cause use of custom
|
||||||
// scalars to always fail validation. Returning false causes them to
|
// scalars to always fail validation. Returning false causes them to
|
||||||
// always pass validation.
|
// always pass validation.
|
||||||
'parseValue' => function() {
|
'parseValue' => function () {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
'parseLiteral' => function() {
|
'parseLiteral' => function () {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@ -573,7 +569,9 @@ class BuildSchema
|
|||||||
return [
|
return [
|
||||||
'name' => $def->name->value,
|
'name' => $def->name->value,
|
||||||
'description' => $this->getDescription($def),
|
'description' => $this->getDescription($def),
|
||||||
'fields' => function() use ($def) { return $this->makeInputValues($def->fields); },
|
'fields' => function () use ($def) {
|
||||||
|
return $this->makeInputValues($def->fields);
|
||||||
|
},
|
||||||
'astNode' => $def,
|
'astNode' => $def,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -611,7 +609,7 @@ class BuildSchema
|
|||||||
{
|
{
|
||||||
$loc = $node->loc;
|
$loc = $node->loc;
|
||||||
if (!$loc || !$loc->startToken) {
|
if (!$loc || !$loc->startToken) {
|
||||||
return ;
|
return;
|
||||||
}
|
}
|
||||||
$comments = [];
|
$comments = [];
|
||||||
$token = $loc->startToken->prev;
|
$token = $loc->startToken->prev;
|
||||||
@ -644,12 +642,4 @@ class BuildSchema
|
|||||||
$doc = $source instanceof DocumentNode ? $source : Parser::parse($source);
|
$doc = $source instanceof DocumentNode ? $source : Parser::parse($source);
|
||||||
return self::buildAST($doc, $typeConfigDecorator);
|
return self::buildAST($doc, $typeConfigDecorator);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public function cannotExecuteSchema()
|
|
||||||
{
|
|
||||||
throw new Error(
|
|
||||||
'Generated Schema cannot use Interface or Union types for execution.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -87,9 +87,7 @@ class AbstractPromiseTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
|
|
||||||
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
|
||||||
$result = GraphQL::execute($schema, $query);
|
$result = GraphQL::execute($schema, $query);
|
||||||
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
|
||||||
|
|
||||||
$expected = [
|
$expected = [
|
||||||
'data' => [
|
'data' => [
|
||||||
@ -174,9 +172,7 @@ class AbstractPromiseTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
|
|
||||||
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
|
||||||
$result = GraphQL::execute($schema, $query);
|
$result = GraphQL::execute($schema, $query);
|
||||||
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
|
||||||
|
|
||||||
$expected = [
|
$expected = [
|
||||||
'data' => [
|
'data' => [
|
||||||
|
@ -256,9 +256,7 @@ class UnionInterfaceTest extends \PHPUnit_Framework_TestCase
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
|
||||||
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
||||||
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -294,9 +292,7 @@ class UnionInterfaceTest extends \PHPUnit_Framework_TestCase
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray(true));
|
||||||
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
|
||||||
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -351,9 +347,7 @@ class UnionInterfaceTest extends \PHPUnit_Framework_TestCase
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
|
||||||
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
||||||
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,10 +74,7 @@ class DefinitionTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
$this->objectType = new ObjectType([
|
$this->objectType = new ObjectType(['name' => 'Object']);
|
||||||
'name' => 'Object',
|
|
||||||
'isTypeOf' => function() {return true;}
|
|
||||||
]);
|
|
||||||
$this->interfaceType = new InterfaceType(['name' => 'Interface']);
|
$this->interfaceType = new InterfaceType(['name' => 'Interface']);
|
||||||
$this->unionType = new UnionType(['name' => 'Union', 'types' => [$this->objectType]]);
|
$this->unionType = new UnionType(['name' => 'Union', 'types' => [$this->objectType]]);
|
||||||
$this->enumType = new EnumType(['name' => 'Enum']);
|
$this->enumType = new EnumType(['name' => 'Enum']);
|
||||||
@ -363,7 +360,6 @@ class DefinitionTest extends \PHPUnit_Framework_TestCase
|
|||||||
'f' => ['type' => Type::int()]
|
'f' => ['type' => Type::int()]
|
||||||
],
|
],
|
||||||
'interfaces' => [$someInterface],
|
'interfaces' => [$someInterface],
|
||||||
'isTypeOf' => function() {return true;}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$schema = new Schema([
|
$schema = new Schema([
|
||||||
@ -391,7 +387,6 @@ class DefinitionTest extends \PHPUnit_Framework_TestCase
|
|||||||
'f' => ['type' => Type::int()]
|
'f' => ['type' => Type::int()]
|
||||||
],
|
],
|
||||||
'interfaces' => function() use (&$someInterface) { return [$someInterface]; },
|
'interfaces' => function() use (&$someInterface) { return [$someInterface]; },
|
||||||
'isTypeOf' => function() {return true;}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$someInterface = new InterfaceType([
|
$someInterface = new InterfaceType([
|
||||||
|
@ -58,24 +58,15 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$this->ObjectWithIsTypeOf = new ObjectType([
|
$this->ObjectWithIsTypeOf = new ObjectType([
|
||||||
'name' => 'ObjectWithIsTypeOf',
|
'name' => 'ObjectWithIsTypeOf',
|
||||||
'isTypeOf' => function() {
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
'fields' => [ 'f' => [ 'type' => Type::string() ]]
|
'fields' => [ 'f' => [ 'type' => Type::string() ]]
|
||||||
]);
|
]);
|
||||||
$this->SomeUnionType = new UnionType([
|
$this->SomeUnionType = new UnionType([
|
||||||
'name' => 'SomeUnion',
|
'name' => 'SomeUnion',
|
||||||
'resolveType' => function() {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
'types' => [ $this->SomeObjectType ]
|
'types' => [ $this->SomeObjectType ]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->SomeInterfaceType = new InterfaceType([
|
$this->SomeInterfaceType = new InterfaceType([
|
||||||
'name' => 'SomeInterface',
|
'name' => 'SomeInterface',
|
||||||
'resolveType' => function() {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
'fields' => [ 'f' => ['type' => Type::string() ]]
|
'fields' => [ 'f' => ['type' => Type::string() ]]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -404,7 +395,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function() {},
|
|
||||||
'fields' => [ 'f' => [ 'type' => Type::string() ]],
|
'fields' => [ 'f' => [ 'type' => Type::string() ]],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -736,8 +726,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterfaceType = new InterfaceType([
|
$AnotherInterfaceType = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => ['f' => ['type' => Type::string()]]
|
'fields' => ['f' => ['type' => Type::string()]]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -756,8 +744,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterfaceType = new InterfaceType([
|
$AnotherInterfaceType = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => ['f' => ['type' => Type::string()]]
|
'fields' => ['f' => ['type' => Type::string()]]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -795,14 +781,11 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$NonUniqInterface = new InterfaceType([
|
$NonUniqInterface = new InterfaceType([
|
||||||
'name' => 'NonUniqInterface',
|
'name' => 'NonUniqInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => ['f' => ['type' => Type::string()]],
|
'fields' => ['f' => ['type' => Type::string()]],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function(){},
|
|
||||||
'fields' => ['f' => ['type' => Type::string()]],
|
'fields' => ['f' => ['type' => Type::string()]],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -851,9 +834,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$schema = $this->schemaWithFieldType(new UnionType([
|
$schema = $this->schemaWithFieldType(new UnionType([
|
||||||
'name' => 'SomeUnion',
|
'name' => 'SomeUnion',
|
||||||
'resolveType' => function () {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
'types' => [$this->SomeObjectType],
|
'types' => [$this->SomeObjectType],
|
||||||
]));
|
]));
|
||||||
$schema->assertValid();
|
$schema->assertValid();
|
||||||
@ -866,9 +846,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$schema = $this->schemaWithFieldType(new UnionType([
|
$schema = $this->schemaWithFieldType(new UnionType([
|
||||||
'name' => 'SomeUnion',
|
'name' => 'SomeUnion',
|
||||||
'resolveType' => function () {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
'types' => function () {
|
'types' => function () {
|
||||||
return [$this->SomeObjectType];
|
return [$this->SomeObjectType];
|
||||||
},
|
},
|
||||||
@ -887,7 +864,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
$this->schemaWithFieldType(new UnionType([
|
$this->schemaWithFieldType(new UnionType([
|
||||||
'name' => 'SomeUnion',
|
'name' => 'SomeUnion',
|
||||||
'resolveType' => function() {return null;}
|
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -898,8 +874,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$schema = $this->schemaWithFieldType(new UnionType([
|
$schema = $this->schemaWithFieldType(new UnionType([
|
||||||
'name' => 'SomeUnion',
|
'name' => 'SomeUnion',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'types' => []
|
'types' => []
|
||||||
]));
|
]));
|
||||||
|
|
||||||
@ -921,8 +895,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
$this->schemaWithFieldType(new UnionType([
|
$this->schemaWithFieldType(new UnionType([
|
||||||
'name' => 'SomeUnion',
|
'name' => 'SomeUnion',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'types' => $this->SomeObjectType
|
'types' => $this->SomeObjectType
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
@ -934,7 +906,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$schema = $this->schemaWithFieldType(new UnionType([
|
$schema = $this->schemaWithFieldType(new UnionType([
|
||||||
'name' => 'SomeUnion',
|
'name' => 'SomeUnion',
|
||||||
'resolveType' => function(){},
|
|
||||||
'types' => [
|
'types' => [
|
||||||
$this->SomeObjectType,
|
$this->SomeObjectType,
|
||||||
$this->SomeObjectType,
|
$this->SomeObjectType,
|
||||||
@ -1193,8 +1164,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterfaceType = new InterfaceType([
|
$AnotherInterfaceType = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => ['f' => ['type' => Type::string()]]
|
'fields' => ['f' => ['type' => Type::string()]]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -1234,8 +1203,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterfaceType = new InterfaceType([
|
$AnotherInterfaceType = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => ['f' => ['type' => Type::string()]]
|
'fields' => ['f' => ['type' => Type::string()]]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -1270,32 +1237,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
$type->assertValid();
|
$type->assertValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @it rejects an Interface type not defining resolveType with implementing type not defining isTypeOf
|
|
||||||
*/
|
|
||||||
public function testRejectsAnInterfaceTypeNotDefiningResolveTypeWithImplementingTypeNotDefiningIsTypeOf()
|
|
||||||
{
|
|
||||||
$InterfaceTypeWithoutResolveType = new InterfaceType([
|
|
||||||
'name' => 'InterfaceTypeWithoutResolveType',
|
|
||||||
'fields' => ['f' => ['type' => Type::string()]]
|
|
||||||
]);
|
|
||||||
|
|
||||||
$schema = $this->schemaWithFieldType(new ObjectType([
|
|
||||||
'name' => 'SomeObject',
|
|
||||||
'interfaces' => [$InterfaceTypeWithoutResolveType],
|
|
||||||
'fields' => ['f' => ['type' => Type::string()]]
|
|
||||||
]));
|
|
||||||
|
|
||||||
$this->setExpectedException(
|
|
||||||
InvariantViolation::class,
|
|
||||||
'Interface Type InterfaceTypeWithoutResolveType does not provide a "resolveType" function and implementing '.
|
|
||||||
'Type SomeObject does not provide a "isTypeOf" function. There is no way to resolve this implementing type '.
|
|
||||||
'during execution.'
|
|
||||||
);
|
|
||||||
|
|
||||||
$schema->assertValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DESCRIBE: Type System: Union types must be resolvable
|
// DESCRIBE: Type System: Union types must be resolvable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1305,8 +1246,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$schema = $this->schemaWithFieldType(new UnionType([
|
$schema = $this->schemaWithFieldType(new UnionType([
|
||||||
'name' => 'SomeUnion',
|
'name' => 'SomeUnion',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'types' => [$this->SomeObjectType],
|
'types' => [$this->SomeObjectType],
|
||||||
]));
|
]));
|
||||||
$schema->assertValid();
|
$schema->assertValid();
|
||||||
@ -1332,8 +1271,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$schema = $this->schemaWithFieldType(new UnionType([
|
$schema = $this->schemaWithFieldType(new UnionType([
|
||||||
'name' => 'SomeUnion',
|
'name' => 'SomeUnion',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'types' => [$this->ObjectWithIsTypeOf],
|
'types' => [$this->ObjectWithIsTypeOf],
|
||||||
]));
|
]));
|
||||||
$schema->assertValid();
|
$schema->assertValid();
|
||||||
@ -1358,25 +1295,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
$schema->assertValid();
|
$schema->assertValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @it rejects a Union type not defining resolveType of Object types not defining isTypeOf
|
|
||||||
*/
|
|
||||||
public function testRejectsAUnionTypeNotDefiningResolveTypeOfObjectTypesNotDefiningIsTypeOf()
|
|
||||||
{
|
|
||||||
$schema = $this->schemaWithFieldType(new UnionType([
|
|
||||||
'name' => 'SomeUnion',
|
|
||||||
'types' => [$this->SomeObjectType],
|
|
||||||
]));
|
|
||||||
|
|
||||||
$this->setExpectedException(
|
|
||||||
InvariantViolation::class,
|
|
||||||
'Union type "SomeUnion" does not provide a "resolveType" function and possible type "SomeObject" '.
|
|
||||||
'does not provide an "isTypeOf" function. There is no way to resolve this possible type during execution.'
|
|
||||||
);
|
|
||||||
|
|
||||||
$schema->assertValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
// DESCRIBE: Type System: Scalar types must be serializable
|
// DESCRIBE: Type System: Scalar types must be serializable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1747,8 +1665,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterfaceType = new InterfaceType([
|
$AnotherInterfaceType = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => ['f' => ['type' => Type::string()]]
|
'fields' => ['f' => ['type' => Type::string()]]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -2085,8 +2001,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => [
|
'field' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
@ -2121,8 +2035,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => [
|
'field' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
@ -2158,8 +2070,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => [
|
'field' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
@ -2195,8 +2105,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => [
|
'field' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
@ -2238,8 +2146,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => [
|
'field' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
@ -2274,8 +2180,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => ['type' => Type::string()]
|
'field' => ['type' => Type::string()]
|
||||||
]
|
]
|
||||||
@ -2318,8 +2222,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => ['type' => $TypeA]
|
'field' => ['type' => $TypeA]
|
||||||
]
|
]
|
||||||
@ -2350,8 +2252,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => function () use (&$AnotherInterface) {
|
'fields' => function () use (&$AnotherInterface) {
|
||||||
return [
|
return [
|
||||||
'field' => ['type' => $AnotherInterface]
|
'field' => ['type' => $AnotherInterface]
|
||||||
@ -2380,8 +2280,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => ['type' => $this->SomeUnionType]
|
'field' => ['type' => $this->SomeUnionType]
|
||||||
]
|
]
|
||||||
@ -2406,8 +2304,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => [
|
'field' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
@ -2445,8 +2341,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => [
|
'field' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
@ -2487,8 +2381,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => ['type' => Type::nonNull(Type::listOf(Type::string()))]
|
'field' => ['type' => Type::nonNull(Type::listOf(Type::string()))]
|
||||||
]
|
]
|
||||||
@ -2513,8 +2405,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => ['type' => Type::listOf(Type::string())]
|
'field' => ['type' => Type::listOf(Type::string())]
|
||||||
]
|
]
|
||||||
@ -2545,8 +2435,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => ['type' => Type::string()]
|
'field' => ['type' => Type::string()]
|
||||||
]
|
]
|
||||||
@ -2575,8 +2463,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => ['type' => Type::string()]
|
'field' => ['type' => Type::string()]
|
||||||
]
|
]
|
||||||
@ -2601,8 +2487,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$AnotherInterface = new InterfaceType([
|
$AnotherInterface = new InterfaceType([
|
||||||
'name' => 'AnotherInterface',
|
'name' => 'AnotherInterface',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'field' => ['type' => Type::nonNull(Type::string())]
|
'field' => ['type' => Type::nonNull(Type::string())]
|
||||||
]
|
]
|
||||||
@ -2820,8 +2704,6 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$BadUnionType = new UnionType([
|
$BadUnionType = new UnionType([
|
||||||
'name' => 'BadUnion',
|
'name' => 'BadUnion',
|
||||||
'resolveType' => function () {
|
|
||||||
},
|
|
||||||
'types' => [$type],
|
'types' => [$type],
|
||||||
]);
|
]);
|
||||||
return new Schema([
|
return new Schema([
|
||||||
|
@ -36,8 +36,8 @@ class BuildSchemaTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
'));
|
'));
|
||||||
|
|
||||||
$result = GraphQL::execute($schema, '{ str }', ['str' => 123]);
|
$result = GraphQL::executeQuery($schema, '{ str }', ['str' => 123]);
|
||||||
$this->assertEquals($result['data'], ['str' => 123]);
|
$this->assertEquals(['str' => 123], $result->toArray(true)['data']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,7 +52,7 @@ class BuildSchemaTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
");
|
");
|
||||||
|
|
||||||
$result = GraphQL::execute(
|
$result = GraphQL::executeQuery(
|
||||||
$schema,
|
$schema,
|
||||||
'{ add(x: 34, y: 55) }',
|
'{ add(x: 34, y: 55) }',
|
||||||
[
|
[
|
||||||
@ -61,7 +61,7 @@ class BuildSchemaTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
$this->assertEquals($result, ['data' => ['add' => 89]]);
|
$this->assertEquals(['data' => ['add' => 89]], $result->toArray(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -447,6 +447,135 @@ type WorldTwo {
|
|||||||
$this->assertEquals($output, $body);
|
$this->assertEquals($output, $body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it Specifying Union type using __typename
|
||||||
|
*/
|
||||||
|
public function testSpecifyingUnionTypeUsingTypename()
|
||||||
|
{
|
||||||
|
$schema = BuildSchema::buildAST(Parser::parse('
|
||||||
|
schema {
|
||||||
|
query: Root
|
||||||
|
}
|
||||||
|
|
||||||
|
type Root {
|
||||||
|
fruits: [Fruit]
|
||||||
|
}
|
||||||
|
|
||||||
|
union Fruit = Apple | Banana
|
||||||
|
|
||||||
|
type Apple {
|
||||||
|
color: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type Banana {
|
||||||
|
length: Int
|
||||||
|
}
|
||||||
|
'));
|
||||||
|
$query = '
|
||||||
|
{
|
||||||
|
fruits {
|
||||||
|
... on Apple {
|
||||||
|
color
|
||||||
|
}
|
||||||
|
... on Banana {
|
||||||
|
length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
';
|
||||||
|
$root = [
|
||||||
|
'fruits' => [
|
||||||
|
[
|
||||||
|
'color' => 'green',
|
||||||
|
'__typename' => 'Apple',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'length' => 5,
|
||||||
|
'__typename' => 'Banana',
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$expected = [
|
||||||
|
'data' => [
|
||||||
|
'fruits' => [
|
||||||
|
['color' => 'green'],
|
||||||
|
['length' => 5],
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = GraphQL::executeQuery($schema, $query, $root);
|
||||||
|
$this->assertEquals($expected, $result->toArray(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @it Specifying Interface type using __typename
|
||||||
|
*/
|
||||||
|
public function testSpecifyingInterfaceUsingTypename()
|
||||||
|
{
|
||||||
|
$schema = BuildSchema::buildAST(Parser::parse('
|
||||||
|
schema {
|
||||||
|
query: Root
|
||||||
|
}
|
||||||
|
|
||||||
|
type Root {
|
||||||
|
characters: [Character]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Character {
|
||||||
|
name: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Human implements Character {
|
||||||
|
name: String!
|
||||||
|
totalCredits: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Droid implements Character {
|
||||||
|
name: String!
|
||||||
|
primaryFunction: String
|
||||||
|
}
|
||||||
|
'));
|
||||||
|
$query = '
|
||||||
|
{
|
||||||
|
characters {
|
||||||
|
name
|
||||||
|
... on Human {
|
||||||
|
totalCredits
|
||||||
|
}
|
||||||
|
... on Droid {
|
||||||
|
primaryFunction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
';
|
||||||
|
$root = [
|
||||||
|
'characters' => [
|
||||||
|
[
|
||||||
|
'name' => 'Han Solo',
|
||||||
|
'totalCredits' => 10,
|
||||||
|
'__typename' => 'Human',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'R2-D2',
|
||||||
|
'primaryFunction' => 'Astromech',
|
||||||
|
'__typename' => 'Droid',
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
$expected = [
|
||||||
|
'data' => [
|
||||||
|
'characters' => [
|
||||||
|
['name' => 'Han Solo', 'totalCredits' => 10],
|
||||||
|
['name' => 'R2-D2', 'primaryFunction' => 'Astromech'],
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = GraphQL::executeQuery($schema, $query, $root);
|
||||||
|
$this->assertEquals($expected, $result->toArray(true));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @it CustomScalar
|
* @it CustomScalar
|
||||||
*/
|
*/
|
||||||
@ -1093,9 +1222,8 @@ interface Hello {
|
|||||||
$this->assertInstanceOf(InterfaceTypeDefinitionNode::class, $node);
|
$this->assertInstanceOf(InterfaceTypeDefinitionNode::class, $node);
|
||||||
$this->assertEquals('Hello', $defaultConfig['name']);
|
$this->assertEquals('Hello', $defaultConfig['name']);
|
||||||
$this->assertInstanceOf(\Closure::class, $defaultConfig['fields']);
|
$this->assertInstanceOf(\Closure::class, $defaultConfig['fields']);
|
||||||
$this->assertInstanceOf(\Closure::class, $defaultConfig['resolveType']);
|
|
||||||
$this->assertArrayHasKey('description', $defaultConfig);
|
$this->assertArrayHasKey('description', $defaultConfig);
|
||||||
$this->assertCount(5, $defaultConfig);
|
$this->assertCount(4, $defaultConfig);
|
||||||
$this->assertEquals(array_keys($allNodesMap), ['Query', 'Color', 'Hello']);
|
$this->assertEquals(array_keys($allNodesMap), ['Query', 'Color', 'Hello']);
|
||||||
$this->assertEquals('My description of Hello', $schema->getType('Hello')->description);
|
$this->assertEquals('My description of Hello', $schema->getType('Hello')->description);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* FindBreakingChanges tests
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace GraphQL\Tests\Utils;
|
namespace GraphQL\Tests\Utils;
|
||||||
|
|
||||||
use GraphQL\Type\Definition\EnumType;
|
use GraphQL\Type\Definition\EnumType;
|
||||||
@ -16,7 +12,6 @@ use GraphQL\Utils\FindBreakingChanges;
|
|||||||
|
|
||||||
class FindBreakingChangesTest extends \PHPUnit_Framework_TestCase
|
class FindBreakingChangesTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
private $queryType;
|
private $queryType;
|
||||||
|
|
||||||
public function setUp()
|
public function setUp()
|
||||||
@ -88,7 +83,7 @@ class FindBreakingChangesTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$unionType = new UnionType([
|
$unionType = new UnionType([
|
||||||
'name' => 'Type1',
|
'name' => 'Type1',
|
||||||
'types' => [new ObjectType(['name' => 'blah'])],
|
'types' => [$objectType],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$oldSchema = new Schema([
|
$oldSchema = new Schema([
|
||||||
@ -510,16 +505,12 @@ class FindBreakingChangesTest extends \PHPUnit_Framework_TestCase
|
|||||||
$oldUnionType = new UnionType([
|
$oldUnionType = new UnionType([
|
||||||
'name' => 'UnionType1',
|
'name' => 'UnionType1',
|
||||||
'types' => [$type1, $type2],
|
'types' => [$type1, $type2],
|
||||||
'resolveType' => function () {
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
$newUnionType = new UnionType([
|
$newUnionType = new UnionType([
|
||||||
'name' => 'UnionType1',
|
'name' => 'UnionType1',
|
||||||
'types' => [$type1a, $type3],
|
'types' => [$type1a, $type3],
|
||||||
'resolveType' => function () {
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$oldSchema = new Schema([
|
$oldSchema = new Schema([
|
||||||
@ -978,8 +969,6 @@ class FindBreakingChangesTest extends \PHPUnit_Framework_TestCase
|
|||||||
'fields' => [
|
'fields' => [
|
||||||
'field1' => Type::string()
|
'field1' => Type::string()
|
||||||
],
|
],
|
||||||
'resolveType' => function () {
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
$oldType = new ObjectType([
|
$oldType = new ObjectType([
|
||||||
'name' => 'Type1',
|
'name' => 'Type1',
|
||||||
@ -1099,15 +1088,11 @@ class FindBreakingChangesTest extends \PHPUnit_Framework_TestCase
|
|||||||
$unionTypeThatLosesATypeOld = new UnionType([
|
$unionTypeThatLosesATypeOld = new UnionType([
|
||||||
'name' => 'UnionTypeThatLosesAType',
|
'name' => 'UnionTypeThatLosesAType',
|
||||||
'types' => [$typeInUnion1, $typeInUnion2],
|
'types' => [$typeInUnion1, $typeInUnion2],
|
||||||
'resolveType' => function () {
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$unionTypeThatLosesATypeNew = new UnionType([
|
$unionTypeThatLosesATypeNew = new UnionType([
|
||||||
'name' => 'UnionTypeThatLosesAType',
|
'name' => 'UnionTypeThatLosesAType',
|
||||||
'types' => [$typeInUnion1],
|
'types' => [$typeInUnion1],
|
||||||
'resolveType' => function () {
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$enumTypeThatLosesAValueOld = new EnumType([
|
$enumTypeThatLosesAValueOld = new EnumType([
|
||||||
@ -1132,8 +1117,6 @@ class FindBreakingChangesTest extends \PHPUnit_Framework_TestCase
|
|||||||
'fields' => [
|
'fields' => [
|
||||||
'field1' => Type::string()
|
'field1' => Type::string()
|
||||||
],
|
],
|
||||||
'resolveType' => function () {
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$typeThatLosesInterfaceOld = new ObjectType([
|
$typeThatLosesInterfaceOld = new ObjectType([
|
||||||
@ -1353,15 +1336,11 @@ class FindBreakingChangesTest extends \PHPUnit_Framework_TestCase
|
|||||||
$oldUnionType = new UnionType([
|
$oldUnionType = new UnionType([
|
||||||
'name' => 'UnionType1',
|
'name' => 'UnionType1',
|
||||||
'types' => [$type1],
|
'types' => [$type1],
|
||||||
'resolveType' => function () {
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$newUnionType = new UnionType([
|
$newUnionType = new UnionType([
|
||||||
'name' => 'UnionType1',
|
'name' => 'UnionType1',
|
||||||
'types' => [$type1a, $type2],
|
'types' => [$type1a, $type2],
|
||||||
'resolveType' => function () {
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$oldSchema = new Schema([
|
$oldSchema = new Schema([
|
||||||
@ -1452,15 +1431,11 @@ class FindBreakingChangesTest extends \PHPUnit_Framework_TestCase
|
|||||||
$unionTypeThatGainsATypeOld = new UnionType([
|
$unionTypeThatGainsATypeOld = new UnionType([
|
||||||
'name' => 'UnionType1',
|
'name' => 'UnionType1',
|
||||||
'types' => [$typeInUnion1],
|
'types' => [$typeInUnion1],
|
||||||
'resolveType' => function () {
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$unionTypeThatGainsATypeNew = new UnionType([
|
$unionTypeThatGainsATypeNew = new UnionType([
|
||||||
'name' => 'UnionType1',
|
'name' => 'UnionType1',
|
||||||
'types' => [$typeInUnion1, $typeInUnion2],
|
'types' => [$typeInUnion1, $typeInUnion2],
|
||||||
'resolveType' => function () {
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$oldSchema = new Schema([
|
$oldSchema = new Schema([
|
||||||
@ -1498,4 +1473,4 @@ class FindBreakingChangesTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$this->assertEquals($expectedDangerousChanges, FindBreakingChanges::findDangerousChanges($oldSchema, $newSchema));
|
$this->assertEquals($expectedDangerousChanges, FindBreakingChanges::findDangerousChanges($oldSchema, $newSchema));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,7 +360,6 @@ type Root {
|
|||||||
{
|
{
|
||||||
$fooType = new InterfaceType([
|
$fooType = new InterfaceType([
|
||||||
'name' => 'Foo',
|
'name' => 'Foo',
|
||||||
'resolveType' => function() { return null; },
|
|
||||||
'fields' => ['str' => ['type' => Type::string()]]
|
'fields' => ['str' => ['type' => Type::string()]]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -406,13 +405,11 @@ type Root {
|
|||||||
{
|
{
|
||||||
$fooType = new InterfaceType([
|
$fooType = new InterfaceType([
|
||||||
'name' => 'Foo',
|
'name' => 'Foo',
|
||||||
'resolveType' => function() { return null; },
|
|
||||||
'fields' => ['str' => ['type' => Type::string()]]
|
'fields' => ['str' => ['type' => Type::string()]]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$baazType = new InterfaceType([
|
$baazType = new InterfaceType([
|
||||||
'name' => 'Baaz',
|
'name' => 'Baaz',
|
||||||
'resolveType' => function() { return null; },
|
|
||||||
'fields' => ['int' => ['type' => Type::int()]]
|
'fields' => ['int' => ['type' => Type::int()]]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -476,13 +473,11 @@ type Root {
|
|||||||
|
|
||||||
$singleUnion = new UnionType([
|
$singleUnion = new UnionType([
|
||||||
'name' => 'SingleUnion',
|
'name' => 'SingleUnion',
|
||||||
'resolveType' => function() { return null; },
|
|
||||||
'types' => [$fooType]
|
'types' => [$fooType]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$multipleUnion = new UnionType([
|
$multipleUnion = new UnionType([
|
||||||
'name' => 'MultipleUnion',
|
'name' => 'MultipleUnion',
|
||||||
'resolveType' => function() { return null; },
|
|
||||||
'types' => [$fooType, $barType]
|
'types' => [$fooType, $barType]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -1098,4 +1093,4 @@ enum __TypeKind {
|
|||||||
EOT;
|
EOT;
|
||||||
$this->assertEquals($introspectionSchema, $output);
|
$this->assertEquals($introspectionSchema, $output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -795,7 +795,6 @@ class OverlappingFieldsCanBeMergedTest extends TestCase
|
|||||||
|
|
||||||
$SomeBox = new InterfaceType([
|
$SomeBox = new InterfaceType([
|
||||||
'name' => 'SomeBox',
|
'name' => 'SomeBox',
|
||||||
'resolveType' => function() use (&$StringBox) {return $StringBox;},
|
|
||||||
'fields' => function() use (&$SomeBox) {
|
'fields' => function() use (&$SomeBox) {
|
||||||
return [
|
return [
|
||||||
'deepBox' => ['type' => $SomeBox],
|
'deepBox' => ['type' => $SomeBox],
|
||||||
@ -837,7 +836,6 @@ class OverlappingFieldsCanBeMergedTest extends TestCase
|
|||||||
|
|
||||||
$NonNullStringBox1 = new InterfaceType([
|
$NonNullStringBox1 = new InterfaceType([
|
||||||
'name' => 'NonNullStringBox1',
|
'name' => 'NonNullStringBox1',
|
||||||
'resolveType' => function() use (&$StringBox) {return $StringBox;},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'scalar' => [ 'type' => Type::nonNull(Type::string()) ]
|
'scalar' => [ 'type' => Type::nonNull(Type::string()) ]
|
||||||
]
|
]
|
||||||
@ -855,7 +853,6 @@ class OverlappingFieldsCanBeMergedTest extends TestCase
|
|||||||
|
|
||||||
$NonNullStringBox2 = new InterfaceType([
|
$NonNullStringBox2 = new InterfaceType([
|
||||||
'name' => 'NonNullStringBox2',
|
'name' => 'NonNullStringBox2',
|
||||||
'resolveType' => function() use (&$StringBox) {return $StringBox;},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'scalar' => ['type' => Type::nonNull(Type::string())]
|
'scalar' => ['type' => Type::nonNull(Type::string())]
|
||||||
]
|
]
|
||||||
|
@ -67,7 +67,6 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$Dog = new ObjectType([
|
$Dog = new ObjectType([
|
||||||
'name' => 'Dog',
|
'name' => 'Dog',
|
||||||
'isTypeOf' => function() {return true;},
|
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'name' => [
|
'name' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
@ -94,7 +93,6 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$Cat = new ObjectType([
|
$Cat = new ObjectType([
|
||||||
'name' => 'Cat',
|
'name' => 'Cat',
|
||||||
'isTypeOf' => function() {return true;},
|
|
||||||
'fields' => function() use (&$FurColor) {
|
'fields' => function() use (&$FurColor) {
|
||||||
return [
|
return [
|
||||||
'name' => [
|
'name' => [
|
||||||
@ -113,10 +111,6 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
$CatOrDog = new UnionType([
|
$CatOrDog = new UnionType([
|
||||||
'name' => 'CatOrDog',
|
'name' => 'CatOrDog',
|
||||||
'types' => [$Dog, $Cat],
|
'types' => [$Dog, $Cat],
|
||||||
'resolveType' => function($value) {
|
|
||||||
// not used for validation
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$Intelligent = new InterfaceType([
|
$Intelligent = new InterfaceType([
|
||||||
@ -129,7 +123,6 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
$Human = null;
|
$Human = null;
|
||||||
$Human = new ObjectType([
|
$Human = new ObjectType([
|
||||||
'name' => 'Human',
|
'name' => 'Human',
|
||||||
'isTypeOf' => function() {return true;},
|
|
||||||
'interfaces' => [$Being, $Intelligent],
|
'interfaces' => [$Being, $Intelligent],
|
||||||
'fields' => function() use (&$Human, $Pet) {
|
'fields' => function() use (&$Human, $Pet) {
|
||||||
return [
|
return [
|
||||||
@ -146,7 +139,6 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$Alien = new ObjectType([
|
$Alien = new ObjectType([
|
||||||
'name' => 'Alien',
|
'name' => 'Alien',
|
||||||
'isTypeOf' => function() {return true;},
|
|
||||||
'interfaces' => [$Being, $Intelligent],
|
'interfaces' => [$Being, $Intelligent],
|
||||||
'fields' => [
|
'fields' => [
|
||||||
'iq' => ['type' => Type::int()],
|
'iq' => ['type' => Type::int()],
|
||||||
@ -161,19 +153,11 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
|
|||||||
$DogOrHuman = new UnionType([
|
$DogOrHuman = new UnionType([
|
||||||
'name' => 'DogOrHuman',
|
'name' => 'DogOrHuman',
|
||||||
'types' => [$Dog, $Human],
|
'types' => [$Dog, $Human],
|
||||||
'resolveType' => function() {
|
|
||||||
// not used for validation
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$HumanOrAlien = new UnionType([
|
$HumanOrAlien = new UnionType([
|
||||||
'name' => 'HumanOrAlien',
|
'name' => 'HumanOrAlien',
|
||||||
'types' => [$Human, $Alien],
|
'types' => [$Human, $Alien],
|
||||||
'resolveType' => function() {
|
|
||||||
// not used for validation
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$FurColor = new EnumType([
|
$FurColor = new EnumType([
|
||||||
|
Loading…
Reference in New Issue
Block a user