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:
Daniel Tschinder 2018-02-09 12:54:34 +01:00
parent 7705e50e44
commit 4e26de3588
13 changed files with 198 additions and 261 deletions

View File

@ -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 = [];

View File

@ -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.'
);
}
} }
} }
} }

View File

@ -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.'
);
}
} }
} }
} }

View File

@ -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.'
);
}
}

View File

@ -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' => [

View File

@ -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);
} }
/** /**

View File

@ -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([

View File

@ -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([

View File

@ -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);
} }

View File

@ -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));
} }
} }

View File

@ -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);
} }
} }

View File

@ -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())]
] ]

View File

@ -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([