Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176

This commit is contained in:
Pantheon Automation 2015-08-17 17:00:26 -07:00 committed by Greg Anderson
commit 9921556621
13277 changed files with 1459781 additions and 0 deletions

View file

@ -0,0 +1,42 @@
<?php
namespace React\Promise;
use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
class DeferredTest extends TestCase
{
use PromiseTest\FullTestTrait;
public function getPromiseTestAdapter(callable $canceller = null)
{
$d = new Deferred($canceller);
return new CallbackPromiseAdapter([
'promise' => [$d, 'promise'],
'resolve' => [$d, 'resolve'],
'reject' => [$d, 'reject'],
'notify' => [$d, 'progress'],
'settle' => [$d, 'resolve'],
]);
}
/** @test */
public function progressIsAnAliasForNotify()
{
$deferred = new Deferred();
$sentinel = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($sentinel);
$deferred->promise()
->then($this->expectCallableNever(), $this->expectCallableNever(), $mock);
$deferred->progress($sentinel);
}
}

View file

@ -0,0 +1,50 @@
<?php
namespace React\Promise;
use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
class FulfilledPromiseTest extends TestCase
{
use PromiseTest\PromiseSettledTestTrait,
PromiseTest\PromiseFulfilledTestTrait;
public function getPromiseTestAdapter(callable $canceller = null)
{
$promise = null;
return new CallbackPromiseAdapter([
'promise' => function () use (&$promise) {
if (!$promise) {
throw new \LogicException('FulfilledPromise must be resolved before obtaining the promise');
}
return $promise;
},
'resolve' => function ($value = null) use (&$promise) {
if (!$promise) {
$promise = new FulfilledPromise($value);
}
},
'reject' => function () {
throw new \LogicException('You cannot call reject() for React\Promise\FulfilledPromise');
},
'notify' => function () {
// no-op
},
'settle' => function ($value = null) use (&$promise) {
if (!$promise) {
$promise = new FulfilledPromise($value);
}
},
]);
}
/** @test */
public function shouldThrowExceptionIfConstructedWithAPromise()
{
$this->setExpectedException('\InvalidArgumentException');
return new FulfilledPromise(new FulfilledPromise());
}
}

View file

@ -0,0 +1,97 @@
<?php
namespace React\Promise;
class FunctionAllTest extends TestCase
{
/** @test */
public function shouldResolveEmptyInput()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([]));
all([])
->then($mock);
}
/** @test */
public function shouldResolveValuesArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([1, 2, 3]));
all([1, 2, 3])
->then($mock);
}
/** @test */
public function shouldResolvePromisesArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([1, 2, 3]));
all([resolve(1), resolve(2), resolve(3)])
->then($mock);
}
/** @test */
public function shouldResolveSparseArrayInput()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([null, 1, null, 1, 1]));
all([null, 1, null, 1, 1])
->then($mock);
}
/** @test */
public function shouldRejectIfAnyInputPromiseRejects()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
all([resolve(1), reject(2), resolve(3)])
->then($this->expectCallableNever(), $mock);
}
/** @test */
public function shouldAcceptAPromiseForAnArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([1, 2, 3]));
all(resolve([1, 2, 3]))
->then($mock);
}
/** @test */
public function shouldResolveToEmptyArrayWhenInputPromiseDoesNotResolveToArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([]));
all(resolve(1))
->then($mock);
}
}

View file

@ -0,0 +1,116 @@
<?php
namespace React\Promise;
class FunctionAnyTest extends TestCase
{
/** @test */
public function shouldResolveToNullWithEmptyInputArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(null));
any([])
->then($mock);
}
/** @test */
public function shouldResolveWithAnInputValue()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
any([1, 2, 3])
->then($mock);
}
/** @test */
public function shouldResolveWithAPromisedInputValue()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
any([resolve(1), resolve(2), resolve(3)])
->then($mock);
}
/** @test */
public function shouldRejectWithAllRejectedInputValuesIfAllInputsAreRejected()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([0 => 1, 1 => 2, 2 => 3]));
any([reject(1), reject(2), reject(3)])
->then($this->expectCallableNever(), $mock);
}
/** @test */
public function shouldResolveWhenFirstInputPromiseResolves()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
any([resolve(1), reject(2), reject(3)])
->then($mock);
}
/** @test */
public function shouldAcceptAPromiseForAnArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
any(resolve([1, 2, 3]))
->then($mock);
}
/** @test */
public function shouldResolveToNullArrayWhenInputPromiseDoesNotResolveToArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(null));
any(resolve(1))
->then($mock);
}
/** @test */
public function shouldNotRelyOnArryIndexesWhenUnwrappingToASingleResolutionValue()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
$d1 = new Deferred();
$d2 = new Deferred();
any(['abc' => $d1->promise(), 1 => $d2->promise()])
->then($mock);
$d2->resolve(2);
$d1->resolve(1);
}
}

View file

@ -0,0 +1,118 @@
<?php
namespace React\Promise;
class FunctionCheckTypehintTest extends TestCase
{
/** @test */
public function shouldAcceptClosureCallbackWithTypehint()
{
$this->assertTrue(_checkTypehint(function (\InvalidArgumentException $e) {
}, new \InvalidArgumentException()));
$this->assertfalse(_checkTypehint(function (\InvalidArgumentException $e) {
}, new \Exception()));
}
/** @test */
public function shouldAcceptFunctionStringCallbackWithTypehint()
{
$this->assertTrue(_checkTypehint('React\Promise\testCallbackWithTypehint', new \InvalidArgumentException()));
$this->assertfalse(_checkTypehint('React\Promise\testCallbackWithTypehint', new \Exception()));
}
/** @test */
public function shouldAcceptInvokableObjectCallbackWithTypehint()
{
$this->assertTrue(_checkTypehint(new TestCallbackWithTypehintClass(), new \InvalidArgumentException()));
$this->assertfalse(_checkTypehint(new TestCallbackWithTypehintClass(), new \Exception()));
}
/** @test */
public function shouldAcceptObjectMethodCallbackWithTypehint()
{
$this->assertTrue(_checkTypehint([new TestCallbackWithTypehintClass(), 'testCallback'], new \InvalidArgumentException()));
$this->assertfalse(_checkTypehint([new TestCallbackWithTypehintClass(), 'testCallback'], new \Exception()));
}
/** @test */
public function shouldAcceptStaticClassCallbackWithTypehint()
{
$this->assertTrue(_checkTypehint(['React\Promise\TestCallbackWithTypehintClass', 'testCallbackStatic'], new \InvalidArgumentException()));
$this->assertfalse(_checkTypehint(['React\Promise\TestCallbackWithTypehintClass', 'testCallbackStatic'], new \Exception()));
}
/** @test */
public function shouldAcceptClosureCallbackWithoutTypehint()
{
$this->assertTrue(_checkTypehint(function (\InvalidArgumentException $e) {
}, new \InvalidArgumentException()));
}
/** @test */
public function shouldAcceptFunctionStringCallbackWithoutTypehint()
{
$this->assertTrue(_checkTypehint('React\Promise\testCallbackWithoutTypehint', new \InvalidArgumentException()));
}
/** @test */
public function shouldAcceptInvokableObjectCallbackWithoutTypehint()
{
$this->assertTrue(_checkTypehint(new TestCallbackWithoutTypehintClass(), new \InvalidArgumentException()));
}
/** @test */
public function shouldAcceptObjectMethodCallbackWithoutTypehint()
{
$this->assertTrue(_checkTypehint([new TestCallbackWithoutTypehintClass(), 'testCallback'], new \InvalidArgumentException()));
}
/** @test */
public function shouldAcceptStaticClassCallbackWithoutTypehint()
{
$this->assertTrue(_checkTypehint(['React\Promise\TestCallbackWithoutTypehintClass', 'testCallbackStatic'], new \InvalidArgumentException()));
}
}
function testCallbackWithTypehint(\InvalidArgumentException $e)
{
}
function testCallbackWithoutTypehint()
{
}
class TestCallbackWithTypehintClass
{
public function __invoke(\InvalidArgumentException $e)
{
}
public function testCallback(\InvalidArgumentException $e)
{
}
public static function testCallbackStatic(\InvalidArgumentException $e)
{
}
}
class TestCallbackWithoutTypehintClass
{
public function __invoke()
{
}
public function testCallback()
{
}
public static function testCallbackStatic()
{
}
}

View file

@ -0,0 +1,125 @@
<?php
namespace React\Promise;
class FunctionMapTest extends TestCase
{
protected function mapper()
{
return function ($val) {
return $val * 2;
};
}
protected function promiseMapper()
{
return function ($val) {
return resolve($val * 2);
};
}
/** @test */
public function shouldMapInputValuesArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([2, 4, 6]));
map(
[1, 2, 3],
$this->mapper()
)->then($mock);
}
/** @test */
public function shouldMapInputPromisesArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([2, 4, 6]));
map(
[resolve(1), resolve(2), resolve(3)],
$this->mapper()
)->then($mock);
}
/** @test */
public function shouldMapMixedInputArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([2, 4, 6]));
map(
[1, resolve(2), 3],
$this->mapper()
)->then($mock);
}
/** @test */
public function shouldMapInputWhenMapperReturnsAPromise()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([2, 4, 6]));
map(
[1, 2, 3],
$this->promiseMapper()
)->then($mock);
}
/** @test */
public function shouldAcceptAPromiseForAnArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([2, 4, 6]));
map(
resolve([1, resolve(2), 3]),
$this->mapper()
)->then($mock);
}
/** @test */
public function shouldResolveToEmptyArrayWhenInputPromiseDoesNotResolveToArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([]));
map(
resolve(1),
$this->mapper()
)->then($mock);
}
/** @test */
public function shouldRejectWhenInputContainsRejection()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
map(
[resolve(1), reject(2), resolve(3)],
$this->mapper()
)->then($this->expectCallableNever(), $mock);
}
}

View file

@ -0,0 +1,122 @@
<?php
namespace React\Promise;
class FunctionRaceTest extends TestCase
{
/** @test */
public function shouldResolveEmptyInput()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(null));
race(
[]
)->then($mock);
}
/** @test */
public function shouldResolveValuesArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
race(
[1, 2, 3]
)->then($mock);
}
/** @test */
public function shouldResolvePromisesArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
$d1 = new Deferred();
$d2 = new Deferred();
$d3 = new Deferred();
race(
[$d1->promise(), $d2->promise(), $d3->promise()]
)->then($mock);
$d2->resolve(2);
$d1->resolve(1);
$d3->resolve(3);
}
/** @test */
public function shouldResolveSparseArrayInput()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(null));
race(
[null, 1, null, 2, 3]
)->then($mock);
}
/** @test */
public function shouldRejectIfFirstSettledPromiseRejects()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
$d1 = new Deferred();
$d2 = new Deferred();
$d3 = new Deferred();
race(
[$d1->promise(), $d2->promise(), $d3->promise()]
)->then($this->expectCallableNever(), $mock);
$d2->reject(2);
$d1->resolve(1);
$d3->resolve(3);
}
/** @test */
public function shouldAcceptAPromiseForAnArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
race(
resolve([1, 2, 3])
)->then($mock);
}
/** @test */
public function shouldResolveToNullWhenInputPromiseDoesNotResolveToArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(null));
race(
resolve(1)
)->then($mock);
}
}

View file

@ -0,0 +1,290 @@
<?php
namespace React\Promise;
class FunctionReduceTest extends TestCase
{
protected function plus()
{
return function ($sum, $val) {
return $sum + $val;
};
}
protected function append()
{
return function ($sum, $val) {
return $sum . $val;
};
}
/** @test */
public function shouldReduceValuesWithoutInitialValue()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(6));
reduce(
[1, 2, 3],
$this->plus()
)->then($mock);
}
/** @test */
public function shouldReduceValuesWithInitialValue()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(7));
reduce(
[1, 2, 3],
$this->plus(),
1
)->then($mock);
}
/** @test */
public function shouldReduceValuesWithInitialPromise()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(7));
reduce(
[1, 2, 3],
$this->plus(),
resolve(1)
)->then($mock);
}
/** @test */
public function shouldReducePromisedValuesWithoutInitialValue()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(6));
reduce(
[resolve(1), resolve(2), resolve(3)],
$this->plus()
)->then($mock);
}
/** @test */
public function shouldReducePromisedValuesWithInitialValue()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(7));
reduce(
[resolve(1), resolve(2), resolve(3)],
$this->plus(),
1
)->then($mock);
}
/** @test */
public function shouldReducePromisedValuesWithInitialPromise()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(7));
reduce(
[resolve(1), resolve(2), resolve(3)],
$this->plus(),
resolve(1)
)->then($mock);
}
/** @test */
public function shouldReduceEmptyInputWithInitialValue()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
reduce(
[],
$this->plus(),
1
)->then($mock);
}
/** @test */
public function shouldReduceEmptyInputWithInitialPromise()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
reduce(
[],
$this->plus(),
resolve(1)
)->then($mock);
}
/** @test */
public function shouldRejectWhenInputContainsRejection()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
reduce(
[resolve(1), reject(2), resolve(3)],
$this->plus(),
resolve(1)
)->then($this->expectCallableNever(), $mock);
}
/** @test */
public function shouldResolveWithNullWhenInputIsEmptyAndNoInitialValueOrPromiseProvided()
{
// Note: this is different from when.js's behavior!
// In when.reduce(), this rejects with a TypeError exception (following
// JavaScript's [].reduce behavior.
// We're following PHP's array_reduce behavior and resolve with NULL.
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(null));
reduce(
[],
$this->plus()
)->then($mock);
}
/** @test */
public function shouldAllowSparseArrayInputWithoutInitialValue()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(3));
reduce(
[null, null, 1, null, 1, 1],
$this->plus()
)->then($mock);
}
/** @test */
public function shouldAllowSparseArrayInputWithInitialValue()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(4));
reduce(
[null, null, 1, null, 1, 1],
$this->plus(),
1
)->then($mock);
}
/** @test */
public function shouldReduceInInputOrder()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo('123'));
reduce(
[1, 2, 3],
$this->append(),
''
)->then($mock);
}
/** @test */
public function shouldAcceptAPromiseForAnArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo('123'));
reduce(
resolve([1, 2, 3]),
$this->append(),
''
)->then($mock);
}
/** @test */
public function shouldResolveToInitialValueWhenInputPromiseDoesNotResolveToAnArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
reduce(
resolve(1),
$this->plus(),
1
)->then($mock);
}
/** @test */
public function shouldProvideCorrectBasisValue()
{
$insertIntoArray = function ($arr, $val, $i) {
$arr[$i] = $val;
return $arr;
};
$d1 = new Deferred();
$d2 = new Deferred();
$d3 = new Deferred();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([1, 2, 3]));
reduce(
[$d1->promise(), $d2->promise(), $d3->promise()],
$insertIntoArray,
[]
)->then($mock);
$d3->resolve(3);
$d1->resolve(1);
$d2->resolve(2);
}
}

View file

@ -0,0 +1,64 @@
<?php
namespace React\Promise;
class FunctionRejectTest extends TestCase
{
/** @test */
public function shouldRejectAnImmediateValue()
{
$expected = 123;
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($expected));
reject($expected)
->then(
$this->expectCallableNever(),
$mock
);
}
/** @test */
public function shouldRejectAFulfilledPromise()
{
$expected = 123;
$resolved = new FulfilledPromise($expected);
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($expected));
reject($resolved)
->then(
$this->expectCallableNever(),
$mock
);
}
/** @test */
public function shouldRejectARejectedPromise()
{
$expected = 123;
$resolved = new RejectedPromise($expected);
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($expected));
reject($resolved)
->then(
$this->expectCallableNever(),
$mock
);
}
}

View file

@ -0,0 +1,102 @@
<?php
namespace React\Promise;
class FunctionResolveTest extends TestCase
{
/** @test */
public function shouldResolveAnImmediateValue()
{
$expected = 123;
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($expected));
resolve($expected)
->then(
$mock,
$this->expectCallableNever()
);
}
/** @test */
public function shouldResolveAFulfilledPromise()
{
$expected = 123;
$resolved = new FulfilledPromise($expected);
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($expected));
resolve($resolved)
->then(
$mock,
$this->expectCallableNever()
);
}
/** @test */
public function shouldRejectARejectedPromise()
{
$expected = 123;
$resolved = new RejectedPromise($expected);
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($expected));
resolve($resolved)
->then(
$this->expectCallableNever(),
$mock
);
}
/** @test */
public function shouldSupportDeepNestingInPromiseChains()
{
$d = new Deferred();
$d->resolve(false);
$result = resolve(resolve($d->promise()->then(function ($val) {
$d = new Deferred();
$d->resolve($val);
$identity = function ($val) {
return $val;
};
return resolve($d->promise()->then($identity))->then(
function ($val) {
return !$val;
}
);
})));
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(true));
$result->then($mock);
}
/** @test */
public function returnsExtendePromiseForSimplePromise()
{
$promise = $this->getMock('React\Promise\PromiseInterface');
$this->assertInstanceOf('React\Promise\ExtendedPromiseInterface', resolve($promise));
}
}

View file

@ -0,0 +1,126 @@
<?php
namespace React\Promise;
class FunctionSomeTest extends TestCase
{
/** @test */
public function shouldResolveEmptyInput()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([]));
some(
[],
1
)->then($mock);
}
/** @test */
public function shouldResolveValuesArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([1, 2]));
some(
[1, 2, 3],
2
)->then($mock);
}
/** @test */
public function shouldResolvePromisesArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([1, 2]));
some(
[resolve(1), resolve(2), resolve(3)],
2
)->then($mock);
}
/** @test */
public function shouldResolveSparseArrayInput()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([null, 1]));
some(
[null, 1, null, 2, 3],
2
)->then($mock);
}
/** @test */
public function shouldRejectIfAnyInputPromiseRejectsBeforeDesiredNumberOfInputsAreResolved()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([1 => 2, 2 => 3]));
some(
[resolve(1), reject(2), reject(3)],
2
)->then($this->expectCallableNever(), $mock);
}
/** @test */
public function shouldAcceptAPromiseForAnArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([1, 2]));
some(
resolve([1, 2, 3]),
2
)->then($mock);
}
/** @test */
public function shouldResolveWithEmptyArrayIfHowManyIsLessThanOne()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([]));
some(
[1],
0
)->then($mock);
}
/** @test */
public function shouldResolveToEmptyArrayWhenInputPromiseDoesNotResolveToArray()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo([]));
some(
resolve(1),
1
)->then($mock);
}
}

View file

@ -0,0 +1,107 @@
<?php
namespace React\Promise;
use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
class LazyPromiseTest extends TestCase
{
use PromiseTest\FullTestTrait;
public function getPromiseTestAdapter(callable $canceller = null)
{
$d = new Deferred($canceller);
$factory = function () use ($d) {
return $d->promise();
};
return new CallbackPromiseAdapter([
'promise' => function () use ($factory) {
return new LazyPromise($factory);
},
'resolve' => [$d, 'resolve'],
'reject' => [$d, 'reject'],
'notify' => [$d, 'progress'],
'settle' => [$d, 'resolve'],
]);
}
/** @test */
public function shouldNotCallFactoryIfThenIsNotInvoked()
{
$factory = $this->createCallableMock();
$factory
->expects($this->never())
->method('__invoke');
new LazyPromise($factory);
}
/** @test */
public function shouldCallFactoryIfThenIsInvoked()
{
$factory = $this->createCallableMock();
$factory
->expects($this->once())
->method('__invoke');
$p = new LazyPromise($factory);
$p->then();
}
/** @test */
public function shouldReturnPromiseFromFactory()
{
$factory = $this->createCallableMock();
$factory
->expects($this->once())
->method('__invoke')
->will($this->returnValue(new FulfilledPromise(1)));
$onFulfilled = $this->createCallableMock();
$onFulfilled
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$p = new LazyPromise($factory);
$p->then($onFulfilled);
}
/** @test */
public function shouldReturnPromiseIfFactoryReturnsNull()
{
$factory = $this->createCallableMock();
$factory
->expects($this->once())
->method('__invoke')
->will($this->returnValue(null));
$p = new LazyPromise($factory);
$this->assertInstanceOf('React\\Promise\\PromiseInterface', $p->then());
}
/** @test */
public function shouldReturnRejectedPromiseIfFactoryThrowsException()
{
$exception = new \Exception();
$factory = $this->createCallableMock();
$factory
->expects($this->once())
->method('__invoke')
->will($this->throwException($exception));
$onRejected = $this->createCallableMock();
$onRejected
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$p = new LazyPromise($factory);
$p->then($this->expectCallableNever(), $onRejected);
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace React\Promise\PromiseAdapter;
use React\Promise;
class CallbackPromiseAdapter implements PromiseAdapterInterface
{
private $callbacks;
public function __construct(array $callbacks)
{
$this->callbacks = $callbacks;
}
public function promise()
{
return call_user_func_array($this->callbacks['promise'], func_get_args());
}
public function resolve()
{
return call_user_func_array($this->callbacks['resolve'], func_get_args());
}
public function reject()
{
return call_user_func_array($this->callbacks['reject'], func_get_args());
}
public function notify()
{
return call_user_func_array($this->callbacks['notify'], func_get_args());
}
public function settle()
{
return call_user_func_array($this->callbacks['settle'], func_get_args());
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace React\Promise\PromiseAdapter;
use React\Promise;
interface PromiseAdapterInterface
{
public function promise();
public function resolve();
public function reject();
public function notify();
public function settle();
}

View file

@ -0,0 +1,116 @@
<?php
namespace React\Promise;
use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
class PromiseTest extends TestCase
{
use PromiseTest\FullTestTrait;
public function getPromiseTestAdapter(callable $canceller = null)
{
$resolveCallback = $rejectCallback = $progressCallback = null;
$promise = new Promise(function ($resolve, $reject, $progress) use (&$resolveCallback, &$rejectCallback, &$progressCallback) {
$resolveCallback = $resolve;
$rejectCallback = $reject;
$progressCallback = $progress;
}, $canceller);
return new CallbackPromiseAdapter([
'promise' => function () use ($promise) {
return $promise;
},
'resolve' => $resolveCallback,
'reject' => $rejectCallback,
'notify' => $progressCallback,
'settle' => $resolveCallback,
]);
}
/** @test */
public function shouldRejectIfResolverThrowsException()
{
$exception = new \Exception('foo');
$promise = new Promise(function () use ($exception) {
throw $exception;
});
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$promise
->then($this->expectCallableNever(), $mock);
}
/** @test */
public function shouldFulfillIfFullfilledWithSimplePromise()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo('foo'));
$adapter->promise()
->then($mock);
$adapter->resolve(new SimpleFulfilledTestPromise());
}
/** @test */
public function shouldRejectIfRejectedWithSimplePromise()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo('foo'));
$adapter->promise()
->then($this->expectCallableNever(), $mock);
$adapter->resolve(new SimpleRejectedTestPromise());
}
}
class SimpleFulfilledTestPromise implements PromiseInterface
{
public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
{
try {
if ($onFulfilled) {
$onFulfilled('foo');
}
return new self('foo');
} catch (\Exception $exception) {
return new RejectedPromise($exception);
}
}
}
class SimpleRejectedTestPromise implements PromiseInterface
{
public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
{
try {
if ($onRejected) {
$onRejected('foo');
}
return new self('foo');
} catch (\Exception $exception) {
return new RejectedPromise($exception);
}
}
}

View file

@ -0,0 +1,206 @@
<?php
namespace React\Promise\PromiseTest;
use React\Promise;
trait CancelTestTrait
{
/**
* @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
*/
abstract public function getPromiseTestAdapter(callable $canceller = null);
/** @test */
public function cancelShouldCallCancellerWithResolverArguments()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->isType('callable'), $this->isType('callable'), $this->isType('callable'));
$adapter = $this->getPromiseTestAdapter($mock);
$adapter->promise()->cancel();
}
/** @test */
public function cancelShouldFulfillPromiseIfCancellerFulfills()
{
$adapter = $this->getPromiseTestAdapter(function ($resolve) {
$resolve(1);
});
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($mock, $this->expectCallableNever());
$adapter->promise()->cancel();
}
/** @test */
public function cancelShouldRejectPromiseIfCancellerRejects()
{
$adapter = $this->getPromiseTestAdapter(function ($resolve, $reject) {
$reject(1);
});
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($this->expectCallableNever(), $mock);
$adapter->promise()->cancel();
}
/** @test */
public function cancelShouldRejectPromiseWithExceptionIfCancellerThrows()
{
$e = new \Exception();
$adapter = $this->getPromiseTestAdapter(function () use ($e) {
throw $e;
});
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($e));
$adapter->promise()
->then($this->expectCallableNever(), $mock);
$adapter->promise()->cancel();
}
/** @test */
public function cancelShouldProgressPromiseIfCancellerNotifies()
{
$adapter = $this->getPromiseTestAdapter(function ($resolve, $reject, $progress) {
$progress(1);
});
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($this->expectCallableNever(), $this->expectCallableNever(), $mock);
$adapter->promise()->cancel();
}
/** @test */
public function cancelShouldCallCancellerOnlyOnceIfCancellerResolves()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->will($this->returnCallback(function ($resolve) {
$resolve();
}));
$adapter = $this->getPromiseTestAdapter($mock);
$adapter->promise()->cancel();
$adapter->promise()->cancel();
}
/** @test */
public function cancelShouldHaveNoEffectIfCancellerDoesNothing()
{
$adapter = $this->getPromiseTestAdapter(function () {});
$adapter->promise()
->then($this->expectCallableNever(), $this->expectCallableNever());
$adapter->promise()->cancel();
$adapter->promise()->cancel();
}
/** @test */
public function cancelShouldCallCancellerFromDeepNestedPromiseChain()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke');
$adapter = $this->getPromiseTestAdapter($mock);
$promise = $adapter->promise()
->then(function () {
return new Promise\Promise(function () {});
})
->then(function () {
$d = new Promise\Deferred();
return $d->promise();
})
->then(function () {
return new Promise\Promise(function () {});
});
$promise->cancel();
}
/** @test */
public function cancelCalledOnChildrenSouldOnlyCancelWhenAllChildrenCancelled()
{
$adapter = $this->getPromiseTestAdapter($this->expectCallableNever());
$child1 = $adapter->promise()
->then()
->then();
$adapter->promise()
->then();
$child1->cancel();
}
/** @test */
public function cancelShouldTriggerCancellerWhenAllChildrenCancel()
{
$adapter = $this->getPromiseTestAdapter($this->expectCallableOnce());
$child1 = $adapter->promise()
->then()
->then();
$child2 = $adapter->promise()
->then();
$child1->cancel();
$child2->cancel();
}
/** @test */
public function cancelShouldAlwaysTriggerCancellerWhenCalledOnRootPromise()
{
$adapter = $this->getPromiseTestAdapter($this->expectCallableOnce());
$adapter->promise()
->then()
->then();
$adapter->promise()
->then();
$adapter->promise()->cancel();
}
}

View file

@ -0,0 +1,15 @@
<?php
namespace React\Promise\PromiseTest;
trait FullTestTrait
{
use PromisePendingTestTrait,
PromiseSettledTestTrait,
PromiseFulfilledTestTrait,
PromiseRejectedTestTrait,
ResolveTestTrait,
RejectTestTrait,
NotifyTestTrait,
CancelTestTrait;
}

View file

@ -0,0 +1,336 @@
<?php
namespace React\Promise\PromiseTest;
trait NotifyTestTrait
{
/**
* @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
*/
abstract public function getPromiseTestAdapter(callable $canceller = null);
/** @test */
public function notifyShouldProgress()
{
$adapter = $this->getPromiseTestAdapter();
$sentinel = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($sentinel);
$adapter->promise()
->then($this->expectCallableNever(), $this->expectCallableNever(), $mock);
$adapter->notify($sentinel);
}
/** @test */
public function notifyShouldPropagateProgressToDownstreamPromises()
{
$adapter = $this->getPromiseTestAdapter();
$sentinel = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->will($this->returnArgument(0));
$mock2 = $this->createCallableMock();
$mock2
->expects($this->once())
->method('__invoke')
->with($sentinel);
$adapter->promise()
->then(
$this->expectCallableNever(),
$this->expectCallableNever(),
$mock
)
->then(
$this->expectCallableNever(),
$this->expectCallableNever(),
$mock2
);
$adapter->notify($sentinel);
}
/** @test */
public function notifyShouldPropagateTransformedProgressToDownstreamPromises()
{
$adapter = $this->getPromiseTestAdapter();
$sentinel = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->will($this->returnValue($sentinel));
$mock2 = $this->createCallableMock();
$mock2
->expects($this->once())
->method('__invoke')
->with($sentinel);
$adapter->promise()
->then(
$this->expectCallableNever(),
$this->expectCallableNever(),
$mock
)
->then(
$this->expectCallableNever(),
$this->expectCallableNever(),
$mock2
);
$adapter->notify(1);
}
/** @test */
public function notifyShouldPropagateCaughtExceptionValueAsProgress()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->will($this->throwException($exception));
$mock2 = $this->createCallableMock();
$mock2
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->promise()
->then(
$this->expectCallableNever(),
$this->expectCallableNever(),
$mock
)
->then(
$this->expectCallableNever(),
$this->expectCallableNever(),
$mock2
);
$adapter->notify(1);
}
/** @test */
public function notifyShouldForwardProgressEventsWhenIntermediaryCallbackTiedToAResolvedPromiseReturnsAPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter2 = $this->getPromiseTestAdapter();
$promise2 = $adapter2->promise();
$sentinel = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($sentinel);
// resolve BEFORE attaching progress handler
$adapter->resolve();
$adapter->promise()
->then(function () use ($promise2) {
return $promise2;
})
->then(
$this->expectCallableNever(),
$this->expectCallableNever(),
$mock
);
$adapter2->notify($sentinel);
}
/** @test */
public function notifyShouldForwardProgressEventsWhenIntermediaryCallbackTiedToAnUnresolvedPromiseReturnsAPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter2 = $this->getPromiseTestAdapter();
$promise2 = $adapter2->promise();
$sentinel = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($sentinel);
$adapter->promise()
->then(function () use ($promise2) {
return $promise2;
})
->then(
$this->expectCallableNever(),
$this->expectCallableNever(),
$mock
);
// resolve AFTER attaching progress handler
$adapter->resolve();
$adapter2->notify($sentinel);
}
/** @test */
public function notifyShouldForwardProgressWhenResolvedWithAnotherPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter2 = $this->getPromiseTestAdapter();
$sentinel = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->will($this->returnValue($sentinel));
$mock2 = $this->createCallableMock();
$mock2
->expects($this->once())
->method('__invoke')
->with($sentinel);
$adapter->promise()
->then(
$this->expectCallableNever(),
$this->expectCallableNever(),
$mock
)
->then(
$this->expectCallableNever(),
$this->expectCallableNever(),
$mock2
);
$adapter->resolve($adapter2->promise());
$adapter2->notify($sentinel);
}
/** @test */
public function notifyShouldAllowResolveAfterProgress()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->at(0))
->method('__invoke')
->with($this->identicalTo(1));
$mock
->expects($this->at(1))
->method('__invoke')
->with($this->identicalTo(2));
$adapter->promise()
->then(
$mock,
$this->expectCallableNever(),
$mock
);
$adapter->notify(1);
$adapter->resolve(2);
}
/** @test */
public function notifyShouldAllowRejectAfterProgress()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->at(0))
->method('__invoke')
->with($this->identicalTo(1));
$mock
->expects($this->at(1))
->method('__invoke')
->with($this->identicalTo(2));
$adapter->promise()
->then(
$this->expectCallableNever(),
$mock,
$mock
);
$adapter->notify(1);
$adapter->reject(2);
}
/** @test */
public function notifyShouldReturnSilentlyOnProgressWhenAlreadyRejected()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->reject(1);
$this->assertNull($adapter->notify());
}
/** @test */
public function notifyShouldInvokeProgressHandler()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()->progress($mock);
$adapter->notify(1);
}
/** @test */
public function notifyShouldInvokeProgressHandlerFromDone()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$this->assertNull($adapter->promise()->done(null, null, $mock));
$adapter->notify(1);
}
/** @test */
public function notifyShouldThrowExceptionThrownProgressHandlerFromDone()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$this->assertNull($adapter->promise()->done(null, null, function () {
throw new \Exception('UnhandledRejectionException');
}));
$adapter->notify(1);
}
}

View file

@ -0,0 +1,351 @@
<?php
namespace React\Promise\PromiseTest;
trait PromiseFulfilledTestTrait
{
/**
* @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
*/
abstract public function getPromiseTestAdapter(callable $canceller = null);
/** @test */
public function fulfilledPromiseShouldBeImmutable()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->resolve(1);
$adapter->resolve(2);
$adapter->promise()
->then(
$mock,
$this->expectCallableNever()
);
}
/** @test */
public function fulfilledPromiseShouldInvokeNewlyAddedCallback()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->resolve(1);
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($mock, $this->expectCallableNever());
}
/** @test */
public function thenShouldForwardResultWhenCallbackIsNull()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->resolve(1);
$adapter->promise()
->then(
null,
$this->expectCallableNever()
)
->then(
$mock,
$this->expectCallableNever()
);
}
/** @test */
public function thenShouldForwardCallbackResultToNextCallback()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
$adapter->resolve(1);
$adapter->promise()
->then(
function ($val) {
return $val + 1;
},
$this->expectCallableNever()
)
->then(
$mock,
$this->expectCallableNever()
);
}
/** @test */
public function thenShouldForwardPromisedCallbackResultValueToNextCallback()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
$adapter->resolve(1);
$adapter->promise()
->then(
function ($val) {
return \React\Promise\resolve($val + 1);
},
$this->expectCallableNever()
)
->then(
$mock,
$this->expectCallableNever()
);
}
/** @test */
public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackReturnsARejection()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
$adapter->resolve(1);
$adapter->promise()
->then(
function ($val) {
return \React\Promise\reject($val + 1);
},
$this->expectCallableNever()
)
->then(
$this->expectCallableNever(),
$mock
);
}
/** @test */
public function thenShouldSwitchFromCallbacksToErrbacksWhenCallbackThrows()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->will($this->throwException($exception));
$mock2 = $this->createCallableMock();
$mock2
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->resolve(1);
$adapter->promise()
->then(
$mock,
$this->expectCallableNever()
)
->then(
$this->expectCallableNever(),
$mock2
);
}
/** @test */
public function cancelShouldReturnNullForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->resolve();
$this->assertNull($adapter->promise()->cancel());
}
/** @test */
public function cancelShouldHaveNoEffectForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter($this->expectCallableNever());
$adapter->resolve();
$adapter->promise()->cancel();
}
/** @test */
public function doneShouldInvokeFulfillmentHandlerForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->resolve(1);
$this->assertNull($adapter->promise()->done($mock));
}
/** @test */
public function doneShouldThrowExceptionThrownFulfillmentHandlerForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$adapter->resolve(1);
$this->assertNull($adapter->promise()->done(function () {
throw new \Exception('UnhandledRejectionException');
}));
}
/** @test */
public function doneShouldThrowUnhandledRejectionExceptionWhenFulfillmentHandlerRejectsForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('React\\Promise\\UnhandledRejectionException');
$adapter->resolve(1);
$this->assertNull($adapter->promise()->done(function () {
return \React\Promise\reject();
}));
}
/** @test */
public function otherwiseShouldNotInvokeRejectionHandlerForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->resolve(1);
$adapter->promise()->otherwise($this->expectCallableNever());
}
/** @test */
public function alwaysShouldNotSuppressValueForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$value = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($value));
$adapter->resolve($value);
$adapter->promise()
->always(function () {})
->then($mock);
}
/** @test */
public function alwaysShouldNotSuppressValueWhenHandlerReturnsANonPromiseForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$value = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($value));
$adapter->resolve($value);
$adapter->promise()
->always(function () {
return 1;
})
->then($mock);
}
/** @test */
public function alwaysShouldNotSuppressValueWhenHandlerReturnsAPromiseForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$value = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($value));
$adapter->resolve($value);
$adapter->promise()
->always(function () {
return \React\Promise\resolve(1);
})
->then($mock);
}
/** @test */
public function alwaysShouldRejectWhenHandlerThrowsForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->resolve(1);
$adapter->promise()
->always(function () use ($exception) {
throw $exception;
})
->then(null, $mock);
}
/** @test */
public function alwaysShouldRejectWhenHandlerRejectsForFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->resolve(1);
$adapter->promise()
->always(function () use ($exception) {
return \React\Promise\reject($exception);
})
->then(null, $mock);
}
}

View file

@ -0,0 +1,68 @@
<?php
namespace React\Promise\PromiseTest;
trait PromisePendingTestTrait
{
/**
* @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
*/
abstract public function getPromiseTestAdapter(callable $canceller = null);
/** @test */
public function thenShouldReturnAPromiseForPendingPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->then());
}
/** @test */
public function thenShouldReturnAllowNullForPendingPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->then(null, null, null));
}
/** @test */
public function cancelShouldReturnNullForPendingPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->assertNull($adapter->promise()->cancel());
}
/** @test */
public function doneShouldReturnNullForPendingPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->assertNull($adapter->promise()->done());
}
/** @test */
public function doneShouldReturnAllowNullForPendingPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->assertNull($adapter->promise()->done(null, null, null));
}
/** @test */
public function otherwiseShouldNotInvokeRejectionHandlerForPendingPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->settle();
$adapter->promise()->otherwise($this->expectCallableNever());
}
/** @test */
public function alwaysShouldReturnAPromiseForPendingPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->always(function () {}));
}
}

View file

@ -0,0 +1,492 @@
<?php
namespace React\Promise\PromiseTest;
use React\Promise\Deferred;
trait PromiseRejectedTestTrait
{
/**
* @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
*/
abstract public function getPromiseTestAdapter(callable $canceller = null);
/** @test */
public function rejectedPromiseShouldBeImmutable()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->reject(1);
$adapter->reject(2);
$adapter->promise()
->then(
$this->expectCallableNever(),
$mock
);
}
/** @test */
public function rejectedPromiseShouldInvokeNewlyAddedCallback()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->reject(1);
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($this->expectCallableNever(), $mock);
}
/** @test */
public function shouldForwardUndefinedRejectionValue()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with(null);
$adapter->reject(1);
$adapter->promise()
->then(
$this->expectCallableNever(),
function () {
// Presence of rejection handler is enough to switch back
// to resolve mode, even though it returns undefined.
// The ONLY way to propagate a rejection is to re-throw or
// return a rejected promise;
}
)
->then(
$mock,
$this->expectCallableNever()
);
}
/** @test */
public function shouldSwitchFromErrbacksToCallbacksWhenErrbackDoesNotExplicitlyPropagate()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
$adapter->reject(1);
$adapter->promise()
->then(
$this->expectCallableNever(),
function ($val) {
return $val + 1;
}
)
->then(
$mock,
$this->expectCallableNever()
);
}
/** @test */
public function shouldSwitchFromErrbacksToCallbacksWhenErrbackReturnsAResolution()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
$adapter->reject(1);
$adapter->promise()
->then(
$this->expectCallableNever(),
function ($val) {
return \React\Promise\resolve($val + 1);
}
)
->then(
$mock,
$this->expectCallableNever()
);
}
/** @test */
public function shouldPropagateRejectionsWhenErrbackThrows()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->will($this->throwException($exception));
$mock2 = $this->createCallableMock();
$mock2
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->reject(1);
$adapter->promise()
->then(
$this->expectCallableNever(),
$mock
)
->then(
$this->expectCallableNever(),
$mock2
);
}
/** @test */
public function shouldPropagateRejectionsWhenErrbackReturnsARejection()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(2));
$adapter->reject(1);
$adapter->promise()
->then(
$this->expectCallableNever(),
function ($val) {
return \React\Promise\reject($val + 1);
}
)
->then(
$this->expectCallableNever(),
$mock
);
}
/** @test */
public function doneShouldInvokeRejectionHandlerForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->reject(1);
$this->assertNull($adapter->promise()->done(null, $mock));
}
/** @test */
public function doneShouldThrowExceptionThrownByRejectionHandlerForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$adapter->reject(1);
$this->assertNull($adapter->promise()->done(null, function () {
throw new \Exception('UnhandledRejectionException');
}));
}
/** @test */
public function doneShouldThrowUnhandledRejectionExceptionWhenRejectedWithNonExceptionForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('React\\Promise\\UnhandledRejectionException');
$adapter->reject(1);
$this->assertNull($adapter->promise()->done());
}
/** @test */
public function doneShouldThrowUnhandledRejectionExceptionWhenRejectionHandlerRejectsForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('React\\Promise\\UnhandledRejectionException');
$adapter->reject(1);
$this->assertNull($adapter->promise()->done(null, function () {
return \React\Promise\reject();
}));
}
/** @test */
public function doneShouldThrowRejectionExceptionWhenRejectionHandlerRejectsWithExceptionForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$adapter->reject(1);
$this->assertNull($adapter->promise()->done(null, function () {
return \React\Promise\reject(new \Exception('UnhandledRejectionException'));
}));
}
/** @test */
public function doneShouldThrowExceptionProvidedAsRejectionValueForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$adapter->reject(new \Exception('UnhandledRejectionException'));
$this->assertNull($adapter->promise()->done());
}
/** @test */
public function doneShouldThrowWithDeepNestingPromiseChainsForRejectedPromise()
{
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$exception = new \Exception('UnhandledRejectionException');
$d = new Deferred();
$d->resolve();
$result = \React\Promise\resolve(\React\Promise\resolve($d->promise()->then(function () use ($exception) {
$d = new Deferred();
$d->resolve();
return \React\Promise\resolve($d->promise()->then(function () {}))->then(
function () use ($exception) {
throw $exception;
}
);
})));
$result->done();
}
/** @test */
public function doneShouldRecoverWhenRejectionHandlerCatchesExceptionForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->reject(new \Exception('UnhandledRejectionException'));
$this->assertNull($adapter->promise()->done(null, function (\Exception $e) {
}));
}
/** @test */
public function otherwiseShouldInvokeRejectionHandlerForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->reject(1);
$adapter->promise()->otherwise($mock);
}
/** @test */
public function otherwiseShouldInvokeNonTypeHintedRejectionHandlerIfReasonIsAnExceptionForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->reject($exception);
$adapter->promise()
->otherwise(function ($reason) use ($mock) {
$mock($reason);
});
}
/** @test */
public function otherwiseShouldInvokeRejectionHandlerIfReasonMatchesTypehintForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \InvalidArgumentException();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->reject($exception);
$adapter->promise()
->otherwise(function (\InvalidArgumentException $reason) use ($mock) {
$mock($reason);
});
}
/** @test */
public function otherwiseShouldNotInvokeRejectionHandlerIfReaonsDoesNotMatchTypehintForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->expectCallableNever();
$adapter->reject($exception);
$adapter->promise()
->otherwise(function (\InvalidArgumentException $reason) use ($mock) {
$mock($reason);
});
}
/** @test */
public function alwaysShouldNotSuppressRejectionForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->reject($exception);
$adapter->promise()
->always(function () {})
->then(null, $mock);
}
/** @test */
public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsANonPromiseForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->reject($exception);
$adapter->promise()
->always(function () {
return 1;
})
->then(null, $mock);
}
/** @test */
public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsAPromiseForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->reject($exception);
$adapter->promise()
->always(function () {
return \React\Promise\resolve(1);
})
->then(null, $mock);
}
/** @test */
public function alwaysShouldRejectWhenHandlerThrowsForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception1 = new \Exception();
$exception2 = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception2));
$adapter->reject($exception1);
$adapter->promise()
->always(function () use ($exception2) {
throw $exception2;
})
->then(null, $mock);
}
/** @test */
public function alwaysShouldRejectWhenHandlerRejectsForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception1 = new \Exception();
$exception2 = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception2));
$adapter->reject($exception1);
$adapter->promise()
->always(function () use ($exception2) {
return \React\Promise\reject($exception2);
})
->then(null, $mock);
}
/** @test */
public function cancelShouldReturnNullForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->reject();
$this->assertNull($adapter->promise()->cancel());
}
/** @test */
public function cancelShouldHaveNoEffectForRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter($this->expectCallableNever());
$adapter->reject();
$adapter->promise()->cancel();
}
}

View file

@ -0,0 +1,86 @@
<?php
namespace React\Promise\PromiseTest;
trait PromiseSettledTestTrait
{
/**
* @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
*/
abstract public function getPromiseTestAdapter(callable $canceller = null);
/** @test */
public function thenShouldReturnAPromiseForSettledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->settle();
$this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->then());
}
/** @test */
public function thenShouldReturnAllowNullForSettledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->settle();
$this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->then(null, null, null));
}
/** @test */
public function cancelShouldReturnNullForSettledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->settle();
$this->assertNull($adapter->promise()->cancel());
}
/** @test */
public function cancelShouldHaveNoEffectForSettledPromise()
{
$adapter = $this->getPromiseTestAdapter($this->expectCallableNever());
$adapter->settle();
$adapter->promise()->cancel();
}
/** @test */
public function doneShouldReturnNullForSettledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->settle();
$this->assertNull($adapter->promise()->done(null, function () {}));
}
/** @test */
public function doneShouldReturnAllowNullForSettledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->settle();
$this->assertNull($adapter->promise()->done(null, function () {}, null));
}
/** @test */
public function progressShouldNotInvokeProgressHandlerForSettledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->settle();
$adapter->promise()->progress($this->expectCallableNever());
$adapter->notify();
}
/** @test */
public function alwaysShouldReturnAPromiseForSettledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$adapter->settle();
$this->assertInstanceOf('React\\Promise\\PromiseInterface', $adapter->promise()->always(function () {}));
}
}

View file

@ -0,0 +1,363 @@
<?php
namespace React\Promise\PromiseTest;
use React\Promise;
use React\Promise\Deferred;
trait RejectTestTrait
{
/**
* @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
*/
abstract public function getPromiseTestAdapter(callable $canceller = null);
/** @test */
public function rejectShouldRejectWithAnImmediateValue()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($this->expectCallableNever(), $mock);
$adapter->reject(1);
}
/** @test */
public function rejectShouldRejectWithFulfilledPromise()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($this->expectCallableNever(), $mock);
$adapter->reject(Promise\resolve(1));
}
/** @test */
public function rejectShouldRejectWithRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($this->expectCallableNever(), $mock);
$adapter->reject(Promise\reject(1));
}
/** @test */
public function rejectShouldForwardReasonWhenCallbackIsNull()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then(
$this->expectCallableNever()
)
->then(
$this->expectCallableNever(),
$mock
);
$adapter->reject(1);
}
/** @test */
public function rejectShouldMakePromiseImmutable()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then(
$this->expectCallableNever(),
$mock
);
$adapter->reject(1);
$adapter->reject(2);
}
/** @test */
public function notifyShouldInvokeOtherwiseHandler()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->otherwise($mock);
$adapter->reject(1);
}
/** @test */
public function doneShouldInvokeRejectionHandler()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$this->assertNull($adapter->promise()->done(null, $mock));
$adapter->reject(1);
}
/** @test */
public function doneShouldThrowExceptionThrownByRejectionHandler()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$this->assertNull($adapter->promise()->done(null, function () {
throw new \Exception('UnhandledRejectionException');
}));
$adapter->reject(1);
}
/** @test */
public function doneShouldThrowUnhandledRejectionExceptionWhenRejectedWithNonException()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('React\\Promise\\UnhandledRejectionException');
$this->assertNull($adapter->promise()->done());
$adapter->reject(1);
}
/** @test */
public function doneShouldThrowUnhandledRejectionExceptionWhenRejectionHandlerRejects()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('React\\Promise\\UnhandledRejectionException');
$this->assertNull($adapter->promise()->done(null, function () {
return \React\Promise\reject();
}));
$adapter->reject(1);
}
/** @test */
public function doneShouldThrowRejectionExceptionWhenRejectionHandlerRejectsWithException()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$this->assertNull($adapter->promise()->done(null, function () {
return \React\Promise\reject(new \Exception('UnhandledRejectionException'));
}));
$adapter->reject(1);
}
/** @test */
public function doneShouldThrowUnhandledRejectionExceptionWhenRejectionHandlerRetunsPendingPromiseWhichRejectsLater()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('React\\Promise\\UnhandledRejectionException');
$d = new Deferred();
$promise = $d->promise();
$this->assertNull($adapter->promise()->done(null, function () use ($promise) {
return $promise;
}));
$adapter->reject(1);
$d->reject(1);
}
/** @test */
public function doneShouldThrowExceptionProvidedAsRejectionValue()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$this->assertNull($adapter->promise()->done());
$adapter->reject(new \Exception('UnhandledRejectionException'));
}
/** @test */
public function doneShouldThrowWithDeepNestingPromiseChains()
{
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$exception = new \Exception('UnhandledRejectionException');
$d = new Deferred();
$result = \React\Promise\resolve(\React\Promise\resolve($d->promise()->then(function () use ($exception) {
$d = new Deferred();
$d->resolve();
return \React\Promise\resolve($d->promise()->then(function () {}))->then(
function () use ($exception) {
throw $exception;
}
);
})));
$result->done();
$d->resolve();
}
/** @test */
public function doneShouldRecoverWhenRejectionHandlerCatchesException()
{
$adapter = $this->getPromiseTestAdapter();
$this->assertNull($adapter->promise()->done(null, function (\Exception $e) {
}));
$adapter->reject(new \Exception('UnhandledRejectionException'));
}
/** @test */
public function alwaysShouldNotSuppressRejection()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->promise()
->always(function () {})
->then(null, $mock);
$adapter->reject($exception);
}
/** @test */
public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsANonPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->promise()
->always(function () {
return 1;
})
->then(null, $mock);
$adapter->reject($exception);
}
/** @test */
public function alwaysShouldNotSuppressRejectionWhenHandlerReturnsAPromise()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->promise()
->always(function () {
return \React\Promise\resolve(1);
})
->then(null, $mock);
$adapter->reject($exception);
}
/** @test */
public function alwaysShouldRejectWhenHandlerThrowsForRejection()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->promise()
->always(function () use ($exception) {
throw $exception;
})
->then(null, $mock);
$adapter->reject($exception);
}
/** @test */
public function alwaysShouldRejectWhenHandlerRejectsForRejection()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->promise()
->always(function () use ($exception) {
return \React\Promise\reject($exception);
})
->then(null, $mock);
$adapter->reject($exception);
}
}

View file

@ -0,0 +1,258 @@
<?php
namespace React\Promise\PromiseTest;
use React\Promise;
trait ResolveTestTrait
{
/**
* @return \React\Promise\PromiseAdapter\PromiseAdapterInterface
*/
abstract public function getPromiseTestAdapter(callable $canceller = null);
/** @test */
public function resolveShouldResolve()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($mock);
$adapter->resolve(1);
}
/** @test */
public function resolveShouldResolveWithPromisedValue()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($mock);
$adapter->resolve(Promise\resolve(1));
}
/** @test */
public function resolveShouldRejectWhenResolvedWithRejectedPromise()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then($this->expectCallableNever(), $mock);
$adapter->resolve(Promise\reject(1));
}
/** @test */
public function resolveShouldForwardValueWhenCallbackIsNull()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then(
null,
$this->expectCallableNever()
)
->then(
$mock,
$this->expectCallableNever()
);
$adapter->resolve(1);
}
/** @test */
public function resolveShouldMakePromiseImmutable()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$adapter->promise()
->then(
$mock,
$this->expectCallableNever()
);
$adapter->resolve(1);
$adapter->resolve(2);
}
/** @test */
public function doneShouldInvokeFulfillmentHandler()
{
$adapter = $this->getPromiseTestAdapter();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo(1));
$this->assertNull($adapter->promise()->done($mock));
$adapter->resolve(1);
}
/** @test */
public function doneShouldThrowExceptionThrownFulfillmentHandler()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('\Exception', 'UnhandledRejectionException');
$this->assertNull($adapter->promise()->done(function () {
throw new \Exception('UnhandledRejectionException');
}));
$adapter->resolve(1);
}
/** @test */
public function doneShouldThrowUnhandledRejectionExceptionWhenFulfillmentHandlerRejects()
{
$adapter = $this->getPromiseTestAdapter();
$this->setExpectedException('React\\Promise\\UnhandledRejectionException');
$this->assertNull($adapter->promise()->done(function () {
return \React\Promise\reject();
}));
$adapter->resolve(1);
}
/** @test */
public function alwaysShouldNotSuppressValue()
{
$adapter = $this->getPromiseTestAdapter();
$value = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($value));
$adapter->promise()
->always(function () {})
->then($mock);
$adapter->resolve($value);
}
/** @test */
public function alwaysShouldNotSuppressValueWhenHandlerReturnsANonPromise()
{
$adapter = $this->getPromiseTestAdapter();
$value = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($value));
$adapter->promise()
->always(function () {
return 1;
})
->then($mock);
$adapter->resolve($value);
}
/** @test */
public function alwaysShouldNotSuppressValueWhenHandlerReturnsAPromise()
{
$adapter = $this->getPromiseTestAdapter();
$value = new \stdClass();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($value));
$adapter->promise()
->always(function () {
return \React\Promise\resolve(1);
})
->then($mock);
$adapter->resolve($value);
}
/** @test */
public function alwaysShouldRejectWhenHandlerThrowsForFulfillment()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->promise()
->always(function () use ($exception) {
throw $exception;
})
->then(null, $mock);
$adapter->resolve(1);
}
/** @test */
public function alwaysShouldRejectWhenHandlerRejectsForFulfillment()
{
$adapter = $this->getPromiseTestAdapter();
$exception = new \Exception();
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke')
->with($this->identicalTo($exception));
$adapter->promise()
->always(function () use ($exception) {
return \React\Promise\reject($exception);
})
->then(null, $mock);
$adapter->resolve(1);
}
}

View file

@ -0,0 +1,50 @@
<?php
namespace React\Promise;
use React\Promise\PromiseAdapter\CallbackPromiseAdapter;
class RejectedPromiseTest extends TestCase
{
use PromiseTest\PromiseSettledTestTrait,
PromiseTest\PromiseRejectedTestTrait;
public function getPromiseTestAdapter(callable $canceller = null)
{
$promise = null;
return new CallbackPromiseAdapter([
'promise' => function () use (&$promise) {
if (!$promise) {
throw new \LogicException('RejectedPromise must be rejected before obtaining the promise');
}
return $promise;
},
'resolve' => function () {
throw new \LogicException('You cannot call resolve() for React\Promise\RejectedPromise');
},
'reject' => function ($reason = null) use (&$promise) {
if (!$promise) {
$promise = new RejectedPromise($reason);
}
},
'notify' => function () {
// no-op
},
'settle' => function ($reason = null) use (&$promise) {
if (!$promise) {
$promise = new RejectedPromise($reason);
}
},
]);
}
/** @test */
public function shouldThrowExceptionIfConstructedWithAPromise()
{
$this->setExpectedException('\InvalidArgumentException');
return new RejectedPromise(new RejectedPromise());
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace React\Promise\Stub;
class CallableStub
{
public function __invoke()
{
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace React\Promise;
class TestCase extends \PHPUnit_Framework_TestCase
{
public function expectCallableExactly($amount)
{
$mock = $this->createCallableMock();
$mock
->expects($this->exactly($amount))
->method('__invoke');
return $mock;
}
public function expectCallableOnce()
{
$mock = $this->createCallableMock();
$mock
->expects($this->once())
->method('__invoke');
return $mock;
}
public function expectCallableNever()
{
$mock = $this->createCallableMock();
$mock
->expects($this->never())
->method('__invoke');
return $mock;
}
public function createCallableMock()
{
return $this->getMock('React\\Promise\Stub\CallableStub');
}
}

View file

@ -0,0 +1,7 @@
<?php
$loader = @include __DIR__.'/../vendor/autoload.php';
if (!$loader) {
$loader = require __DIR__.'/../../../../vendor/autoload.php';
}
$loader->addPsr4('React\\Promise\\', __DIR__);