2015-07-15 20:05:46 +03:00
|
|
|
<?php
|
|
|
|
namespace GraphQL\Executor;
|
|
|
|
|
2015-08-17 17:01:55 +03:00
|
|
|
require_once __DIR__ . '/TestClasses.php';
|
|
|
|
|
2015-07-15 20:05:46 +03:00
|
|
|
use GraphQL\Language\Parser;
|
|
|
|
use GraphQL\Schema;
|
|
|
|
use GraphQL\Type\Definition\Config;
|
|
|
|
use GraphQL\Type\Definition\InterfaceType;
|
|
|
|
use GraphQL\Type\Definition\ObjectType;
|
|
|
|
use GraphQL\Type\Definition\Type;
|
|
|
|
use GraphQL\Type\Definition\UnionType;
|
|
|
|
|
|
|
|
class UnionInterfaceTest extends \PHPUnit_Framework_TestCase
|
|
|
|
{
|
|
|
|
public $schema;
|
|
|
|
public $garfield;
|
|
|
|
public $odie;
|
|
|
|
public $liz;
|
|
|
|
public $john;
|
|
|
|
|
|
|
|
public function setUp()
|
|
|
|
{
|
|
|
|
$NamedType = new InterfaceType([
|
|
|
|
'name' => 'Named',
|
|
|
|
'fields' => [
|
|
|
|
'name' => ['type' => Type::string()]
|
|
|
|
]
|
|
|
|
]);
|
|
|
|
|
|
|
|
$DogType = new ObjectType([
|
|
|
|
'name' => 'Dog',
|
|
|
|
'interfaces' => [$NamedType],
|
|
|
|
'fields' => [
|
|
|
|
'name' => ['type' => Type::string()],
|
2015-08-17 17:01:55 +03:00
|
|
|
'woofs' => ['type' => Type::boolean()]
|
2015-07-15 20:05:46 +03:00
|
|
|
],
|
|
|
|
'isTypeOf' => function ($value) {
|
|
|
|
return $value instanceof Dog;
|
|
|
|
}
|
|
|
|
]);
|
|
|
|
|
|
|
|
$CatType = new ObjectType([
|
|
|
|
'name' => 'Cat',
|
|
|
|
'interfaces' => [$NamedType],
|
|
|
|
'fields' => [
|
|
|
|
'name' => ['type' => Type::string()],
|
|
|
|
'meows' => ['type' => Type::boolean()]
|
|
|
|
],
|
|
|
|
'isTypeOf' => function ($value) {
|
|
|
|
return $value instanceof Cat;
|
|
|
|
}
|
|
|
|
]);
|
|
|
|
|
|
|
|
$PetType = new UnionType([
|
|
|
|
'name' => 'Pet',
|
|
|
|
'types' => [$DogType, $CatType],
|
|
|
|
'resolveType' => function ($value) use ($DogType, $CatType) {
|
|
|
|
if ($value instanceof Dog) {
|
|
|
|
return $DogType;
|
|
|
|
}
|
|
|
|
if ($value instanceof Cat) {
|
|
|
|
return $CatType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]);
|
|
|
|
|
|
|
|
$PersonType = new ObjectType([
|
|
|
|
'name' => 'Person',
|
|
|
|
'interfaces' => [$NamedType],
|
|
|
|
'fields' => [
|
|
|
|
'name' => ['type' => Type::string()],
|
|
|
|
'pets' => ['type' => Type::listOf($PetType)],
|
|
|
|
'friends' => ['type' => Type::listOf($NamedType)]
|
|
|
|
],
|
|
|
|
'isTypeOf' => function ($value) {
|
|
|
|
return $value instanceof Person;
|
|
|
|
}
|
|
|
|
]);
|
|
|
|
|
|
|
|
$this->schema = new Schema($PersonType);
|
|
|
|
|
|
|
|
$this->garfield = new Cat('Garfield', false);
|
|
|
|
$this->odie = new Dog('Odie', true);
|
|
|
|
$this->liz = new Person('Liz');
|
|
|
|
$this->john = new Person('John', [$this->garfield, $this->odie], [$this->liz, $this->odie]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Execute: Union and intersection types
|
|
|
|
public function testCanIntrospectOnUnionAndIntersectionTypes()
|
|
|
|
{
|
|
|
|
|
|
|
|
$ast = Parser::parse('
|
|
|
|
{
|
|
|
|
Named: __type(name: "Named") {
|
|
|
|
kind
|
|
|
|
name
|
|
|
|
fields { name }
|
|
|
|
interfaces { name }
|
|
|
|
possibleTypes { name }
|
|
|
|
enumValues { name }
|
|
|
|
inputFields { name }
|
|
|
|
}
|
|
|
|
Pet: __type(name: "Pet") {
|
|
|
|
kind
|
|
|
|
name
|
|
|
|
fields { name }
|
|
|
|
interfaces { name }
|
|
|
|
possibleTypes { name }
|
|
|
|
enumValues { name }
|
|
|
|
inputFields { name }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
');
|
|
|
|
|
|
|
|
$expected = [
|
|
|
|
'data' => [
|
|
|
|
'Named' => [
|
|
|
|
'kind' => 'INTERFACE',
|
|
|
|
'name' => 'Named',
|
|
|
|
'fields' => [
|
|
|
|
['name' => 'name']
|
|
|
|
],
|
|
|
|
'interfaces' => null,
|
|
|
|
'possibleTypes' => [
|
|
|
|
['name' => 'Dog'],
|
|
|
|
['name' => 'Cat'],
|
|
|
|
['name' => 'Person']
|
|
|
|
],
|
|
|
|
'enumValues' => null,
|
|
|
|
'inputFields' => null
|
|
|
|
],
|
|
|
|
'Pet' => [
|
|
|
|
'kind' => 'UNION',
|
|
|
|
'name' => 'Pet',
|
|
|
|
'fields' => null,
|
|
|
|
'interfaces' => null,
|
|
|
|
'possibleTypes' => [
|
|
|
|
['name' => 'Dog'],
|
|
|
|
['name' => 'Cat']
|
|
|
|
],
|
|
|
|
'enumValues' => null,
|
|
|
|
'inputFields' => null
|
|
|
|
]
|
|
|
|
]
|
|
|
|
];
|
2015-08-17 17:01:55 +03:00
|
|
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast)->toArray());
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testExecutesUsingUnionTypes()
|
|
|
|
{
|
|
|
|
// NOTE: This is an *invalid* query, but it should be an *executable* query.
|
|
|
|
$ast = Parser::parse('
|
|
|
|
{
|
|
|
|
__typename
|
|
|
|
name
|
|
|
|
pets {
|
|
|
|
__typename
|
|
|
|
name
|
2015-08-17 17:01:55 +03:00
|
|
|
woofs
|
2015-07-15 20:05:46 +03:00
|
|
|
meows
|
|
|
|
}
|
|
|
|
}
|
|
|
|
');
|
|
|
|
$expected = [
|
|
|
|
'data' => [
|
|
|
|
'__typename' => 'Person',
|
|
|
|
'name' => 'John',
|
|
|
|
'pets' => [
|
|
|
|
['__typename' => 'Cat', 'name' => 'Garfield', 'meows' => false],
|
2015-08-17 17:01:55 +03:00
|
|
|
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true]
|
2015-07-15 20:05:46 +03:00
|
|
|
]
|
|
|
|
]
|
|
|
|
];
|
|
|
|
|
2015-08-17 17:01:55 +03:00
|
|
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testExecutesUnionTypesWithInlineFragments()
|
|
|
|
{
|
|
|
|
// This is the valid version of the query in the above test.
|
|
|
|
$ast = Parser::parse('
|
|
|
|
{
|
|
|
|
__typename
|
|
|
|
name
|
|
|
|
pets {
|
|
|
|
__typename
|
|
|
|
... on Dog {
|
|
|
|
name
|
2015-08-17 17:01:55 +03:00
|
|
|
woofs
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
... on Cat {
|
|
|
|
name
|
|
|
|
meows
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
');
|
|
|
|
$expected = [
|
|
|
|
'data' => [
|
|
|
|
'__typename' => 'Person',
|
|
|
|
'name' => 'John',
|
|
|
|
'pets' => [
|
|
|
|
['__typename' => 'Cat', 'name' => 'Garfield', 'meows' => false],
|
2015-08-17 17:01:55 +03:00
|
|
|
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true]
|
2015-07-15 20:05:46 +03:00
|
|
|
]
|
|
|
|
|
|
|
|
]
|
|
|
|
];
|
2015-08-17 17:01:55 +03:00
|
|
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testExecutesUsingInterfaceTypes()
|
|
|
|
{
|
|
|
|
// NOTE: This is an *invalid* query, but it should be an *executable* query.
|
|
|
|
$ast = Parser::parse('
|
|
|
|
{
|
|
|
|
__typename
|
|
|
|
name
|
|
|
|
friends {
|
|
|
|
__typename
|
|
|
|
name
|
2015-08-17 17:01:55 +03:00
|
|
|
woofs
|
2015-07-15 20:05:46 +03:00
|
|
|
meows
|
|
|
|
}
|
|
|
|
}
|
|
|
|
');
|
|
|
|
$expected = [
|
|
|
|
'data' => [
|
|
|
|
'__typename' => 'Person',
|
|
|
|
'name' => 'John',
|
|
|
|
'friends' => [
|
|
|
|
['__typename' => 'Person', 'name' => 'Liz'],
|
2015-08-17 17:01:55 +03:00
|
|
|
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true]
|
2015-07-15 20:05:46 +03:00
|
|
|
]
|
|
|
|
]
|
|
|
|
];
|
|
|
|
|
2015-08-17 17:01:55 +03:00
|
|
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testExecutesInterfaceTypesWithInlineFragments()
|
|
|
|
{
|
|
|
|
// This is the valid version of the query in the above test.
|
|
|
|
$ast = Parser::parse('
|
|
|
|
{
|
|
|
|
__typename
|
|
|
|
name
|
|
|
|
friends {
|
|
|
|
__typename
|
|
|
|
name
|
|
|
|
... on Dog {
|
2015-08-17 17:01:55 +03:00
|
|
|
woofs
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
... on Cat {
|
|
|
|
meows
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
');
|
|
|
|
$expected = [
|
|
|
|
'data' => [
|
|
|
|
'__typename' => 'Person',
|
|
|
|
'name' => 'John',
|
|
|
|
'friends' => [
|
|
|
|
['__typename' => 'Person', 'name' => 'Liz'],
|
2015-08-17 17:01:55 +03:00
|
|
|
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true]
|
2015-07-15 20:05:46 +03:00
|
|
|
]
|
|
|
|
]
|
|
|
|
];
|
|
|
|
|
2015-08-17 17:01:55 +03:00
|
|
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testAllowsFragmentConditionsToBeAbstractTypes()
|
|
|
|
{
|
|
|
|
$ast = Parser::parse('
|
|
|
|
{
|
|
|
|
__typename
|
|
|
|
name
|
|
|
|
pets { ...PetFields }
|
|
|
|
friends { ...FriendFields }
|
|
|
|
}
|
|
|
|
|
|
|
|
fragment PetFields on Pet {
|
|
|
|
__typename
|
|
|
|
... on Dog {
|
|
|
|
name
|
2015-08-17 17:01:55 +03:00
|
|
|
woofs
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
... on Cat {
|
|
|
|
name
|
|
|
|
meows
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fragment FriendFields on Named {
|
|
|
|
__typename
|
|
|
|
name
|
|
|
|
... on Dog {
|
2015-08-17 17:01:55 +03:00
|
|
|
woofs
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
... on Cat {
|
|
|
|
meows
|
|
|
|
}
|
|
|
|
}
|
|
|
|
');
|
|
|
|
|
|
|
|
$expected = [
|
|
|
|
'data' => [
|
|
|
|
'__typename' => 'Person',
|
|
|
|
'name' => 'John',
|
|
|
|
'pets' => [
|
|
|
|
['__typename' => 'Cat', 'name' => 'Garfield', 'meows' => false],
|
2015-08-17 17:01:55 +03:00
|
|
|
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true]
|
2015-07-15 20:05:46 +03:00
|
|
|
],
|
|
|
|
'friends' => [
|
|
|
|
['__typename' => 'Person', 'name' => 'Liz'],
|
2015-08-17 17:01:55 +03:00
|
|
|
['__typename' => 'Dog', 'name' => 'Odie', 'woofs' => true]
|
2015-07-15 20:05:46 +03:00
|
|
|
]
|
|
|
|
]
|
|
|
|
];
|
|
|
|
|
2015-08-17 17:01:55 +03:00
|
|
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
}
|