graphql-php/tests/Executor/AbstractPromiseTest.php

660 lines
19 KiB
PHP
Raw Permalink Normal View History

<?php
2018-09-01 18:07:06 +03:00
declare(strict_types=1);
namespace GraphQL\Tests\Executor;
use GraphQL\Deferred;
use GraphQL\Error\UserError;
use GraphQL\GraphQL;
2018-09-01 18:07:06 +03:00
use GraphQL\Tests\Executor\TestClasses\Cat;
use GraphQL\Tests\Executor\TestClasses\Dog;
use GraphQL\Tests\Executor\TestClasses\Human;
use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType;
2018-09-01 18:07:06 +03:00
use GraphQL\Type\Schema;
2018-07-29 18:43:10 +03:00
use PHPUnit\Framework\TestCase;
2018-09-01 18:07:06 +03:00
/**
* DESCRIBE: Execute: Handles execution of abstract types with promises
*/
2018-07-29 18:43:10 +03:00
class AbstractPromiseTest extends TestCase
{
/**
* @see it('isTypeOf used to resolve runtime type for Interface')
*/
public function testIsTypeOfUsedToResolveRuntimeTypeForInterface() : void
{
$PetType = new InterfaceType([
2018-09-01 18:07:06 +03:00
'name' => 'Pet',
'fields' => [
2018-09-01 18:07:06 +03:00
'name' => ['type' => Type::string()],
],
]);
$DogType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Dog',
'interfaces' => [$PetType],
2018-09-26 12:07:23 +03:00
'isTypeOf' => static function ($obj) {
return new Deferred(static function () use ($obj) {
return $obj instanceof Dog;
});
},
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'woofs' => ['type' => Type::boolean()],
],
]);
$CatType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Cat',
'interfaces' => [$PetType],
2018-09-26 12:07:23 +03:00
'isTypeOf' => static function ($obj) {
return new Deferred(static function () use ($obj) {
return $obj instanceof Cat;
});
},
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'meows' => ['type' => Type::boolean()],
],
]);
$schema = new Schema([
'query' => new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Query',
'fields' => [
'pets' => [
2018-09-01 18:07:06 +03:00
'type' => Type::listOf($PetType),
2018-09-26 12:07:23 +03:00
'resolve' => static function () {
return [
new Dog('Odie', true),
2018-09-01 18:07:06 +03:00
new Cat('Garfield', false),
];
2018-09-01 18:07:06 +03:00
},
],
],
]),
2018-09-01 18:07:06 +03:00
'types' => [$CatType, $DogType],
]);
$query = '{
pets {
name
... on Dog {
woofs
}
... on Cat {
meows
}
}
}';
$result = GraphQL::executeQuery($schema, $query)->toArray();
$expected = [
'data' => [
'pets' => [
2018-09-01 18:07:06 +03:00
['name' => 'Odie', 'woofs' => true],
['name' => 'Garfield', 'meows' => false],
],
],
];
2018-09-19 18:12:09 +03:00
self::assertEquals($expected, $result);
}
/**
* @see it('isTypeOf can be rejected')
*/
public function testIsTypeOfCanBeRejected() : void
{
$PetType = new InterfaceType([
2018-09-01 18:07:06 +03:00
'name' => 'Pet',
'fields' => [
2018-09-01 18:07:06 +03:00
'name' => ['type' => Type::string()],
],
]);
$DogType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Dog',
'interfaces' => [$PetType],
2018-09-26 12:07:23 +03:00
'isTypeOf' => static function () {
return new Deferred(static function () {
throw new UserError('We are testing this error');
});
},
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'woofs' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$CatType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Cat',
'interfaces' => [$PetType],
2018-09-26 12:07:23 +03:00
'isTypeOf' => static function ($obj) {
return new Deferred(static function () use ($obj) {
return $obj instanceof Cat;
});
},
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'meows' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$schema = new Schema([
'query' => new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Query',
'fields' => [
'pets' => [
2018-09-01 18:07:06 +03:00
'type' => Type::listOf($PetType),
2018-09-26 12:07:23 +03:00
'resolve' => static function () {
return [
new Dog('Odie', true),
2018-09-01 18:07:06 +03:00
new Cat('Garfield', false),
];
2018-09-01 18:07:06 +03:00
},
],
],
]),
2018-09-01 18:07:06 +03:00
'types' => [$CatType, $DogType],
]);
$query = '{
pets {
name
... on Dog {
woofs
}
... on Cat {
meows
}
}
}';
$result = GraphQL::executeQuery($schema, $query)->toArray();
$expected = [
2018-09-01 18:07:06 +03:00
'data' => [
'pets' => [null, null],
],
'errors' => [
[
2018-09-01 18:07:06 +03:00
'message' => 'We are testing this error',
'locations' => [['line' => 2, 'column' => 7]],
2018-09-01 18:07:06 +03:00
'path' => ['pets', 0],
],
[
2018-09-01 18:07:06 +03:00
'message' => 'We are testing this error',
'locations' => [['line' => 2, 'column' => 7]],
2018-09-01 18:07:06 +03:00
'path' => ['pets', 1],
],
],
];
2018-09-19 18:12:09 +03:00
self::assertArraySubset($expected, $result);
}
/**
* @see it('isTypeOf used to resolve runtime type for Union')
*/
public function testIsTypeOfUsedToResolveRuntimeTypeForUnion() : void
{
$DogType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Dog',
2018-09-26 12:07:23 +03:00
'isTypeOf' => static function ($obj) {
return new Deferred(static function () use ($obj) {
return $obj instanceof Dog;
});
},
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'woofs' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$CatType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Cat',
2018-09-26 12:07:23 +03:00
'isTypeOf' => static function ($obj) {
return new Deferred(static function () use ($obj) {
return $obj instanceof Cat;
});
},
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'meows' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$PetType = new UnionType([
2018-09-01 18:07:06 +03:00
'name' => 'Pet',
'types' => [$DogType, $CatType],
]);
$schema = new Schema([
'query' => new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Query',
'fields' => [
'pets' => [
2018-09-01 18:07:06 +03:00
'type' => Type::listOf($PetType),
2018-09-26 12:07:23 +03:00
'resolve' => static function () {
return [new Dog('Odie', true), new Cat('Garfield', false)];
2018-09-01 18:07:06 +03:00
},
],
],
]),
]);
$query = '{
pets {
... on Dog {
name
woofs
}
... on Cat {
name
meows
}
}
}';
$result = GraphQL::executeQuery($schema, $query)->toArray();
$expected = [
'data' => [
'pets' => [
['name' => 'Odie', 'woofs' => true],
2018-09-01 18:07:06 +03:00
['name' => 'Garfield', 'meows' => false],
],
],
];
2018-09-19 18:12:09 +03:00
self::assertEquals($expected, $result);
}
/**
* @see it('resolveType on Interface yields useful error')
*/
public function testResolveTypeOnInterfaceYieldsUsefulError() : void
{
$PetType = new InterfaceType([
2018-09-01 18:07:06 +03:00
'name' => 'Pet',
2018-09-26 12:07:23 +03:00
'resolveType' => static function ($obj) use (&$DogType, &$CatType, &$HumanType) {
return new Deferred(static function () use ($obj, $DogType, $CatType, $HumanType) {
if ($obj instanceof Dog) {
return $DogType;
}
if ($obj instanceof Cat) {
return $CatType;
}
if ($obj instanceof Human) {
return $HumanType;
}
2018-09-01 18:07:06 +03:00
return null;
});
},
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
],
]);
$HumanType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Human',
'fields' => [
'name' => ['type' => Type::string()],
2018-09-01 18:07:06 +03:00
],
]);
$DogType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Dog',
'interfaces' => [$PetType],
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'woofs' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$CatType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Cat',
'interfaces' => [$PetType],
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'meows' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$schema = new Schema([
'query' => new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Query',
'fields' => [
'pets' => [
2018-09-01 18:07:06 +03:00
'type' => Type::listOf($PetType),
2018-09-26 12:07:23 +03:00
'resolve' => static function () {
return new Deferred(static function () {
return [
new Dog('Odie', true),
new Cat('Garfield', false),
2018-09-01 18:07:06 +03:00
new Human('Jon'),
];
});
2018-09-01 18:07:06 +03:00
},
],
],
]),
2018-09-01 18:07:06 +03:00
'types' => [$CatType, $DogType],
]);
$query = '{
pets {
name
... on Dog {
woofs
}
... on Cat {
meows
}
}
}';
$result = GraphQL::executeQuery($schema, $query)->toArray(true);
$expected = [
2018-09-01 18:07:06 +03:00
'data' => [
'pets' => [
['name' => 'Odie', 'woofs' => true],
['name' => 'Garfield', 'meows' => false],
2018-09-01 18:07:06 +03:00
null,
],
],
'errors' => [
[
'debugMessage' => 'Runtime Object type "Human" is not a possible type for "Pet".',
2018-09-01 18:07:06 +03:00
'locations' => [['line' => 2, 'column' => 7]],
'path' => ['pets', 2],
],
2018-09-01 18:07:06 +03:00
],
];
2018-09-19 18:12:09 +03:00
self::assertArraySubset($expected, $result);
}
/**
* @see it('resolveType on Union yields useful error')
*/
public function testResolveTypeOnUnionYieldsUsefulError() : void
{
$HumanType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Human',
'fields' => [
'name' => ['type' => Type::string()],
2018-09-01 18:07:06 +03:00
],
]);
$DogType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Dog',
'fields' => [
2018-09-01 18:07:06 +03:00
'name' => ['type' => Type::string()],
'woofs' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$CatType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Cat',
'fields' => [
2018-09-01 18:07:06 +03:00
'name' => ['type' => Type::string()],
'meows' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$PetType = new UnionType([
2018-09-01 18:07:06 +03:00
'name' => 'Pet',
2018-09-26 12:07:23 +03:00
'resolveType' => static function ($obj) use ($DogType, $CatType, $HumanType) {
return new Deferred(static function () use ($obj, $DogType, $CatType, $HumanType) {
if ($obj instanceof Dog) {
return $DogType;
}
if ($obj instanceof Cat) {
return $CatType;
}
if ($obj instanceof Human) {
return $HumanType;
}
2018-09-01 18:07:06 +03:00
return null;
});
},
2018-09-01 18:07:06 +03:00
'types' => [$DogType, $CatType],
]);
$schema = new Schema([
'query' => new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Query',
'fields' => [
'pets' => [
2018-09-01 18:07:06 +03:00
'type' => Type::listOf($PetType),
2018-09-26 12:07:23 +03:00
'resolve' => static function () {
return [
new Dog('Odie', true),
new Cat('Garfield', false),
2018-09-01 18:07:06 +03:00
new Human('Jon'),
];
2018-09-01 18:07:06 +03:00
},
],
],
]),
]);
$query = '{
pets {
... on Dog {
name
woofs
}
... on Cat {
name
meows
}
}
}';
$result = GraphQL::executeQuery($schema, $query)->toArray(true);
$expected = [
2018-09-01 18:07:06 +03:00
'data' => [
'pets' => [
['name' => 'Odie', 'woofs' => true],
['name' => 'Garfield', 'meows' => false],
2018-09-01 18:07:06 +03:00
null,
],
],
'errors' => [
[
'debugMessage' => 'Runtime Object type "Human" is not a possible type for "Pet".',
2018-09-01 18:07:06 +03:00
'locations' => [['line' => 2, 'column' => 7]],
'path' => ['pets', 2],
],
],
];
2018-09-19 18:12:09 +03:00
self::assertArraySubset($expected, $result);
}
/**
* @see it('resolveType allows resolving with type name')
*/
public function testResolveTypeAllowsResolvingWithTypeName() : void
{
$PetType = new InterfaceType([
2018-09-01 18:07:06 +03:00
'name' => 'Pet',
2018-09-26 12:07:23 +03:00
'resolveType' => static function ($obj) {
return new Deferred(static function () use ($obj) {
if ($obj instanceof Dog) {
return 'Dog';
}
if ($obj instanceof Cat) {
return 'Cat';
}
2018-09-01 18:07:06 +03:00
return null;
});
},
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
],
]);
$DogType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Dog',
'interfaces' => [$PetType],
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'woofs' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$CatType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Cat',
'interfaces' => [$PetType],
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'meows' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$schema = new Schema([
'query' => new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Query',
'fields' => [
'pets' => [
2018-09-01 18:07:06 +03:00
'type' => Type::listOf($PetType),
2018-09-26 12:07:23 +03:00
'resolve' => static function () {
return [
new Dog('Odie', true),
2018-09-01 18:07:06 +03:00
new Cat('Garfield', false),
];
2018-09-01 18:07:06 +03:00
},
],
],
]),
2018-09-01 18:07:06 +03:00
'types' => [$CatType, $DogType],
]);
$query = '{
pets {
name
... on Dog {
woofs
}
... on Cat {
meows
}
}
}';
$result = GraphQL::executeQuery($schema, $query)->toArray();
$expected = [
'data' => [
'pets' => [
['name' => 'Odie', 'woofs' => true],
['name' => 'Garfield', 'meows' => false],
2018-09-01 18:07:06 +03:00
],
],
];
2018-09-19 18:12:09 +03:00
self::assertEquals($expected, $result);
}
/**
* @see it('resolveType can be caught')
*/
public function testResolveTypeCanBeCaught() : void
{
$PetType = new InterfaceType([
2018-09-01 18:07:06 +03:00
'name' => 'Pet',
2018-09-26 12:07:23 +03:00
'resolveType' => static function () {
return new Deferred(static function () {
throw new UserError('We are testing this error');
});
},
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
],
]);
$DogType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Dog',
'interfaces' => [$PetType],
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'woofs' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$CatType = new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Cat',
'interfaces' => [$PetType],
2018-09-01 18:07:06 +03:00
'fields' => [
'name' => ['type' => Type::string()],
'meows' => ['type' => Type::boolean()],
2018-09-01 18:07:06 +03:00
],
]);
$schema = new Schema([
'query' => new ObjectType([
2018-09-01 18:07:06 +03:00
'name' => 'Query',
'fields' => [
'pets' => [
2018-09-01 18:07:06 +03:00
'type' => Type::listOf($PetType),
2018-09-26 12:07:23 +03:00
'resolve' => static function () {
return [
new Dog('Odie', true),
2018-09-01 18:07:06 +03:00
new Cat('Garfield', false),
];
2018-09-01 18:07:06 +03:00
},
],
],
]),
2018-09-01 18:07:06 +03:00
'types' => [$CatType, $DogType],
]);
$query = '{
pets {
name
... on Dog {
woofs
}
... on Cat {
meows
}
}
}';
$result = GraphQL::executeQuery($schema, $query)->toArray();
$expected = [
2018-09-01 18:07:06 +03:00
'data' => [
'pets' => [null, null],
],
'errors' => [
[
2018-09-01 18:07:06 +03:00
'message' => 'We are testing this error',
'locations' => [['line' => 2, 'column' => 7]],
2018-09-01 18:07:06 +03:00
'path' => ['pets', 0],
],
[
2018-09-01 18:07:06 +03:00
'message' => 'We are testing this error',
'locations' => [['line' => 2, 'column' => 7]],
2018-09-01 18:07:06 +03:00
'path' => ['pets', 1],
],
],
];
2018-09-19 18:12:09 +03:00
self::assertArraySubset($expected, $result);
}
}