mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-29 00:25:17 +03:00
263 lines
6.9 KiB
PHP
263 lines
6.9 KiB
PHP
|
<?php
|
||
|
namespace GraphQL\Executor;
|
||
|
|
||
|
use GraphQL\Error;
|
||
|
use GraphQL\FormattedError;
|
||
|
use GraphQL\Language\Parser;
|
||
|
use GraphQL\Language\SourceLocation;
|
||
|
use GraphQL\Schema;
|
||
|
use GraphQL\Type\Definition\ObjectType;
|
||
|
use GraphQL\Type\Definition\Type;
|
||
|
|
||
|
class NonNullTest extends \PHPUnit_Framework_TestCase
|
||
|
{
|
||
|
/** @var Error */
|
||
|
public $syncError;
|
||
|
public $nonNullSyncError;
|
||
|
public $throwingData;
|
||
|
public $nullingData;
|
||
|
public $schema;
|
||
|
|
||
|
public function setUp()
|
||
|
{
|
||
|
$this->syncError = new Error('sync');
|
||
|
$this->nonNullSyncError = new Error('nonNullSync');
|
||
|
|
||
|
$this->throwingData = [
|
||
|
'sync' => function () {
|
||
|
throw $this->syncError;
|
||
|
},
|
||
|
'nonNullSync' => function () {
|
||
|
throw $this->nonNullSyncError;
|
||
|
},
|
||
|
'nest' => function () {
|
||
|
return $this->throwingData;
|
||
|
},
|
||
|
'nonNullNest' => function () {
|
||
|
return $this->throwingData;
|
||
|
},
|
||
|
];
|
||
|
|
||
|
$this->nullingData = [
|
||
|
'sync' => function () {
|
||
|
return null;
|
||
|
},
|
||
|
'nonNullSync' => function () {
|
||
|
return null;
|
||
|
},
|
||
|
'nest' => function () {
|
||
|
return $this->nullingData;
|
||
|
},
|
||
|
'nonNullNest' => function () {
|
||
|
return $this->nullingData;
|
||
|
},
|
||
|
];
|
||
|
|
||
|
$dataType = new ObjectType([
|
||
|
'name' => 'DataType',
|
||
|
'fields' => [
|
||
|
'sync' => ['type' => Type::string()],
|
||
|
'nonNullSync' => ['type' => Type::nonNull(Type::string())],
|
||
|
'nest' => ['type' => function () use (&$dataType) {
|
||
|
return $dataType;
|
||
|
}],
|
||
|
'nonNullNest' => ['type' => function () use (&$dataType) {
|
||
|
return Type::nonNull($dataType);
|
||
|
}]
|
||
|
]
|
||
|
]);
|
||
|
|
||
|
$this->schema = new Schema($dataType);
|
||
|
}
|
||
|
|
||
|
// Execute: handles non-nullable types
|
||
|
public function testNullsANullableFieldThatThrowsSynchronously()
|
||
|
{
|
||
|
$doc = '
|
||
|
query Q {
|
||
|
sync
|
||
|
}
|
||
|
';
|
||
|
|
||
|
$ast = Parser::parse($doc);
|
||
|
|
||
|
$expected = [
|
||
|
'data' => [
|
||
|
'sync' => null,
|
||
|
],
|
||
|
'errors' => [
|
||
|
new FormattedError(
|
||
|
$this->syncError->message,
|
||
|
[new SourceLocation(3, 9)]
|
||
|
)
|
||
|
]
|
||
|
];
|
||
|
$this->assertEquals($expected, Executor::execute($this->schema, $this->throwingData, $ast, 'Q', []));
|
||
|
}
|
||
|
|
||
|
public function testNullsASynchronouslyReturnedObjectThatContainsANonNullableFieldThatThrowsSynchronously()
|
||
|
{
|
||
|
// nulls a synchronously returned object that contains a non-nullable field that throws synchronously
|
||
|
$doc = '
|
||
|
query Q {
|
||
|
nest {
|
||
|
nonNullSync,
|
||
|
}
|
||
|
}
|
||
|
';
|
||
|
|
||
|
$ast = Parser::parse($doc);
|
||
|
|
||
|
$expected = [
|
||
|
'data' => [
|
||
|
'nest' => null
|
||
|
],
|
||
|
'errors' => [
|
||
|
new FormattedError($this->nonNullSyncError->message, [new SourceLocation(4, 11)])
|
||
|
]
|
||
|
];
|
||
|
$this->assertEquals($expected, Executor::execute($this->schema, $this->throwingData, $ast, 'Q', []));
|
||
|
}
|
||
|
|
||
|
public function testNullsAComplexTreeOfNullableFieldsThatThrow()
|
||
|
{
|
||
|
$doc = '
|
||
|
query Q {
|
||
|
nest {
|
||
|
sync
|
||
|
nest {
|
||
|
sync
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
';
|
||
|
|
||
|
$ast = Parser::parse($doc);
|
||
|
|
||
|
$expected = [
|
||
|
'data' => [
|
||
|
'nest' => [
|
||
|
'sync' => null,
|
||
|
'nest' => [
|
||
|
'sync' => null,
|
||
|
]
|
||
|
]
|
||
|
],
|
||
|
'errors' => [
|
||
|
new FormattedError($this->syncError->message, [new SourceLocation(4, 11)]),
|
||
|
new FormattedError($this->syncError->message, [new SourceLocation(6, 13)]),
|
||
|
]
|
||
|
];
|
||
|
$this->assertEquals($expected, Executor::execute($this->schema, $this->throwingData, $ast, 'Q', []));
|
||
|
}
|
||
|
|
||
|
public function testNullsANullableFieldThatSynchronouslyReturnsNull()
|
||
|
{
|
||
|
$doc = '
|
||
|
query Q {
|
||
|
sync
|
||
|
}
|
||
|
';
|
||
|
|
||
|
$ast = Parser::parse($doc);
|
||
|
|
||
|
$expected = [
|
||
|
'data' => [
|
||
|
'sync' => null,
|
||
|
]
|
||
|
];
|
||
|
$this->assertEquals($expected, Executor::execute($this->schema, $this->nullingData, $ast, 'Q', []));
|
||
|
}
|
||
|
|
||
|
public function test4()
|
||
|
{
|
||
|
// nulls a synchronously returned object that contains a non-nullable field that returns null synchronously
|
||
|
$doc = '
|
||
|
query Q {
|
||
|
nest {
|
||
|
nonNullSync,
|
||
|
}
|
||
|
}
|
||
|
';
|
||
|
|
||
|
$ast = Parser::parse($doc);
|
||
|
|
||
|
$expected = [
|
||
|
'data' => [
|
||
|
'nest' => null
|
||
|
],
|
||
|
'errors' => [
|
||
|
new FormattedError('Cannot return null for non-nullable type.', [new SourceLocation(4, 11)])
|
||
|
]
|
||
|
];
|
||
|
$this->assertEquals($expected, Executor::execute($this->schema, $this->nullingData, $ast, 'Q', []));
|
||
|
}
|
||
|
|
||
|
public function test5()
|
||
|
{
|
||
|
// nulls a complex tree of nullable fields that return null
|
||
|
|
||
|
$doc = '
|
||
|
query Q {
|
||
|
nest {
|
||
|
sync
|
||
|
nest {
|
||
|
sync
|
||
|
nest {
|
||
|
sync
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
';
|
||
|
|
||
|
$ast = Parser::parse($doc);
|
||
|
|
||
|
$expected = [
|
||
|
'data' => [
|
||
|
'nest' => [
|
||
|
'sync' => null,
|
||
|
'nest' => [
|
||
|
'sync' => null,
|
||
|
'nest' => [
|
||
|
'sync' => null
|
||
|
]
|
||
|
],
|
||
|
],
|
||
|
]
|
||
|
];
|
||
|
$this->assertEquals($expected, Executor::execute($this->schema, $this->nullingData, $ast, 'Q', []));
|
||
|
}
|
||
|
|
||
|
public function testNullsTheTopLevelIfSyncNonNullableFieldThrows()
|
||
|
{
|
||
|
$doc = '
|
||
|
query Q { nonNullSync }
|
||
|
';
|
||
|
|
||
|
$expected = [
|
||
|
'data' => null,
|
||
|
'errors' => [
|
||
|
new FormattedError($this->nonNullSyncError->message, [new SourceLocation(2, 17)])
|
||
|
]
|
||
|
];
|
||
|
$this->assertEquals($expected, Executor::execute($this->schema, $this->throwingData, Parser::parse($doc)));
|
||
|
}
|
||
|
|
||
|
public function testNullsTheTopLevelIfSyncNonNullableFieldReturnsNull()
|
||
|
{
|
||
|
// nulls the top level if sync non-nullable field returns null
|
||
|
$doc = '
|
||
|
query Q { nonNullSync }
|
||
|
';
|
||
|
|
||
|
$expected = [
|
||
|
'data' => null,
|
||
|
'errors' => [
|
||
|
new FormattedError('Cannot return null for non-nullable type.', [new SourceLocation(2, 17)]),
|
||
|
]
|
||
|
];
|
||
|
$this->assertEquals($expected, Executor::execute($this->schema, $this->nullingData, Parser::parse($doc)));
|
||
|
}
|
||
|
}
|