Add Executor Promise tests

This commit is contained in:
Jeremiah VALERIE 2016-11-26 23:51:42 +01:00
parent 35d7d83088
commit 76c31df1af

View File

@ -4,8 +4,10 @@ namespace GraphQL\Tests\Executor;
require_once __DIR__ . '/TestClasses.php'; require_once __DIR__ . '/TestClasses.php';
use GraphQL\Error\Error; use GraphQL\Error\Error;
use GraphQL\Executor\ExecutionResult;
use GraphQL\Executor\Executor; use GraphQL\Executor\Executor;
use GraphQL\Error\FormattedError; use GraphQL\Error\FormattedError;
use GraphQL\Executor\Promise\Adapter\ReactPromiseAdapter;
use GraphQL\Language\Parser; use GraphQL\Language\Parser;
use GraphQL\Language\SourceLocation; use GraphQL\Language\SourceLocation;
use GraphQL\Schema; use GraphQL\Schema;
@ -16,9 +18,15 @@ use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType; use GraphQL\Type\Definition\UnionType;
use GraphQL\Utils; use GraphQL\Utils;
use React\Promise\Promise;
class ExecutorTest extends \PHPUnit_Framework_TestCase class ExecutorTest extends \PHPUnit_Framework_TestCase
{ {
public function tearDown()
{
Executor::setPromiseAdapter(null);
}
// Execute: Handles basic execution tasks // Execute: Handles basic execution tasks
/** /**
@ -26,7 +34,16 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
*/ */
public function testExecutesArbitraryCode() public function testExecutesArbitraryCode()
{ {
Executor::setPromiseAdapter(new ReactPromiseAdapter());
$deepData = null; $deepData = null;
$data = null;
$promiseData = function () use (&$data) {
return new Promise(function (callable $resolve) use (&$data) {
return $resolve($data);
});
};
$data = [ $data = [
'a' => function () { return 'Apple';}, 'a' => function () { return 'Apple';},
'b' => function () {return 'Banana';}, 'b' => function () {return 'Banana';},
@ -37,8 +54,8 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
'pic' => function ($size = 50) { 'pic' => function ($size = 50) {
return 'Pic of size: ' . $size; return 'Pic of size: ' . $size;
}, },
'promise' => function() use (&$data) { 'promise' => function() use ($promiseData) {
return $data; return $promiseData();
}, },
'deep' => function () use (&$deepData) { 'deep' => function () use (&$deepData) {
return $deepData; return $deepData;
@ -51,7 +68,7 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
'c' => function () { 'c' => function () {
return ['Contrived', null, 'Confusing']; return ['Contrived', null, 'Confusing'];
}, },
'deeper' => function () use ($data) { 'deeper' => function () use (&$data) {
return [$data, null, $data]; return [$data, null, $data];
} }
]; ];
@ -148,7 +165,7 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
]); ]);
$schema = new Schema(['query' => $dataType]); $schema = new Schema(['query' => $dataType]);
$this->assertEquals($expected, Executor::execute($schema, $ast, $data, null, ['size' => 100], 'Example')->toArray()); $this->assertEquals($expected, self::awaitPromise(Executor::execute($schema, $ast, $data, null, ['size' => 100], 'Example')));
} }
/** /**
@ -342,12 +359,18 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
public function testNullsOutErrorSubtrees() public function testNullsOutErrorSubtrees()
{ {
$doc = '{ $doc = '{
sync, sync
syncError, syncError
syncRawError, syncRawError
async, syncReturnError
asyncReject, syncReturnErrorList
async
asyncReject
asyncRawReject
asyncEmptyReject
asyncError asyncError
asyncRawError
asyncReturnError
}'; }';
$data = [ $data = [
@ -360,17 +383,42 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
'syncRawError' => function() { 'syncRawError' => function() {
throw new \Exception('Error getting syncRawError'); throw new \Exception('Error getting syncRawError');
}, },
// Following are inherited from JS reference implementation, but make no sense in this PHP impl // inherited from JS reference implementation, but make no sense in this PHP impl
// leaving them just to simplify migrations from newer js versions // leaving it just to simplify migrations from newer js versions
'syncReturnError' => function() {
return new \Exception('Error getting syncReturnError');
},
'syncReturnErrorList' => function () {
return [
'sync0',
new \Exception('Error getting syncReturnErrorList1'),
'sync2',
new \Exception('Error getting syncReturnErrorList3')
];
},
'async' => function() { 'async' => function() {
return 'async'; return new Promise(function(callable $resolve) { return $resolve('async'); });
}, },
'asyncReject' => function() { 'asyncReject' => function() {
throw new \Exception('Error getting asyncReject'); return new Promise(function($_, callable $reject) { return $reject('Error getting asyncReject'); });
},
'asyncRawReject' => function () {
return \React\Promise\reject('Error getting asyncRawReject');
},
'asyncEmptyReject' => function () {
return \React\Promise\reject();
}, },
'asyncError' => function() { 'asyncError' => function() {
throw new \Exception('Error getting asyncError'); return new Promise(function() { throw new \Exception('Error getting asyncError'); });
} },
// inherited from JS reference implementation, but make no sense in this PHP impl
// leaving it just to simplify migrations from newer js versions
'asyncRawError' => function() {
return new Promise(function() { throw new \Exception('Error getting asyncRawError'); });
},
'asyncReturnError' => function() {
return \React\Promise\resolve(new \Exception('Error getting asyncReturnError'));
},
]; ];
$docAst = Parser::parse($doc); $docAst = Parser::parse($doc);
@ -380,10 +428,16 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
'fields' => [ 'fields' => [
'sync' => ['type' => Type::string()], 'sync' => ['type' => Type::string()],
'syncError' => ['type' => Type::string()], 'syncError' => ['type' => Type::string()],
'syncRawError' => [ 'type' => Type::string() ], 'syncRawError' => ['type' => Type::string()],
'syncReturnError' => ['type' => Type::string()],
'syncReturnErrorList' => ['type' => Type::listOf(Type::string())],
'async' => ['type' => Type::string()], 'async' => ['type' => Type::string()],
'asyncReject' => ['type' => Type::string() ], 'asyncReject' => ['type' => Type::string() ],
'asyncRawReject' => ['type' => Type::string() ],
'asyncEmptyReject' => ['type' => Type::string() ],
'asyncError' => ['type' => Type::string()], 'asyncError' => ['type' => Type::string()],
'asyncRawError' => ['type' => Type::string()],
'asyncReturnError' => ['type' => Type::string()],
] ]
]) ])
]); ]);
@ -393,21 +447,79 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
'sync' => 'sync', 'sync' => 'sync',
'syncError' => null, 'syncError' => null,
'syncRawError' => null, 'syncRawError' => null,
'syncReturnError' => null,
'syncReturnErrorList' => ['sync0', null, 'sync2', null],
'async' => 'async', 'async' => 'async',
'asyncReject' => null, 'asyncReject' => null,
'asyncRawReject' => null,
'asyncEmptyReject' => null,
'asyncError' => null, 'asyncError' => null,
'asyncRawError' => null,
'asyncReturnError' => null,
], ],
'errors' => [ 'errors' => [
FormattedError::create('Error getting syncError', [new SourceLocation(3, 7)]), [
FormattedError::create('Error getting syncRawError', [new SourceLocation(4, 7)]), 'message' => 'Error getting syncError',
FormattedError::create('Error getting asyncReject', [new SourceLocation(6, 7)]), 'locations' => [['line' => 3, 'column' => 7]],
FormattedError::create('Error getting asyncError', [new SourceLocation(7, 7)]) 'path' => ['syncError']
],
[
'message' => 'Error getting syncRawError',
'locations' => [ [ 'line' => 4, 'column' => 7 ] ],
'path'=> [ 'syncRawError' ]
],
[
'message' => 'Error getting syncReturnError',
'locations' => [['line' => 5, 'column' => 7]],
'path' => ['syncReturnError']
],
[
'message' => 'Error getting syncReturnErrorList1',
'locations' => [['line' => 6, 'column' => 7]],
'path' => ['syncReturnErrorList', 1]
],
[
'message' => 'Error getting syncReturnErrorList3',
'locations' => [['line' => 6, 'column' => 7]],
'path' => ['syncReturnErrorList', 3]
],
[
'message' => 'Error getting asyncReject',
'locations' => [['line' => 8, 'column' => 7]],
'path' => ['asyncReject']
],
[
'message' => 'Error getting asyncRawReject',
'locations' => [['line' => 9, 'column' => 7]],
'path' => ['asyncRawReject']
],
[
'message' => 'An unknown error occurred.',
'locations' => [['line' => 10, 'column' => 7]],
'path' => ['asyncEmptyReject']
],
[
'message' => 'Error getting asyncError',
'locations' => [['line' => 11, 'column' => 7]],
'path' => ['asyncError']
],
[
'message' => 'Error getting asyncRawError',
'locations' => [ [ 'line' => 12, 'column' => 7 ] ],
'path' => [ 'asyncRawError' ]
],
[
'message' => 'Error getting asyncReturnError',
'locations' => [['line' => 13, 'column' => 7]],
'path' => ['asyncReturnError']
],
] ]
]; ];
Executor::setPromiseAdapter(new ReactPromiseAdapter());
$result = Executor::execute($schema, $docAst, $data); $result = Executor::execute($schema, $docAst, $data);
$this->assertArraySubset($expected, $result->toArray()); $this->assertEquals($expected, self::awaitPromise($result));
} }
/** /**
@ -629,6 +741,62 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(['data' => ['a' => 'b']], $subscriptionResult->toArray()); $this->assertEquals(['data' => ['a' => 'b']], $subscriptionResult->toArray());
} }
public function testCorrectFieldOrderingDespiteExecutionOrder()
{
Executor::setPromiseAdapter(new ReactPromiseAdapter());
$doc = '{
a,
b,
c,
d,
e
}';
$data = [
'a' => function () {
return 'a';
},
'b' => function () {
return new Promise(function (callable $resolve) { return $resolve('b'); });
},
'c' => function () {
return 'c';
},
'd' => function () {
return new Promise(function (callable $resolve) { return $resolve('d'); });
},
'e' => function () {
return 'e';
},
];
$ast = Parser::parse($doc);
$queryType = new ObjectType([
'name' => 'DeepDataType',
'fields' => [
'a' => [ 'type' => Type::string() ],
'b' => [ 'type' => Type::string() ],
'c' => [ 'type' => Type::string() ],
'd' => [ 'type' => Type::string() ],
'e' => [ 'type' => Type::string() ],
]
]);
$schema = new Schema(['query' => $queryType]);
$expected = [
'data' => [
'a' => 'a',
'b' => 'b',
'c' => 'c',
'd' => 'd',
'e' => 'e',
]
];
$this->assertEquals($expected, self::awaitPromise(Executor::execute($schema, $ast, $data)));
}
/** /**
* @it Avoids recursion * @it Avoids recursion
*/ */
@ -923,4 +1091,17 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
] ]
], $result->toArray()); ], $result->toArray());
} }
/**
* @param \GraphQL\Executor\Promise\Promise $promise
* @return array
*/
private static function awaitPromise($promise)
{
$results = null;
$promise->then(function (ExecutionResult $executionResult) use (&$results) {
$results = $executionResult->toArray();
});
return $results;
}
} }