Skip to content

Commit

Permalink
organized tests and introduced react/promise
Browse files Browse the repository at this point in the history
  • Loading branch information
jgswift committed Oct 3, 2014
1 parent 9e6ad5b commit 309c651
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 95 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
composer.lock
vendor
vendor
test.php
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Install via composer.json using [composer](https://getcomposer.org/):
## Dependency

* php 5.5+
* [react/promise](https://github.com/reactphp/promise)

## Usage

Expand Down Expand Up @@ -181,7 +182,7 @@ $foo->setState("fizz",$event); // throws exception
```
### Emitter

Emitters encapsulate a single event and may be used in conjunction with one or many Subject implementations. Subject notifications are processed by Emitter ```__invoke```.
Emitter is a Subject where events are exposed into individual objects

#### Basic Emitter

Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
}
],
"require": {
"php": ">=5.5"
"php": ">=5.5",
"react/promise": "2.0.0"
},
"require-dev": {
"phpunit/phpunit": "3.7.*",
Expand Down
1 change: 1 addition & 0 deletions src/State/StateListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ public function getName() {
*/
public function notify(EventAwareInterface $event) {
$results = [];

if($this->isWatched()) {
$observers = $this->getObservers();
unset($this->observers); // prevent recursion
Expand Down
1 change: 0 additions & 1 deletion src/State/StateObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ public function trigger(EventAwareInterface $event, callable $callable = null) {
$event->complete($event);
$event->cancel($event);
} else {

$event->fail($event);
$event->setException($exception);
}
Expand Down
17 changes: 0 additions & 17 deletions src/Subject/Emitter/EmitterTrait.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<?php
namespace observr\Subject\Emitter {
use observr\Event;

trait EmitterTrait {
/**
* Locally stores event name
Expand Down Expand Up @@ -104,21 +102,6 @@ public function __toString() {
return $this->getName();
}

/**
* Performs filtering operation
* @param mixed $subject
* @param observr\Event $e
*/
public function execute($subject, $e = null) {
if(is_null($e)) {
$e = new Event();
}

$this->emit($e);

$subject->setState($this->name,$e);
}

/**
* Alias for execution
* @return mixed
Expand Down
77 changes: 76 additions & 1 deletion src/Subject/SubjectEmitter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,91 @@
use observr\Subject\Emitter\EmitterTrait as EmitterTrait;
use observr\Subject\Emitter\EmitterSubjectTrait as EmitterSubjectTrait;
use observr\Subject\Emitter\EmitterSubjectInterface as EmitterSubjectInterface;
use React\Promise\PromisorInterface;
use React\Promise\Promise;
use observr\Event;

abstract class SubjectEmitter implements EmitterSubjectInterface, EmitterInterface {
class SubjectEmitter implements
EmitterSubjectInterface,
EmitterInterface,
PromisorInterface
{
use FixtureTrait, EmitterSubjectTrait, EmitterTrait;

private $promise;
private $complete;
private $failure;
private $progress;

/**
* Default emitter constructor
* @param string $name
*/
function __construct($name) {
$this->setName($name);
}

public function promise() {
if(is_null($this->promise)) {
$this->promise = new Promise(function($resolve,$reject,$progress) {
$this->complete = $resolve;
$this->failure = $reject;
$this->progress = $progress;
});
}

return $this->promise;
}

/**
* Handles promise fulfillment
* @param mixed $value
*/
public function complete($value = null) {
$this->promise();

call_user_func($this->complete, $value);
}

/**
* Handles promise rejection
* @param type $reason
*/
public function fail($reason = null) {
$this->promise();

call_user_func($this->failure, $reason);
}

/**
* Hanldes promise progress
* @param type $update
*/
public function progress($update = null) {
$this->promise();

call_user_func($this->progress, $update);
}

/**
* Performs filtering operation
* @param mixed $subject
* @param observr\Event $e
*/
public function execute($subject, $e = null) {
if(is_null($e)) {
$e = new Event($subject);
}

try {
$subject->setState($this->name, $e);

$this->emit();

$this->complete();
} catch(\Exception $e) {
$this->fail($e->getMessage());
}
}
}
}
117 changes: 117 additions & 0 deletions tests/EmitterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php
namespace observr\Tests {
use observr;

/**
* @package observr
*/
class EmitterTest extends ObservrTestCase {
function testEmitterPromise() {
$click = new observr\Emitter('click');

$getPromise = function($result,$error=null) use ($click) {
if($error) {
$click->fail($error);
} else {
$click->complete($result);
}
return $click->promise();
};

$button = new Mock\Button;

$c=0;
$getPromise('hello')->then(
function($value)use(&$c) {
$c++;
}
);

$click($button);
$this->assertEquals(1,$c);
}

function testEmitterBasic() {
$click = new observr\Emitter('click');

$button = new Mock\Button;

$c = 0;

$button->attach($click, function($s,$e)use(&$c) {
$c++;
});

$click->attach(function($s,$e)use(&$c) {
$c++;
});

$click($button);

$this->assertEquals(2,$c);
}

function testCombinedEventSource() {
$click = new observr\Emitter('click');
$mouseup = new observr\Emitter('mouseup');
$mousedown = new observr\Emitter('mousedown');

$combined = $click->map(function($sender, $e) {
return $e['x'] = 'Click';
})->merge($mousedown->map(function($sender,$e) {
return $e['x'] = 'Mousedown';
}))->merge($mouseup->map(function($sender,$e) {
return $e['x'] = 'Mouseup';
}));

$button = new Mock\Button;

$c = 0;
$button->attach($click,function($sender,$e)use(&$c) {
$this->assertEquals('Click',$e['x']);
$c++;
});

$button->attach($mouseup,function($sender,$e)use(&$c) {
$this->assertEquals('Mouseup',$e['x']);
$c++;
});

$button->attach($mousedown,function($sender,$e)use(&$c) {
$this->assertEquals('Mousedown',$e['x']);
$c++;
});

$combined($button);

$this->assertEquals(3,$c);
}

function testEventFilter() {
$click = new observr\Emitter('click');

$doOK = $click
->filter(function($button,$e) {
if($button instanceof Mock\Button) {
return true;
}

return false;
})->map(function($button,$e) {
$button->value = 'Ok';
});

$button = new Mock\Button;

$c = 0;
$button->attach($click,function($sender,$e)use(&$c) {
$c++;
});

$doOK($button);

$this->assertEquals(1,$c);
$this->assertEquals('Ok',$button->value);
}
}
}

0 comments on commit 309c651

Please sign in to comment.