Skip to content

Commit 038c97c

Browse files
committed
Add AssertPromise trait
1 parent 9f3e7a8 commit 038c97c

File tree

3 files changed

+153
-137
lines changed

3 files changed

+153
-137
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ composer require seregazhuk/react-promise-testing --dev
3838
```
3939

4040
## Quick Start
41-
Just extend your test classes from `seregazhuk\React\PromiseTesting\TestCase` class,
42-
which itself extends PHPUnit `TestCase`:
43-
41+
Use the trait `seregazhuk\React\PromiseTesting\AssertPromise` or extend your
42+
test classes from `seregazhuk\React\PromiseTesting\TestCase` class,
43+
which itself extends PHPUnit `TestCase`.
44+
4445
```php
4546
final class MyTest extends TestCase
4647
{

src/AssertPromise.php

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<?php
2+
3+
namespace seregazhuk\React\PromiseTesting;
4+
5+
use Clue\React\Block;
6+
use Exception;
7+
use PHPUnit\Framework\AssertionFailedError;
8+
use React\EventLoop\Factory as LoopFactory;
9+
use React\EventLoop\LoopInterface;
10+
use React\Promise\PromiseInterface;
11+
use React\Promise\Timer\TimeoutException;
12+
13+
trait AssertPromise
14+
{
15+
protected $defaultWaitTimeout = 2;
16+
17+
private $loop;
18+
19+
/**
20+
* @param PromiseInterface $promise
21+
* @param int|null $timeout seconds to wait for resolving
22+
* @throws AssertionFailedError
23+
*/
24+
public function assertPromiseFulfills(PromiseInterface $promise, int $timeout = null): void
25+
{
26+
$failMessage = 'Failed asserting that promise fulfills. ';
27+
$this->addToAssertionCount(1);
28+
29+
try {
30+
$this->waitForPromise($promise, $timeout);
31+
} catch (TimeoutException $exception) {
32+
$this->fail($failMessage . 'Promise was cancelled due to timeout.');
33+
} catch (Exception $exception) {
34+
$this->fail($failMessage . 'Promise was rejected.');
35+
}
36+
}
37+
38+
/**
39+
* @param PromiseInterface $promise
40+
* @param mixed $value
41+
* @param int|null $timeout
42+
* @throws AssertionFailedError
43+
*/
44+
public function assertPromiseFulfillsWith(PromiseInterface $promise, $value, int $timeout = null): void
45+
{
46+
$failMessage = 'Failed asserting that promise fulfills with a specified value. ';
47+
$result = null;
48+
$this->addToAssertionCount(1);
49+
50+
try {
51+
$result = $this->waitForPromise($promise, $timeout);
52+
} catch (TimeoutException $exception) {
53+
$this->fail($failMessage . 'Promise was cancelled due to timeout.');
54+
} catch (Exception $exception) {
55+
$this->fail($failMessage . 'Promise was rejected.');
56+
}
57+
58+
$this->assertEquals($value, $result, $failMessage);
59+
}
60+
61+
/**
62+
* @throws AssertionFailedError
63+
*/
64+
public function assertPromiseFulfillsWithInstanceOf(PromiseInterface $promise, string $class, int $timeout = null): void
65+
{
66+
$failMessage = "Failed asserting that promise fulfills with a value of class $class. ";
67+
$result = null;
68+
$this->addToAssertionCount(1);
69+
70+
try {
71+
$result = $this->waitForPromise($promise, $timeout);
72+
} catch (TimeoutException $exception) {
73+
$this->fail($failMessage . 'Promise was cancelled due to timeout.');
74+
} catch (Exception $exception) {
75+
$this->fail($failMessage . 'Promise was rejected.');
76+
}
77+
78+
$this->assertInstanceOf($class, $result, $failMessage);
79+
}
80+
81+
/**
82+
* @param PromiseInterface $promise
83+
* @param int|null $timeout
84+
* @throws AssertionFailedError
85+
*/
86+
public function assertPromiseRejects(PromiseInterface $promise, int $timeout = null): void
87+
{
88+
$this->addToAssertionCount(1);
89+
90+
try {
91+
$this->waitForPromise($promise, $timeout);
92+
} catch (Exception $exception) {
93+
return;
94+
}
95+
96+
$this->fail('Failed asserting that promise rejects. Promise was fulfilled.');
97+
}
98+
99+
/**
100+
* @throws AssertionFailedError
101+
*/
102+
public function assertPromiseRejectsWith(PromiseInterface $promise, string $reasonExceptionClass, int $timeout = null): void
103+
{
104+
try {
105+
$this->waitForPromise($promise, $timeout);
106+
} catch (Exception $reason) {
107+
$this->assertInstanceOf(
108+
$reasonExceptionClass, $reason, 'Failed asserting that promise rejects with a specified reason.'
109+
);
110+
}
111+
112+
$this->fail('Failed asserting that promise rejects. Promise was fulfilled.');
113+
}
114+
115+
/**
116+
* @throws Exception
117+
* @return mixed
118+
*/
119+
public function waitForPromiseToFulfill(PromiseInterface $promise, int $timeout = null)
120+
{
121+
try {
122+
return $this->waitForPromise($promise, $timeout);
123+
} catch (Exception $exception) {
124+
$reason = get_class($exception);
125+
$this->fail("Failed to fulfill a promise. It was rejected with {$reason}.");
126+
}
127+
}
128+
129+
/**
130+
* @return mixed
131+
* @throws Exception
132+
*/
133+
public function waitForPromise(PromiseInterface $promise, int $timeout = null)
134+
{
135+
return Block\await($promise, $this->eventLoop(), $timeout ?: $this->defaultWaitTimeout);
136+
}
137+
138+
public function eventLoop(): LoopInterface
139+
{
140+
if (! $this->loop) {
141+
$this->loop = LoopFactory::create();
142+
}
143+
144+
return $this->loop;
145+
}
146+
}

src/TestCase.php

Lines changed: 3 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -2,147 +2,16 @@
22

33
namespace seregazhuk\React\PromiseTesting;
44

5-
use PHPUnit\Framework\AssertionFailedError;
65
use PHPUnit\Framework\TestCase as PHPUnitTestCase;
7-
use React\EventLoop\LoopInterface;
8-
use React\Promise\PromiseInterface;
9-
use Clue\React\Block;
10-
use Exception;
11-
use React\EventLoop\Factory as LoopFactory;
12-
use React\Promise\Timer\TimeoutException;
136

147
abstract class TestCase extends PHPUnitTestCase
158
{
16-
private const DEFAULT_WAIT_TIMEOUT = 2;
17-
18-
private $loop;
9+
use AssertPromise;
1910

2011
protected function setUp(): void
2112
{
22-
$this->loop = LoopFactory::create();
23-
}
24-
25-
/**
26-
* @param PromiseInterface $promise
27-
* @param int|null $timeout seconds to wait for resolving
28-
* @throws AssertionFailedError
29-
*/
30-
public function assertPromiseFulfills(PromiseInterface $promise, int $timeout = null): void
31-
{
32-
$failMessage = 'Failed asserting that promise fulfills. ';
33-
$this->addToAssertionCount(1);
34-
35-
try {
36-
$this->waitForPromise($promise, $timeout);
37-
} catch (TimeoutException $exception) {
38-
$this->fail($failMessage . 'Promise was cancelled due to timeout.');
39-
} catch (Exception $exception) {
40-
$this->fail($failMessage . 'Promise was rejected.');
41-
}
42-
}
43-
44-
/**
45-
* @param PromiseInterface $promise
46-
* @param mixed $value
47-
* @param int|null $timeout
48-
* @throws AssertionFailedError
49-
*/
50-
public function assertPromiseFulfillsWith(PromiseInterface $promise, $value, int $timeout = null): void
51-
{
52-
$failMessage = 'Failed asserting that promise fulfills with a specified value. ';
53-
$result = null;
54-
$this->addToAssertionCount(1);
55-
56-
try {
57-
$result = $this->waitForPromise($promise, $timeout);
58-
} catch (TimeoutException $exception) {
59-
$this->fail($failMessage . 'Promise was cancelled due to timeout.');
60-
} catch (Exception $exception) {
61-
$this->fail($failMessage . 'Promise was rejected.');
62-
}
63-
64-
$this->assertEquals($value, $result, $failMessage);
65-
}
66-
67-
/**
68-
* @throws AssertionFailedError
69-
*/
70-
public function assertPromiseFulfillsWithInstanceOf(PromiseInterface $promise, string $class, int $timeout = null): void
71-
{
72-
$failMessage = "Failed asserting that promise fulfills with a value of class $class. ";
73-
$result = null;
74-
$this->addToAssertionCount(1);
75-
76-
try {
77-
$result = $this->waitForPromise($promise, $timeout);
78-
} catch (TimeoutException $exception) {
79-
$this->fail($failMessage . 'Promise was cancelled due to timeout.');
80-
} catch (Exception $exception) {
81-
$this->fail($failMessage . 'Promise was rejected.');
82-
}
83-
84-
$this->assertInstanceOf($class, $result, $failMessage);
85-
}
86-
87-
/**
88-
* @param PromiseInterface $promise
89-
* @param int|null $timeout
90-
* @throws AssertionFailedError
91-
*/
92-
public function assertPromiseRejects(PromiseInterface $promise, int $timeout = null): void
93-
{
94-
$this->addToAssertionCount(1);
95-
96-
try {
97-
$this->waitForPromise($promise, $timeout);
98-
} catch (Exception $exception) {
99-
return;
100-
}
101-
102-
$this->fail('Failed asserting that promise rejects. Promise was fulfilled.');
103-
}
104-
105-
/**
106-
* @throws AssertionFailedError
107-
*/
108-
public function assertPromiseRejectsWith(PromiseInterface $promise, string $reasonExceptionClass, int $timeout = null): void
109-
{
110-
try {
111-
$this->waitForPromise($promise, $timeout);
112-
} catch (Exception $reason) {
113-
$this->assertInstanceOf(
114-
$reasonExceptionClass, $reason, 'Failed asserting that promise rejects with a specified reason.'
115-
);
116-
}
117-
118-
$this->fail('Failed asserting that promise rejects. Promise was fulfilled.');
119-
}
120-
121-
/**
122-
* @throws Exception
123-
* @return mixed
124-
*/
125-
public function waitForPromiseToFulfill(PromiseInterface $promise, int $timeout = null)
126-
{
127-
try {
128-
return $this->waitForPromise($promise, $timeout);
129-
} catch (Exception $exception) {
130-
$reason = get_class($exception);
131-
$this->fail("Failed to fulfill a promise. It was rejected with {$reason}.");
132-
}
133-
}
134-
135-
/**
136-
* @return mixed
137-
* @throws Exception
138-
*/
139-
public function waitForPromise(PromiseInterface $promise, int $timeout = null)
140-
{
141-
return Block\await($promise, $this->loop, $timeout ?: self::DEFAULT_WAIT_TIMEOUT);
142-
}
13+
parent::setUp();
14314

144-
public function eventLoop(): LoopInterface
145-
{
146-
return $this->loop;
15+
$this->eventLoop();
14716
}
14817
}

0 commit comments

Comments
 (0)