Skip to content

Commit

Permalink
test: add tests that close #52 after #70's implementation (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
g105b authored May 5, 2024
1 parent 0bdb4d7 commit ac75701
Showing 1 changed file with 64 additions and 0 deletions.
64 changes: 64 additions & 0 deletions test/phpunit/PromiseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use RuntimeException;
use stdClass;
use Throwable;
use TypeError;
use ValueError;

class PromiseTest extends TestCase {
Expand Down Expand Up @@ -902,4 +903,67 @@ protected function mockCallableThrowsException(
->will(self::throwException($exception));
return $mock;
}

/*
* The functionality tested here is an important distinction in the PHP
* implemnetation, because of the type safety PHP can enforce compared
* to the JavaScript implementation. If there's a catch function, but
* the type of exception does not match the actual rejection, the
* rejection should be thrown to the main thread instead.
*/
public function testCatchRejectionHandlerIsNotCalledByTypeHintedOnRejectedCallback() {
$exception = new RangeException();
$promiseContainer = $this->getTestPromiseContainer();
$sut = $promiseContainer->getPromise();

$shouldNeverBeCalled = self::mockCallable(0);
self::expectException(RangeException::class);

$sut->catch(function(PromiseException $reason) use($shouldNeverBeCalled) {
call_user_func($shouldNeverBeCalled, $reason);
});

$promiseContainer->reject($exception);
}

public function testMatchingTypedCatchRejectionHandlerCanHandleInternalTypeErrors() {
$exception = new RangeException("No, Michael, no!");
$promiseContainer = $this->getTestPromiseContainer();
$sut = $promiseContainer->getPromise();

$onRejected1 = self::mockCallable(0);
$onRejected2 = self::mockCallable(0);

// There is a type error in the matching catch callback. This
// should bubble out of the chain rather than being seen as
// missing the RangeException type hint.
self::expectException(TypeError::class);
self::expectExceptionMessage("DateTime::__construct(): Argument #1 (\$datetime) must be of type string, Closure given");

$sut->catch(function(PromiseException $reason1) use($onRejected1) {
call_user_func($onRejected1, $reason1);
})
->catch(function(RangeException $reason2) use($onRejected2) {
new DateTime(fn() => "That was so not right!");
call_user_func($onRejected2, $reason2);
});
$promiseContainer->reject($exception);
}

public function testCatchRejectionHandlerIsCalledByAnotherMatchingTypeHintedOnRejectedCallback() {
$exception = new RangeException();
$promiseContainer = $this->getTestPromiseContainer();
$sut = $promiseContainer->getPromise();

$onRejected1 = self::mockCallable(0);
$onRejected2 = self::mockCallable(1);

$sut->catch(function(PromiseException $reason) use($onRejected1) {
call_user_func($onRejected1, $reason);
})->catch(function(RangeException $reason) use($onRejected2) {
call_user_func($onRejected2, $reason);
});

$promiseContainer->reject($exception);
}
}

0 comments on commit ac75701

Please sign in to comment.