Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add assertTrueAboutPromise() and assertFalseAboutPromise() #21

Merged
merged 7 commits into from
Jul 3, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ assertions for testing ReactPHP promises.
- [assertPromiseFulfillsWithInstanceOf()](#assertpromisefulfillswithinstanceof)
- [assertPromiseRejects()](#assertpromiserejects())
- [assertPromiseRejectsWith()](#assertpromiserejectswith)
- [assertTrueAboutPromise](#asserttrueaboutpromise)
- [assertFalseAboutPromise](#assertfalseaboutpromise)

- [Helpers](#helpers)
- [waitForPromiseToFulfill()](#waitforpromisetofulfill)
Expand Down Expand Up @@ -246,6 +248,81 @@ Failed asserting that promise rejects with a specified reason.
Failed asserting that LogicException Object (...) is an instance of class "InvalidArgumentException".
```

### assertTrueAboutPromise()
`assertTrueAboutPromise(PromiseInterface $promise, callable $predicate, int $timeout = null): void`

The test fails if the value encapsulated in the Promise does not conform to an arbitrary predicate.

You can specify `$timeout` in seconds to wait for promise to be resolved.
If the promise was not fulfilled in specified timeout, it rejects with `React\Promise\Timer\TimeoutException`.
When not specified, timeout is set to 2 seconds.

```php
final class AssertTrueAboutPromiseTest extends TestCase
{
/** @test */
public function promise_encapsulates_integer(): void
{
$deferred = new Deferred();
$deferred->resolve(23);

$this->assertTrueAboutPromise($deferred->promise(), function ($val) {
return is_object($val);
});
}
}
```

```bash
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

F 1 / 1 (100%)

Time: 136 ms, Memory: 4.00MB

There was 1 failure:

1) seregazhuk\React\PromiseTesting\tests\AssertTrueAboutPromiseTest::promise_encapsulates_integer
Failed asserting that false is true.
```

### assertFalseAboutPromise()
`assertFalseAboutPromise(PromiseInterface $promise, callable $predicate, int $timeout = null): void`

The test fails if the value encapsulated in the Promise conforms to an arbitrary predicate.

You can specify `$timeout` in seconds to wait for promise to be resolved.
If the promise was not fulfilled in specified timeout, it rejects with `React\Promise\Timer\TimeoutException`.
When not specified, timeout is set to 2 seconds.

```php
final class AssertFalseAboutPromiseTest extends TestCase
{
/** @test */
public function promise_encapsulates_object(): void
{
$deferred = new Deferred();
$deferred->resolve(23);

$this->assertFalseAboutPromise($deferred->promise(), function ($val) {
return is_int($val);
});
}
}
```

```bash
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

F 1 / 1 (100%)

Time: 136 ms, Memory: 4.00MB

There was 1 failure:

1) seregazhuk\React\PromiseTesting\tests\AssertFalseAboutPromiseTest::promise_encapsulates_object
Failed asserting that true is false.
```

## Helpers

Expand Down
55 changes: 55 additions & 0 deletions src/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,34 @@ public function assertPromiseFulfillsWith(PromiseInterface $promise, $value, int
$this->assertEquals($value, $result, $failMessage);
}

/**
* @param PromiseInterface $promise
* @param callable $predicate
* @param int|null $timeout
* @throws AssertionFailedError
*/
public function assertTrueAboutPromise(
PromiseInterface $promise,
callable $predicate,
int $timeout = null
): void {
$this->assertAboutPromise($promise, $predicate, $timeout);
}

/**
* @param PromiseInterface $promise
* @param callable $predicate
* @param int|null $timeout
* @throws AssertionFailedError
*/
public function assertFalseAboutPromise(
PromiseInterface $promise,
callable $predicate,
int $timeout = null
): void {
$this->assertAboutPromise($promise, $predicate, $timeout, false);
}

/**
* @throws AssertionFailedError
*/
Expand Down Expand Up @@ -145,4 +173,31 @@ public function eventLoop(): LoopInterface
{
return $this->loop;
}

/**
* @param PromiseInterface $promise
* @param callable $predicate
* @param int|null $timeout
* @param bool $assertTrue
* @throws AssertionFailedError
*/
private function assertAboutPromise(
PromiseInterface $promise,
callable $predicate,
int $timeout = null,
bool $assertTrue = true
): void {
$result = $assertTrue ? false : true;
$this->addToAssertionCount(1);

try {
$result = $predicate($this->waitForPromise($promise, $timeout));
} catch (TimeoutException $exception) {
$this->fail('Promise was cancelled due to timeout');
} catch (Exception $exception) {
$this->fail('Failed asserting that promise was fulfilled. Promise was rejected');
}

$assertTrue ? $this->assertTrue($result) : $this->assertFalse($result);
}
}
68 changes: 68 additions & 0 deletions tests/AboutPromiseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace seregazhuk\React\PromiseTesting\tests;

use Exception;
use React\Promise\Deferred;
use seregazhuk\React\PromiseTesting\TestCase;

final class AboutPromiseTest extends TestCase
{
/** @test */
public function predicate_function_reveals_what_is_true_about_promise(): void
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you used tabs instead of spaces here. Can you fix it, please?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will. Thanks for responding.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this look better? a5a2f7d

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! 🔥 There is a conflict with master branch. Can you fix it? and I'll merge the request.

{
try {
$fst = new Deferred;
$fst->resolve(23);

$snd = new Deferred;
$snd->reject(new Exception('An error'));

$thd = new Deferred;
$thd->reject('Another error');

$this->assertTrueAboutPromise($fst->promise(), function ($val): bool {
return is_int($val) && $val > 20;
});
$this->assertTrueAboutPromise($fst->promise(), 'is_string');

$this->assertTrueAboutPromise($snd->promise(), 'is_string');

$this->assertTrueAboutPromise($thd->promise(), 'is_string');
} catch (Exception $exception) {
$this->assertRegExp(
'/Failed asserting that .+/',
$exception->getMessage()
);
}
}

/** @test */
public function predicate_function_reveals_what_is_false_about_promise(): void
{
try {
$fst = new Deferred;
$fst->resolve(23);

$snd = new Deferred;
$snd->reject(new Exception('An error'));

$thd = new Deferred;
$thd->reject('Another error');

$this->assertFalseAboutPromise($fst->promise(), function ($val): bool {
return is_int($val) && $val > 20;
});
$this->assertFalseAboutPromise($fst->promise(), 'is_string');

$this->assertFalseAboutPromise($snd->promise(), 'is_string');

$this->assertFalseAboutPromise($thd->promise(), 'is_int');
} catch (Exception $exception) {
$this->assertRegExp(
'/Failed asserting that .+/',
$exception->getMessage()
);
}
}
}