Changed ReactPromiseAdapter::all to preserve the array key order and added tests

This commit is contained in:
Juuso Leinonen 2016-12-22 14:43:11 +02:00
parent ff3a40d329
commit 90c4b5d9fa
3 changed files with 177 additions and 1 deletions

View File

@ -17,6 +17,12 @@
</testsuite>
</testsuites>
<groups>
<exclude>
<group>ReactPromise</group>
</exclude>
</groups>
<filter>
<whitelist>
<directory suffix=".php">./src</directory>

View File

@ -71,7 +71,16 @@ class ReactPromiseAdapter implements PromiseAdapter
$promisesOrValues = Utils::map($promisesOrValues, function ($item) {
return $item instanceof Promise ? $item->adoptedPromise : $item;
});
$promise = \React\Promise\all($promisesOrValues);
$promise = \React\Promise\all($promisesOrValues)->then(function($values) use ($promisesOrValues) {
$orderedResults = [];
foreach ($promisesOrValues as $key => $value) {
$orderedResults[$key] = $values[$key];
}
return $orderedResults;
});
return new Promise($promise, $this);
}
}

View File

@ -0,0 +1,161 @@
<?php
namespace GraphQL\Tests\Executor\Promise;
use GraphQL\Executor\Promise\Adapter\ReactPromiseAdapter;
use GraphQL\Executor\Promise\Promise;
use React\Promise\Deferred;
use React\Promise\FulfilledPromise;
use React\Promise\LazyPromise;
use React\Promise\Promise as ReactPromise;
use React\Promise\RejectedPromise;
/**
* @group ReactPromise
*/
class ReactPromiseAdapterTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
if(! class_exists(ReactPromise::class)) {
$this->markTestSkipped('react/promise package must be installed to run ' . self::class);
}
}
public function testIsThenableReturnsTrueWhenAReactPromiseIsGiven()
{
$reactAdapter = new ReactPromiseAdapter();
$this->assertSame(true, $reactAdapter->isThenable(new ReactPromise(function() {})));
$this->assertSame(true, $reactAdapter->isThenable(new FulfilledPromise()));
$this->assertSame(true, $reactAdapter->isThenable(new RejectedPromise()));
$this->assertSame(true, $reactAdapter->isThenable(new LazyPromise(function() {})));
$this->assertSame(false, $reactAdapter->isThenable(false));
$this->assertSame(false, $reactAdapter->isThenable(true));
$this->assertSame(false, $reactAdapter->isThenable(1));
$this->assertSame(false, $reactAdapter->isThenable(0));
$this->assertSame(false, $reactAdapter->isThenable('test'));
$this->assertSame(false, $reactAdapter->isThenable(''));
$this->assertSame(false, $reactAdapter->isThenable([]));
$this->assertSame(false, $reactAdapter->isThenable(new \stdClass()));
}
public function testConvertsReactPromisesToGraphQlOnes()
{
$reactAdapter = new ReactPromiseAdapter();
$reactPromise = new FulfilledPromise(1);
$promise = $reactAdapter->convertThenable($reactPromise);
$this->assertInstanceOf(Promise::class, $promise);
$this->assertInstanceOf(FulfilledPromise::class, $promise->adoptedPromise);
}
public function testThen()
{
$reactAdapter = new ReactPromiseAdapter();
$reactPromise = new FulfilledPromise(1);
$promise = $reactAdapter->convertThenable($reactPromise);
$result = null;
$resultPromise = $reactAdapter->then($promise, function ($value) use (&$result) {
$result = $value;
});
$this->assertSame(1, $result);
$this->assertInstanceOf(Promise::class, $resultPromise);
$this->assertInstanceOf(FulfilledPromise::class, $resultPromise->adoptedPromise);
}
public function testCreate()
{
$reactAdapter = new ReactPromiseAdapter();
$resolvedPromise = $reactAdapter->create(function ($resolve) {
$resolve(1);
});
$this->assertInstanceOf(Promise::class, $resolvedPromise);
$this->assertInstanceOf(ReactPromise::class, $resolvedPromise->adoptedPromise);
$result = null;
$resolvedPromise->then(function ($value) use (&$result) {
$result = $value;
});
$this->assertSame(1, $result);
}
public function testCreateFulfilled()
{
$reactAdapter = new ReactPromiseAdapter();
$fulfilledPromise = $reactAdapter->createFulfilled(1);
$this->assertInstanceOf(Promise::class, $fulfilledPromise);
$this->assertInstanceOf(FulfilledPromise::class, $fulfilledPromise->adoptedPromise);
$result = null;
$fulfilledPromise->then(function ($value) use (&$result) {
$result = $value;
});
$this->assertSame(1, $result);
}
public function testCreateRejected()
{
$reactAdapter = new ReactPromiseAdapter();
$rejectedPromise = $reactAdapter->createRejected(new \Exception('I am a bad promise'));
$this->assertInstanceOf(Promise::class, $rejectedPromise);
$this->assertInstanceOf(RejectedPromise::class, $rejectedPromise->adoptedPromise);
$exception = null;
$rejectedPromise->then(null, function ($error) use (&$exception) {
$exception = $error;
});
$this->assertInstanceOf(\Exception::class, $exception);
$this->assertEquals('I am a bad promise', $exception->getMessage());
}
public function testAll()
{
$reactAdapter = new ReactPromiseAdapter();
$promises = [new FulfilledPromise(1), new FulfilledPromise(2), new FulfilledPromise(3)];
$allPromise = $reactAdapter->all($promises);
$this->assertInstanceOf(Promise::class, $allPromise);
$this->assertInstanceOf(FulfilledPromise::class, $allPromise->adoptedPromise);
$result = null;
$allPromise->then(function ($values) use (&$result) {
$result = $values;
});
$this->assertSame([1, 2, 3], $result);
}
public function testAllShouldPreserveTheOrderOfTheArrayWhenResolvingAsyncPromises()
{
$reactAdapter = new ReactPromiseAdapter();
$deferred = new Deferred();
$promises = [new FulfilledPromise(1), $deferred->promise(), new FulfilledPromise(3)];
$result = null;
$reactAdapter->all($promises)->then(function ($values) use (&$result) {
$result = $values;
});
// Resolve the async promise
$deferred->resolve(2);
$this->assertSame([1, 2, 3], $result);
}
}