From 3fdbb2cbfe778fcf48c61bb9fe40d4ac85f8004f Mon Sep 17 00:00:00 2001 From: Fabio Bas Date: Thu, 19 Sep 2013 23:07:57 +0200 Subject: Committed TComponent patch by javalizard TComponent Update: Behaviors, Class Behaviors, fx global events, and dy one to one events. This patchset was currently available only on svn trunk/ --- tests/unit/TComponentTest.php | 1940 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1926 insertions(+), 14 deletions(-) (limited to 'tests/unit/TComponentTest.php') diff --git a/tests/unit/TComponentTest.php b/tests/unit/TComponentTest.php index ff411954..93668dc0 100644 --- a/tests/unit/TComponentTest.php +++ b/tests/unit/TComponentTest.php @@ -1,9 +1,19 @@ _text; @@ -13,6 +23,14 @@ class NewComponent extends TComponent { $this->_text=$value; } + public function getReadOnlyProperty() { + return 'read only'; + } + + public function getJsReadOnlyJsProperty() { + return 'js read only'; + } + public function getObject() { if(!$this->_object) { $this->_object=new NewComponent; @@ -29,10 +47,363 @@ class NewComponent extends TComponent { $this->_eventHandled=true; } + public function eventReturnValue($sender,$param) { + return $param->Return; + } + public function isEventHandled() { return $this->_eventHandled; } + + public function resetEventHandled() { + $this->_eventHandled = false; + } + public function getReturn() { + return $this->_return; + } + public function setReturn($return) { + $this->_return = $return; + } + public function getjsColorAttribute() { + return $this->_colorattribute; + } + public function setjsColorAttribute($colorattribute) { + $this->_colorattribute = $colorattribute; + } +} + + +class NewComponentNoListen extends NewComponent { + // this object does _not_ auto install global listeners during construction + public function getAutoGlobalListen() { + return false; + } +} + +class DynamicCatchingComponent extends NewComponentNoListen implements IDynamicMethods { + public function __dycall($method, $args) { + + } +} + + +class GlobalRaiseComponent extends NewComponent implements IDynamicMethods { + private $_callorder = array(); + + public function getCallOrders() + { + return $this->_callorder; + } + public function __dycall($method, $args) { + if(strncasecmp($method,'fx',2)!==0) return; + $this->_callorder[] = 'fxcall'; + } + public function fxGlobalListener($sender,$param,$name) { + $this->_callorder[] = 'fxGL'; + } + public function fxPrimaryGlobalEvent($sender,$param,$name) { + $this->_callorder[] = 'primary'; + } + public function commonRaiseEventListener($sender,$param,$name) { + $this->_callorder[] = 'com'; + } + public function postglobalRaiseEventListener($sender,$param,$name) { + $this->_callorder[] = 'postgl'; + } + public function preglobalRaiseEventListener($sender,$param,$name) { + $this->_callorder[] = 'pregl'; + } +} + + + +class FooClassBehavior extends TClassBehavior { + private $_baseObject = null; + public function faaEverMore($object, $laa, $sol) { + $this->_baseObject = $object; + return $laa * $sol; + } + public function getLastClassObject() {return $this->_baseObject;} +} + +class FooFooClassBehavior extends FooClassBehavior { + public function faafaaEverMore($object, $laa, $sol) { + + } +} + +class BarClassBehavior extends TClassBehavior { + public function moreFunction($object, $laa, $sol) { + return true; + } +} + + + +class FooBehavior extends TBehavior { + public function faaEverMore($laa, $sol) { + return true; + } } +class FooFooBehavior extends FooBehavior { + + public function faafaaEverMore($laa, $sol) { + return sqrt($laa * $laa + $sol * $sol); + } +} +class FooBarBehavior extends TBehavior { + public function moreFunction($laa, $sol) { + return $laa * $sol * $sol; + } +} + +class PreBarBehavior extends TBehavior { +} + +class BarBehavior extends PreBarBehavior implements IInstanceCheck { + private $_instanceReturn = null; + + public function moreFunction($laa, $sol) { + return pow($laa+$sol+1, 2); + } + + public function isinstanceof($class, $instance=null) { + return $this->_instanceReturn; + } + public function setInstanceReturn($value) { + $this->_instanceReturn = $value; + } +} +class DynamicCallComponent extends NewComponent implements IDynamicMethods { + public function __dycall($method, $args) { + if($method === 'dyPowerFunction') + return pow($args[0], $args[1]); + if($method === 'dyDivisionFunction') + return $args[0] / $args[1]; + if($method === 'fxPowerFunction') + return 2*pow($args[0], $args[1]); + if($method === 'fxDivisionFunction') + return 2*$args[0] / $args[1]; + } +} + + + +class BehaviorTestBehavior extends TBehavior { + private $excitement = 'faa'; + public function getExcitement() { + return $this->excitement; + } + public function setExcitement($value) { + $this->excitement = $value; + } + public function getReadOnly() { + return true; + } + + public function onBehaviorEvent($sender, $param,$responsetype=null,$postfunction=null) { + return $this->getOwner()->raiseEvent('onBehaviorEvent',$sender,$param,$responsetype,$postfunction); + } + public function fxGlobalBehaviorEvent($sender, $param) { + } +} + +class dy1TextReplace extends TBehavior { + protected $_called = false; + public function dyTextFilter($text, $callchain) { + $this->_called = true; + return str_replace("..", '__', $callchain->dyTextFilter($text)); + } + public function isCalled() { + return $this->_called; + } + public function dyPowerFunction($x, $y, $callchain) + { + return pow($x / $callchain->dyPowerFunction($x, $y), $y); + } +} +class dy2TextReplace extends dy1TextReplace { + public function dyTextFilter($text, $callchain) { + $this->_called = true; + return str_replace("++", '||', $callchain->dyTextFilter($text)); + } +} +class dy3TextReplace extends dy1TextReplace { + public function dyTextFilter($text, $callchain) { + $this->_called = true; + return str_replace("!!", '??', $callchain->dyTextFilter($text)); + } +} + +class dy1ClassTextReplace extends TClassBehavior { + protected $_called = false; + public function dyTextFilter($hostobject, $text, $callchain) { + $this->_called = true; + return str_replace("__", '..', $callchain->dyTextFilter($text)); + } + public function isCalled() { + return $this->_called; + } + public function dyPowerFunction($hostobject, $x, $y, $callchain) + { + return pow($x / $callchain->dyPowerFunction($x, $y), $y); + } +} +class dy2ClassTextReplace extends dy1ClassTextReplace { + public function dyTextFilter($hostobject, $text, $callchain) { + $this->_called = true; + return str_replace("||", '++', $callchain->dyTextFilter($text)); + } +} +class dy3ClassTextReplace extends dy1ClassTextReplace { + public function dyTextFilter($hostobject, $text, $callchain) { + $this->_called = true; + return str_replace("??", '^_^', $callchain->dyTextFilter($text)); + } +} + + +class IntraObjectExtenderBehavior extends TBehavior { + + private $lastCall = null; + private $arglist = null; + + public function getLastCall() { + $v = $this->lastCall; + $this->lastCall = null; + return $v; + } + + public function getLastArgumentList() { + $v = $this->arglist; + $this->arglist = null; + return $v; + } + + + + public function dyListen($fx, $chain) { + $this->lastCall = 1; + $this->arglist = func_get_args(); + + return $chain->dyListen($fx); // Calls the next event, within a chain + } + public function dyUnlisten($fx, $chain) { + $this->lastCall = 2; + $this->arglist = func_get_args(); + + return $chain->dyUnlisten($fx); + } + public function dyPreRaiseEvent($name,$sender,$param,$responsetype,$postfunction, $chain) { + $this->lastCall = 3; + $this->arglist = func_get_args(); + + return $chain->dyPreRaiseEvent($name);// Calls the next event, within a chain, if parameters are left off, they are filled in with + // the original parameters passed to the dynamic event. Parameters can be passed if they are changed. + } + public function dyIntraRaiseEventTestHandler($handler,$sender,$param,$name, $chain) { + $this->lastCall += 4; + $this->arglist = func_get_args(); + } + public function dyIntraRaiseEventPostHandler($name,$sender,$param,$handler, $chain) { + $this->lastCall += 5; + $this->arglist = func_get_args(); + } + public function dyPostRaiseEvent($responses,$name,$sender,$param,$responsetype,$postfunction, $chain) { + $this->lastCall += 6; + $this->arglist = func_get_args(); + } + public function dyEvaluateExpressionFilter($expression, $chain) { + $this->lastCall = 7; + $this->arglist = func_get_args(); + return $expression; + } + public function dyEvaluateStatementsFilter($statement, $chain) { + $this->lastCall = 8; + $this->arglist = func_get_args(); + return $statement; + } + public function dyCreatedOnTemplate($parent, $chain) { + $this->lastCall = 9; + $this->arglist = func_get_args(); + return $parent; + } + public function dyAddParsedObject($object, $chain) { + $this->lastCall = 10; + $this->arglist = func_get_args(); + } + public function dyAttachBehavior($name,$behavior, $chain) { + $this->lastCall = 11; + $this->arglist = func_get_args(); + } + public function dyDetachBehavior($name,$behavior, $chain) { + $this->lastCall = 12; + $this->arglist = func_get_args(); + } + public function dyEnableBehaviors($chain) { + $this->lastCall += 13; + $this->arglist = func_get_args(); + } + public function dyDisableBehaviors($chain) { + $this->lastCall = 14; + $this->arglist = func_get_args(); + } + public function dyEnableBehavior($name,$behavior, $chain) { + $this->lastCall = 15; + $this->arglist = func_get_args(); + } + public function dyDisableBehavior($name,$behavior, $chain) { + $this->lastCall = 16; + $this->arglist = func_get_args(); + } +} + + +class IntraClassObjectExtenderBehavior extends TClassBehavior { +} + + +class TDynamicBehavior extends TBehavior implements IDynamicMethods { + private $_dyMethod = null; + public function getLastBehaviorDynamicMethodCalled() { + return $this->_dyMethod; + } + public function __dycall($method, $args) { + $this->_dyMethod = $method; + if($method == 'dyTestDynamicBehaviorMethod') + return $args[0] / $args[1]; + } + public function dyTestIntraEvent($param1, $param2, $chain) { + return $chain->dyTestIntraEvent($param1*2*$param2, $param2); + } + public function TestBehaviorMethod($param1, $param2) { + return $param1 * $param2; + } +} + + +class TDynamicClassBehavior extends TClassBehavior implements IDynamicMethods { + private $_dyMethod = null; + public function getLastBehaviorDynamicMethodCalled() { + return $this->_dyMethod; + } + //Dynamic Calls within class behaviors contain the main object as the first parameter within the args + public function __dycall($method, $args) { + $this->_dyMethod = $method; + $object = array_shift($args); + if($method == 'dyTestDynamicClassBehaviorMethod') + return $args[0] / $args[1]; + } + public function dyTestIntraEvent($object, $param1, $param2, $chain) { + return $chain->dyTestIntraEvent($param1*2*$param2, $param2); + } + public function TestBehaviorMethod($object, $param1, $param2) { + return $param1 * $param2; + } +} + + + /** * @package System @@ -45,26 +416,761 @@ class TComponentTest extends PHPUnit_Framework_TestCase { $this->component = new NewComponent(); } + public function tearDown() { + // PHP version 5.3.6 doesn't call the __destruct method when unsetting variables; + // Thus any object that listens must be explicitly call unlisten in this version of PHP. + if($this->component) + $this->component->unlisten(); $this->component = null; } + + + public function testGetListeningToGlobalEvents() { + $this->assertEquals(true, $this->component->getListeningToGlobalEvents()); + $this->component->unlisten(); + $this->assertEquals(false, $this->component->getListeningToGlobalEvents()); + } + + + public function testConstructorAutoListen() { + // the default object auto installs class behavior hooks + $this->assertEquals(1, $this->component->getEventHandlers('fxAttachClassBehavior')->getCount()); + $this->assertEquals(1, $this->component->getEventHandlers('fxDetachClassBehavior')->getCount()); + $this->assertTrue($this->component->getListeningToGlobalEvents()); + + // this object does not auto install class behavior hooks, thus not changing the global event structure. + // Creating a new instance should _not_ influence the fxAttachClassBehavior and fxDetachClassBehavior + // count. + $component_nolisten = new NewComponentNoListen(); + $this->assertEquals(1, $this->component->getEventHandlers('fxAttachClassBehavior')->getCount()); + $this->assertEquals(1, $this->component->getEventHandlers('fxDetachClassBehavior')->getCount()); + $this->assertEquals(1, $component_nolisten->getEventHandlers('fxAttachClassBehavior')->getCount()); + $this->assertEquals(1, $component_nolisten->getEventHandlers('fxDetachClassBehavior')->getCount()); + + // tests order of class behaviors when a parent and class have class behavior. + // The child should override the parent object-oriented programming style + $this->component->attachClassBehavior('Bar', 'BarBehavior', 'NewComponentNoListen'); + $this->component->attachClassBehavior('FooBar', 'FooBarBehavior', 'NewComponent'); + + //create new object with new class behaviors built in, defined in the two lines above + $component = new NewComponentNoListen; + + $this->assertEquals(25, $component->moreFunction(2, 2)); + + $this->assertEquals(25, $component->Bar->moreFunction(2, 2)); + $this->assertEquals(8, $component->FooBar->moreFunction(2, 2)); + + $component->unlisten();// unwind object and class behaviors + $this->component->detachClassBehavior('FooBar', 'NewComponent'); + $this->component->detachClassBehavior('Bar', 'NewComponentNoListen'); + + } + + + public function testListenAndUnlisten() { + + $component = new NewComponentNoListen(); + + $this->assertEquals(false, $component->getListeningToGlobalEvents()); + + //This is from $this->component being instanced and listening. $component is accessing the global event structure + $this->assertEquals(1, $component->getEventHandlers('fxAttachClassBehavior')->getCount()); + + $this->assertEquals(2, $component->listen()); + + $this->assertEquals(true, $component->getListeningToGlobalEvents()); + + //This is from $this->component being instanced and listening. $component is accessing the global event structure + $this->assertEquals(2, $component->getEventHandlers('fxAttachClassBehavior')->getCount()); + + $this->assertEquals(2, $component->unlisten()); + + $this->assertEquals(false, $component->getListeningToGlobalEvents()); + + //This is from $this->component being instanced and listening. $component is accessing the global event structure + $this->assertEquals(1, $component->getEventHandlers('fxAttachClassBehavior')->getCount()); + } + + + public function testListenAndUnlistenWithDynamicEventCatching() { + + $component = new DynamicCatchingComponent(); + + $this->assertEquals(false, $component->getListeningToGlobalEvents()); + + //This is from $this->component being instanced and listening. $component is accessing the global event structure + $this->assertEquals(0, $component->getEventHandlers(TComponent::GLOBAL_RAISE_EVENT_LISTENER)->getCount()); + + // this adds the fxAttachClassBehavior, fxDetachClassBehavior, and __dycall of the component + $this->assertEquals(3, $component->listen()); + + $this->assertEquals(true, $component->getListeningToGlobalEvents()); + + //This is from $this->component being instanced and listening. $component is accessing the global event structure + $this->assertEquals(1, $component->getEventHandlers(TComponent::GLOBAL_RAISE_EVENT_LISTENER)->getCount()); + + $this->assertEquals(3, $component->unlisten()); + + $this->assertEquals(false, $component->getListeningToGlobalEvents()); + + //This is from $this->component being instanced and listening. $component is accessing the global event structure + $this->assertEquals(0, $component->getEventHandlers(TComponent::GLOBAL_RAISE_EVENT_LISTENER)->getCount()); + } + + + + //Test Class behaviors + public function testAttachClassBehavior() { + + // ensure that the class is listening + $this->assertEquals(1, $this->component->getEventHandlers('fxAttachClassBehavior')->getCount()); + + //Test that the component is not a FooClassBehavior + $this->assertNull($this->component->asa('FooClassBehavior'), "Component is already a FooClassBehavior and should not have this behavior"); + + //Add the FooClassBehavior + $this->component->attachClassBehavior('FooClassBehavior', new FooClassBehavior); + + //Test that the existing listening component can be a FooClassBehavior + $this->assertNotNull($this->component->asa('FooClassBehavior'), "Component is does not have the FooClassBehavior and should have this behavior"); + + // test if the function modifies new instances of the object + $anothercomponent = new NewComponent(); + + //The new component should be a FooClassBehavior + $this->assertNotNull($anothercomponent->asa('FooClassBehavior'), "anothercomponent does not have the FooClassBehavior"); + + // test when overwriting an existing class behavior, it should throw an TInvalidOperationException + try { + $this->component->attachClassBehavior('FooClassBehavior', new BarClassBehavior); + $this->fail('TInvalidOperationException not raised when overwriting an existing behavior'); + } catch(TInvalidOperationException $e) { + } + + + // test when overwriting an existing class behavior, it should throw an TInvalidOperationException + try { + $this->component->attachClassBehavior('FooBarBehavior', 'FooBarBehavior', 'TComponent'); + $this->fail('TInvalidOperationException not raised when trying to place a behavior on the root object TComponent'); + } catch(TInvalidOperationException $e) { + } + + + // test if the function does not modify any existing objects that are not listening + // The FooClassBehavior is already a part of the class behaviors thus the new instance gets the behavior. + $nolistencomponent = new NewComponentNoListen(); + + // test if the function modifies all existing objects that are listening + // Adding a behavior to the first object, the second instance should automatically get the class behavior. + // This is because the second object is listening to the global events of class behaviors + $this->component->attachClassBehavior('BarClassBehavior', new BarClassBehavior); + $this->assertNotNull($anothercomponent->asa('BarClassBehavior'), "anothercomponent is does not have the BarClassBehavior"); + + // The no listen object should not have the BarClassBehavior because it was added as a class behavior after the object was instanced + $this->assertNull($nolistencomponent->asa('BarClassBehavior'), "nolistencomponent has the BarClassBehavior and should not"); + + // But the no listen object should have the FooClassBehavior because the class behavior was installed before the object was instanced + $this->assertNotNull($nolistencomponent->asa('FooClassBehavior'), "nolistencomponent is does not have the FooClassBehavior"); + + //Clear out what was done during this test + $anothercomponent->unlisten(); + $this->component->detachClassBehavior('FooClassBehavior'); + $this->component->detachClassBehavior('BarClassBehavior'); + + // Test attaching of single object behaviors as class-wide behaviors + $this->component->attachClassBehavior('BarBehaviorObject', 'BarBehavior'); + $this->assertTrue($this->component->asa('BarBehaviorObject') instanceof BarBehavior); + $this->assertEquals($this->component->BarBehaviorObject->Owner, $this->component); + $this->component->detachClassBehavior('BarBehaviorObject'); + } + + + + + + public function testDetachClassBehavior() { + // ensure that the component is listening + $this->assertEquals(1, $this->component->getEventHandlers('fxDetachClassBehavior')->getCount()); + + $prenolistencomponent = new NewComponentNoListen(); + + //Attach a class behavior + $this->component->attachClassBehavior('FooClassBehavior', new FooClassBehavior); + + //Create new components that listen and don't listen to global events + $anothercomponent = new NewComponent(); + $postnolistencomponent = new NewComponentNoListen(); + + //ensures that all the Components are properly initialized + $this->assertEquals(2, $this->component->getEventHandlers('fxDetachClassBehavior')->getCount()); + $this->assertNotNull($this->component->asa('FooClassBehavior'), "Component does not have the FooClassBehavior and should have this behavior"); + $this->assertNull($prenolistencomponent->asa('FooClassBehavior'), "Component has the FooClassBehavior and should _not_ have this behavior"); + $this->assertNotNull($anothercomponent->asa('FooClassBehavior'), "Component does not have the FooClassBehavior and should have this behavior"); + $this->assertNotNull($postnolistencomponent->asa('FooClassBehavior'), "Component does not have the FooClassBehavior and should have this behavior"); + + + $this->component->detachClassBehavior('FooClassBehavior'); + + $this->assertNull($this->component->asa('FooClassBehavior'), "Component has the FooClassBehavior and should _not_ have this behavior"); + $this->assertNull($prenolistencomponent->asa('FooClassBehavior'), "Component has the FooClassBehavior and should _not_ have this behavior"); + $this->assertNull($anothercomponent->asa('FooClassBehavior'), "Component has the FooClassBehavior and should _not_ have this behavior"); + $this->assertNotNull($postnolistencomponent->asa('FooClassBehavior'), "Component does not have the FooClassBehavior and should have this behavior"); + + + //tear down function variables + $anothercomponent->unlisten(); + } + + public function testGetClassHierarchy() { + $component = new DynamicCatchingComponent; + $this->assertEquals(array('TComponent', 'NewComponent', 'NewComponentNoListen', 'DynamicCatchingComponent'), $component->getClassHierarchy()); + $this->assertEquals(array('TComponent', 'NewComponent', 'NewComponentNoListen', 'DynamicCatchingComponent'), $component->getClassHierarchy(false)); + $this->assertEquals(array('tcomponent', 'newcomponent', 'newcomponentnolisten', 'dynamiccatchingcomponent'), $component->getClassHierarchy(true)); + } + + + public function testAsA() { + $anothercomponent = new NewComponent(); + + // ensure the component does not have the FooClassBehavior + $this->assertNull($this->component->asa('FooClassBehavior')); + $this->assertNull($this->component->asa('FooFooClassBehavior')); + $this->assertNull($this->component->asa('BarClassBehavior')); + $this->assertNull($this->component->asa('NonExistantClassBehavior')); + + $this->assertNull($anothercomponent->asa('FooClassBehavior')); + $this->assertNull($anothercomponent->asa('FooFooClassBehavior')); + $this->assertNull($anothercomponent->asa('BarClassBehavior')); + $this->assertNull($anothercomponent->asa('NonExistantClassBehavior')); + + // add the class behavior + $this->component->attachClassBehavior('FooClassBehavior', new FooClassBehavior); + + //Check that the component has only the class behavior assigned + $this->assertNotNull($this->component->asa('FooClassBehavior')); + $this->assertNull($this->component->asa('FooFooClassBehavior')); + $this->assertNull($this->component->asa('BarClassBehavior')); + $this->assertNull($this->component->asa('NonExistantClassBehavior')); + + //Check that the component has only the class behavior assigned + $this->assertNotNull($anothercomponent->asa('FooClassBehavior')); + $this->assertNull($anothercomponent->asa('FooFooClassBehavior')); + $this->assertNull($anothercomponent->asa('BarClassBehavior')); + $this->assertNull($anothercomponent->asa('NonExistantClassBehavior')); + + // remove the class behavior + $this->component->detachClassBehavior('FooClassBehavior'); + + // Check the function doesn't have the behavior any more + $this->assertNull($this->component->asa('FooClassBehavior')); + $this->assertNull($this->component->asa('FooFooClassBehavior')); + $this->assertNull($this->component->asa('BarClassBehavior')); + $this->assertNull($this->component->asa('NonExistantClassBehavior')); + + $this->assertNull($anothercomponent->asa('FooClassBehavior')); + $this->assertNull($anothercomponent->asa('FooFooClassBehavior')); + $this->assertNull($anothercomponent->asa('BarClassBehavior')); + $this->assertNull($anothercomponent->asa('NonExistantClassBehavior')); + + + + + $this->component->attachBehavior('BarBehavior', new BarBehavior); + + //Check that the component has only the object behavior assigned + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertNull($this->component->asa('FooFooBehavior')); + $this->assertNotNull($this->component->asa('BarBehavior')); + $this->assertNull($this->component->asa('NonExistantBehavior')); + + //Check that the component has the behavior assigned + $this->assertNull($anothercomponent->asa('FooBehavior')); + $this->assertNull($anothercomponent->asa('FooFooBehavior')); + $this->assertNull($anothercomponent->asa('BarBehavior')); + $this->assertNull($anothercomponent->asa('NonExistantBehavior')); + + $this->component->detachBehavior('BarBehavior'); + + //Check that the component has no object behaviors assigned + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertNull($this->component->asa('FooFooBehavior')); + $this->assertNull($this->component->asa('BarBehavior')); + $this->assertNull($this->component->asa('NonExistantBehavior')); + + //Check that the component has no behavior assigned + $this->assertNull($anothercomponent->asa('FooBehavior')); + $this->assertNull($anothercomponent->asa('FooFooBehavior')); + $this->assertNull($anothercomponent->asa('BarBehavior')); + $this->assertNull($anothercomponent->asa('NonExistantBehavior')); + + $anothercomponent->unlisten(); + } + + public function testIsA() { + //This doesn't check the IInstanceCheck functionality, separate function + + $this->assertTrue($this->component->isa('TComponent')); + $this->assertTrue($this->component->isa('NewComponent')); + $this->assertFalse($this->component->isa(new FooBehavior)); + $this->assertFalse($this->component->isa('FooBehavior')); + + //Ensure there is no BarBehavior + $this->assertNull($this->component->asa('FooFooBehavior')); + + $this->assertFalse($this->component->isa('FooBehavior')); + $this->assertFalse($this->component->isa('FooFooBehavior')); + + $this->component->attachBehavior('FooFooBehavior', new FooFooBehavior); + + $this->assertNotNull($this->component->asa('FooFooBehavior')); + + $this->assertTrue($this->component->isa('FooBehavior')); + $this->assertTrue($this->component->isa('FooFooBehavior')); + + $this->component->disableBehaviors(); + // It still has the behavior + $this->assertNotNull($this->component->asa('FooFooBehavior')); + + // But it is not expressed + $this->assertFalse($this->component->isa('FooBehavior')); + $this->assertFalse($this->component->isa('FooFooBehavior')); + + $this->component->enableBehaviors(); + $this->assertNotNull($this->component->asa('FooFooBehavior')); + + $this->assertTrue($this->component->isa('FooFooBehavior')); + + + + $this->component->attachBehavior('FooBarBehavior', new FooBarBehavior); + + $this->assertTrue($this->component->isa('FooBehavior')); + $this->assertTrue($this->component->isa('FooBarBehavior')); + + $this->component->disableBehavior('FooBarBehavior'); + + $this->assertTrue($this->component->isa('FooBehavior')); + $this->assertFalse($this->component->isa('FooBarBehavior')); + + $this->component->enableBehavior('FooBarBehavior'); + $this->component->disableBehavior('FooFooBehavior'); + $this->assertFalse($this->component->isa('FooBehavior')); + $this->assertFalse($this->component->isa('FooFooBehavior')); + $this->assertTrue($this->component->isa('FooBarBehavior')); + + $this->component->disableBehavior('FooBarBehavior'); + $this->component->disableBehavior('FooFooBehavior'); + + $this->assertFalse($this->component->isa('FooBehavior')); + $this->assertFalse($this->component->isa('FooFooBehavior')); + $this->assertFalse($this->component->isa('FooBarBehavior')); + + $this->component->enableBehavior('FooBarBehavior'); + $this->component->enableBehavior('FooFooBehavior'); + + $this->assertTrue($this->component->isa('FooFooBehavior')); + $this->assertTrue($this->component->isa('FooBarBehavior')); + + + $this->component->detachBehavior('FooFooBehavior'); + $this->component->detachBehavior('FooBarBehavior'); + + $this->assertFalse($this->component->isa(new FooBehavior)); + $this->assertFalse($this->component->isa('FooBehavior')); + $this->assertFalse($this->component->isa(new FooFooBehavior)); + $this->assertFalse($this->component->isa('FooFooBehavior')); + $this->assertFalse($this->component->isa(new FooBarBehavior)); + $this->assertFalse($this->component->isa('FooBarBehavior')); + + } + + public function testIsA_with_IInstanceCheck() { + + $this->assertTrue($this->component->isa('NewComponent')); + $this->assertFalse($this->component->isa('PreBarBehavior')); + + $this->component->attachBehavior('BarBehavior', $behavior = new BarBehavior); + + $behavior->setInstanceReturn(null); + + $this->assertTrue($this->component->isa('NewComponent')); + $this->assertTrue($this->component->isa('PreBarBehavior')); + $this->assertFalse($this->component->isa('FooBehavior')); + + // This forces the iso on the BarBehavior to respond to any class with false + $behavior->setInstanceReturn(false); + $this->assertFalse($this->component->isa('PreBarBehavior')); + $this->assertFalse($this->component->isa('FooBehavior')); + + //This forces the isa on the BarBehavior to respond to any class with true + $behavior->setInstanceReturn(true); + $this->assertTrue($this->component->isa('FooBehavior')); + + + } + + public function testAttachDetachBehavior() { + + try { + $this->component->faaEverMore(true, true); + $this->fail('TApplicationException not raised trying to execute a undefined class method'); + } catch(TApplicationException $e) {} + + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertFalse($this->component->isa('FooBehavior')); + $this->assertNull($this->component->asa('BarBehavior')); + $this->assertFalse($this->component->isa('BarBehavior')); + + try { + $this->component->attachBehavior('FooBehavior', new TComponent); + $this->fail('TApplicationException not raised trying to execute a undefined class method'); + } catch(TInvalidDataTypeException $e) {} + + $this->component->attachBehavior('FooBehavior', new FooBehavior); + + $this->assertNotNull($this->component->asa('FooBehavior')); + $this->assertTrue($this->component->isa('FooBehavior')); + $this->assertNull($this->component->asa('BarBehavior')); + $this->assertFalse($this->component->isa('BarBehavior')); + + try { + $this->assertTrue($this->component->faaEverMore(true, true)); + } catch(TApplicationException $e) { + $this->fail('TApplicationException raised while trying to execute a behavior class method'); + } + + try { + $this->component->noMethodHere(true); + $this->fail('TApplicationException not raised trying to execute a undefined class method'); + } catch(TApplicationException $e) {} + + $this->assertTrue($this->component->disableBehavior('FooBehavior')); + + //BarBehavior is not a behavior at this time + $this->assertNull($this->component->disableBehavior('BarBehavior')); + + try { + $this->component->faaEverMore(true, true); + $this->fail('TApplicationException not raised trying to execute a undefined class method'); + } catch(TApplicationException $e) {} + + $this->assertTrue($this->component->enableBehavior('FooBehavior')); + + //BarBehavior is not a behavior at this time + $this->assertNull($this->component->enableBehavior('BarBehavior')); + + try { + $this->assertTrue($this->component->faaEverMore(true, true)); + } catch(TApplicationException $e) { + $this->fail('TApplicationException raised while trying to execute a behavior class method'); + } + + $this->component->detachBehavior('FooBehavior'); + + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertFalse($this->component->isa('FooBehavior')); + $this->assertNull($this->component->asa('BarBehavior')); + $this->assertFalse($this->component->isa('BarBehavior')); + + } + + public function testAttachDetachBehaviors() { + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertNull($this->component->asa('BarBehavior')); + $this->assertNull($this->component->asa('FooBarBehavior')); + $this->assertNull($this->component->asa('PreBarBehavior')); + + $this->component->attachBehaviors(array('FooFooBehavior' => new FooFooBehavior, 'BarBehavior' => new BarBehavior, 'PreBarBehavior' => new PreBarBehavior)); + + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertNotNull($this->component->asa('FooFooBehavior')); + $this->assertNotNull($this->component->asa('BarBehavior')); + $this->assertNull($this->component->asa('FooBarBehavior')); + $this->assertNotNull($this->component->asa('PreBarBehavior')); + + $this->assertTrue($this->component->isa('FooFooBehavior')); + $this->assertTrue($this->component->isa('FooBehavior')); + $this->assertTrue($this->component->isa('BarBehavior')); + $this->assertTrue($this->component->isa('PreBarBehavior')); + $this->assertFalse($this->component->isa('FooBarBehavior')); + + $this->component->detachBehaviors(array('FooFooBehavior' => new FooFooBehavior, 'BarBehavior' => new BarBehavior)); + + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertNull($this->component->asa('FooFooBehavior')); + $this->assertNull($this->component->asa('BarBehavior')); + $this->assertNull($this->component->asa('FooBarBehavior')); + $this->assertNotNull($this->component->asa('PreBarBehavior')); + + $this->assertFalse($this->component->isa('FooFooBehavior')); + $this->assertFalse($this->component->isa('FooBehavior')); + $this->assertFalse($this->component->isa('BarBehavior')); + $this->assertFalse($this->component->isa('FooBarBehavior')); + $this->assertTrue($this->component->isa('PreBarBehavior')); + + + + // testing if we can detachBehaviors just by the name of the behavior instead of an array of the behavior + $this->component->attachBehaviors(array('FooFooBehavior' => new FooFooBehavior, 'BarBehavior' => new BarBehavior)); + + $this->assertTrue($this->component->isa('FooBehavior')); + $this->assertTrue($this->component->isa('BarBehavior')); + + $this->component->detachBehaviors(array('FooFooBehavior', 'BarBehavior')); + + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertNull($this->component->asa('FooFooBehavior')); + $this->assertNull($this->component->asa('BarBehavior')); + $this->assertNull($this->component->asa('FooBarBehavior')); + + $this->assertFalse($this->component->isa('FooFooBehavior')); + $this->assertFalse($this->component->isa('FooBehavior')); + $this->assertFalse($this->component->isa('BarBehavior')); + $this->assertFalse($this->component->isa('FooBarBehavior')); + } + + + public function testClearBehaviors() { + + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertNull($this->component->asa('BarBehavior')); + $this->assertNull($this->component->asa('FooBarBehavior')); + $this->assertNull($this->component->asa('PreBarBehavior')); + + $this->component->attachBehaviors(array('FooFooBehavior' => new FooFooBehavior, 'BarBehavior' => new BarBehavior, 'PreBarBehavior' => new PreBarBehavior)); + + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertNotNull($this->component->asa('FooFooBehavior')); + $this->assertNotNull($this->component->asa('BarBehavior')); + $this->assertNull($this->component->asa('FooBarBehavior')); + $this->assertNotNull($this->component->asa('PreBarBehavior')); + + $this->component->clearBehaviors(); + + $this->assertNull($this->component->asa('FooBehavior')); + $this->assertNull($this->component->asa('BarBehavior')); + $this->assertNull($this->component->asa('FooBarBehavior')); + $this->assertNull($this->component->asa('PreBarBehavior')); + } + + public function testEnableDisableBehavior() { + + $this->assertNull($this->component->enableBehavior('FooBehavior')); + $this->assertNull($this->component->disableBehavior('FooBehavior')); + + try { + $this->component->faaEverMore(true, true); + $this->fail('TApplicationException not raised trying to execute a undefined class method'); + } catch(TApplicationException $e) {} + + $this->component->attachBehavior('FooBehavior', new FooBehavior); + + $this->assertTrue($this->component->isa('FooBehavior')); + try { + $this->assertTrue($this->component->faaEverMore(true, true)); + } catch(TApplicationException $e) { + $this->fail('TApplicationException raised while trying to execute a behavior class method'); + } + + $this->assertTrue($this->component->disableBehavior('FooBehavior')); + + $this->assertFalse($this->component->isa('FooBehavior')); + + try { + $this->component->faaEverMore(true, true); + $this->fail('TApplicationException not raised trying to execute a undefined class method'); + } catch(TApplicationException $e) {} + + $this->assertTrue($this->component->enableBehavior('FooBehavior')); + + $this->assertTrue($this->component->isa('FooBehavior')); + try { + $this->assertTrue($this->component->faaEverMore(true, true)); + } catch(TApplicationException $e) { + $this->fail('TApplicationException raised while trying to execute a behavior class method'); + } + + + + $this->assertNull($this->component->enableBehavior('BarClassBehavior')); + $this->assertNull($this->component->disableBehavior('BarClassBehavior')); + + try { + $this->component->moreFunction(true, true); + $this->fail('TApplicationException not raised trying to execute an undefined class method'); + } catch(TApplicationException $e) {} + + $this->component->attachClassBehavior('BarClassBehavior', new BarClassBehavior); + + $this->assertFalse($this->component->enableBehavior('BarClassBehavior')); + $this->assertFalse($this->component->disableBehavior('BarClassBehavior')); + + try { + $this->assertTrue($this->component->moreFunction(true, true)); + } catch(TApplicationException $e) { + $this->fail('TApplicationException raised while trying to execute a behavior class method'); + } + + $this->component->detachClassBehavior('BarClassBehavior'); + } + + + public function testBehaviorFunctionCalls() { + + $this->component->attachBehavior('FooBarBehavior', $behavior = new FooBarBehavior); + $this->component->attachClassBehavior('FooClassBehavior', $classbehavior = new FooClassBehavior); + + // Test the Class Methods + $this->assertEquals(12, $this->component->faaEverMore(3, 4)); + + // Check that the called object is shifted in front of the array of a class behavior call + $this->assertEquals($this->component, $this->component->getLastClassObject()); + + + //Test the FooBarBehavior + $this->assertEquals(27, $this->component->moreFunction(3, 3)); + + $this->assertTrue($this->component->disableBehavior('FooBarBehavior')); + try { + $this->assertNull($this->component->moreFunction(3, 4)); + $this->fail('TApplicationException not raised trying to execute a disabled behavior'); + } catch(TApplicationException $e) {} + $this->assertTrue($this->component->enableBehavior('FooBarBehavior')); + + // Test the global event space, this should work and return false because no function implements these methods + $this->assertNull($this->component->fxSomeUndefinedGlobalEvent()); + $this->assertNull($this->component->dySomeUndefinedIntraObjectEvent()); + + $this->component->detachClassBehavior('FooClassBehavior'); + + + + // test object instance behaviors implemented through class-wide behaviors + $this->component->attachClassBehavior('FooFooBehaviorAsClass', 'FooFooBehavior'); + + $component = new NewComponent; + + $this->assertEquals(5, $this->component->faafaaEverMore(3, 4)); + $this->assertEquals(10, $component->faafaaEverMore(6, 8)); + + $this->component->detachClassBehavior('FooFooBehaviorAsClass'); + $component->unlisten(); + $component = null; + + try { + $this->component->faafaaEverMore(3, 4); + $this->fail('TApplicationException not raised trying to execute a disabled behavior'); + } catch(TApplicationException $e) {} + + + + // make a call to an unpatched fx and dy call so that it's passed through to the __dycall function + $dynamicComponent = new DynamicCallComponent; + + $this->assertNull($dynamicComponent->fxUndefinedEvent()); + $this->assertNull($dynamicComponent->dyUndefinedEvent()); + + //This tests the dynamic __dycall function + $this->assertEquals(1024, $dynamicComponent->dyPowerFunction(2, 10)); + $this->assertEquals(5, $dynamicComponent->dyDivisionFunction(10, 2)); + + $this->assertEquals(2048, $dynamicComponent->fxPowerFunction(2, 10)); + $this->assertEquals(10, $dynamicComponent->fxDivisionFunction(10, 2)); + + $dynamicComponent->unlisten(); + + } + public function testHasProperty() { $this->assertTrue($this->component->hasProperty('Text'), "Component hasn't property Text"); $this->assertTrue($this->component->hasProperty('text'), "Component hasn't property text"); - $this->assertFalse($this->component->hasProperty('Caption'), "Component as property Caption"); + $this->assertFalse($this->component->hasProperty('Caption'), "Component has property Caption"); + + $this->assertTrue($this->component->hasProperty('ColorAttribute'), "Component hasn't property JsColorAttribute"); + $this->assertTrue($this->component->hasProperty('colorattribute'), "Component hasn't property JsColorAttribute"); + $this->assertFalse($this->component->canGetProperty('PastelAttribute'), "Component has property JsPastelAttribute"); + + $this->assertTrue($this->component->hasProperty('JSColorAttribute'), "Component hasn't property JsColorAttribute"); + $this->assertTrue($this->component->hasProperty('jscolorattribute'), "Component hasn't property JsColorAttribute"); + $this->assertFalse($this->component->hasProperty('jsPastelAttribute'), "Component has property JsPastelAttribute"); + + $this->assertFalse($this->component->hasProperty('Excitement'), "Component has property Excitement"); + $this->component->attachBehavior('ExcitementPropBehavior', new BehaviorTestBehavior); + $this->assertTrue($this->component->hasProperty('Excitement'), "Component hasn't property Excitement"); + $this->component->disableBehaviors(); + $this->assertFalse($this->component->hasProperty('Excitement'), "Component has property Excitement"); + $this->component->enableBehaviors(); + $this->assertTrue($this->component->hasProperty('Excitement'), "Component hasn't property Excitement"); + $this->component->disableBehavior('ExcitementPropBehavior'); + $this->assertFalse($this->component->hasProperty('Excitement'), "Component has property Excitement"); + $this->component->enableBehavior('ExcitementPropBehavior'); + $this->assertTrue($this->component->hasProperty('Excitement'), "Component hasn't property Excitement"); + + $this->component->detachBehavior('ExcitementPropBehavior'); + + $this->assertFalse($this->component->hasProperty('Excitement'), "Component has property Excitement"); + } public function testCanGetProperty() { $this->assertTrue($this->component->canGetProperty('Text')); $this->assertTrue($this->component->canGetProperty('text')); $this->assertFalse($this->component->canGetProperty('Caption')); + + $this->assertTrue($this->component->canGetProperty('ColorAttribute')); + $this->assertTrue($this->component->canGetProperty('colorattribute')); + $this->assertFalse($this->component->canGetProperty('PastelAttribute')); + + $this->assertTrue($this->component->canGetProperty('JSColorAttribute')); + $this->assertTrue($this->component->canGetProperty('jscolorattribute')); + $this->assertFalse($this->component->canGetProperty('jsPastelAttribute')); + + + $this->assertFalse($this->component->canGetProperty('Excitement'), "Component has property Excitement"); + $this->component->attachBehavior('ExcitementPropBehavior', new BehaviorTestBehavior); + $this->assertTrue($this->component->canGetProperty('Excitement'), "Component hasn't property Excitement"); + $this->component->disableBehaviors(); + $this->assertFalse($this->component->canGetProperty('Excitement'), "Component has property Excitement"); + $this->component->enableBehaviors(); + $this->assertTrue($this->component->canGetProperty('Excitement'), "Component hasn't property Excitement"); + $this->component->disableBehavior('ExcitementPropBehavior'); + $this->assertFalse($this->component->canGetProperty('Excitement'), "Component has property Excitement"); + $this->component->enableBehavior('ExcitementPropBehavior'); + $this->assertTrue($this->component->canGetProperty('Excitement'), "Component hasn't property Excitement"); + + $this->component->detachBehavior('ExcitementPropBehavior'); + + $this->assertFalse($this->component->canGetProperty('Excitement'), "Component has property Excitement"); } public function testCanSetProperty() { $this->assertTrue($this->component->canSetProperty('Text')); $this->assertTrue($this->component->canSetProperty('text')); $this->assertFalse($this->component->canSetProperty('Caption')); + + $this->assertTrue($this->component->canSetProperty('ColorAttribute')); + $this->assertTrue($this->component->canSetProperty('colorattribute')); + $this->assertFalse($this->component->canSetProperty('PastelAttribute')); + + $this->assertTrue($this->component->canSetProperty('JSColorAttribute')); + $this->assertTrue($this->component->canSetProperty('jscolorattribute')); + $this->assertFalse($this->component->canSetProperty('jsPastelAttribute')); + + $this->assertFalse($this->component->canSetProperty('Excitement'), "Component has property Excitement"); + $this->component->attachBehavior('ExcitementPropBehavior', new BehaviorTestBehavior); + $this->assertTrue($this->component->canSetProperty('Excitement'), "Component hasn't property Excitement"); + $this->component->disableBehaviors(); + $this->assertFalse($this->component->canSetProperty('Excitement'), "Component has property Excitement"); + $this->component->enableBehaviors(); + $this->assertTrue($this->component->canSetProperty('Excitement'), "Component hasn't property Excitement"); + $this->component->disableBehavior('ExcitementPropBehavior'); + $this->assertFalse($this->component->canSetProperty('Excitement'), "Component has property Excitement"); + $this->component->enableBehavior('ExcitementPropBehavior'); + $this->assertTrue($this->component->canSetProperty('Excitement'), "Component hasn't property Excitement"); + + $this->component->detachBehavior('ExcitementPropBehavior'); } public function testGetProperty() { @@ -74,6 +1180,67 @@ class TComponentTest extends PHPUnit_Framework_TestCase { $this->fail('exception not raised when getting undefined property'); } catch(TInvalidOperationException $e) { } + + $this->assertTrue($this->component->OnMyEvent instanceof TPriorityList); + try { + $value2=$this->component->onUndefinedEvent; + $this->fail('exception not raised when getting undefined property'); + } catch(TInvalidOperationException $e) { + } + + //Without the function parenthesis, the function is _not_ called but the __get + // method is called and the global events (list) are accessed + $this->assertTrue($this->component->fxAttachClassBehavior instanceof TPriorityList); + $this->assertTrue($this->component->fxDetachClassBehavior instanceof TPriorityList); + + // even undefined global events have a list as every object is able to access every event + $this->assertTrue($this->component->fxUndefinedEvent instanceof TPriorityList); + + + // Test the behaviors within the __get function + $this->component->enableBehaviors(); + + try { + $value2=$this->component->Excitement; + $this->fail('exception not raised when getting undefined property'); + } catch(TInvalidOperationException $e) { + } + + $this->component->attachBehavior('BehaviorTestBehavior', $behavior = new BehaviorTestBehavior); + $this->assertEquals('faa', $this->component->Excitement); + + $this->component->disableBehaviors(); + + try { + $this->assertEquals('faa', $this->component->Excitement); + $this->fail('exception not raised when getting undefined property'); + } catch(TInvalidOperationException $e) { + } + + $this->component->enableBehaviors(); + $this->assertEquals('faa', $this->component->getExcitement()); + + $this->component->disableBehavior('BehaviorTestBehavior'); + + $this->assertEquals($behavior, $this->component->BehaviorTestBehavior); + try { + $behavior = $this->component->BehaviorTestBehavior2; + $this->fail('exception not raised when getting undefined property'); + } catch(TInvalidOperationException $e) { + } + + try { + $this->assertEquals('faa', $this->component->Excitement); + $this->fail('exception not raised when getting undefined property'); + } catch(TInvalidOperationException $e) { + } + $this->component->enableBehavior('BehaviorTestBehavior'); + $this->assertEquals('faa', $this->component->getExcitement()); + + + // behaviors allow on and fx events to be passed through. + $this->assertTrue($this->component->onBehaviorEvent instanceof TPriorityList); + } public function testSetProperty() { @@ -86,6 +1253,203 @@ class TComponentTest extends PHPUnit_Framework_TestCase { $this->fail('exception not raised when setting undefined property'); } catch(TInvalidOperationException $e) { } + + // Test get only properties is a set function + try { + $this->component->ReadOnlyProperty = 'setting read only'; + $this->fail('a property without a set function was set to a new value without error'); + } catch(TInvalidOperationException $e) { + } + + try { + $this->component->ReadOnlyJsProperty = 'jssetting read only'; + $this->fail('a js property without a set function was set to a new value without error'); + } catch(TInvalidOperationException $e) { + } + + try { + $this->component->JsReadOnlyJsProperty = 'jssetting read only'; + $this->fail('a js property without a set function was set to a new value without error'); + } catch(TInvalidOperationException $e) { + } + + $this->assertEquals(0, $this->component->getEventHandlers('onMyEvent')->getCount()); + $this->component->onMyEvent = array($this->component,'myEventHandler'); + $this->assertEquals(1, $this->component->getEventHandlers('onMyEvent')->getCount()); + $this->component->onMyEvent[] = array($this->component,'Object.myEventHandler'); + $this->assertEquals(2, $this->component->getEventHandlers('onMyEvent')->getCount()); + + $this->component->getEventHandlers('onMyEvent')->clear(); + + // Test the behaviors within the __get function + $this->component->enableBehaviors(); + + try { + $this->component->Excitement = 'laa'; + $this->fail('exception not raised when getting undefined property'); + } catch(TInvalidOperationException $e) { + } + + $this->component->attachBehavior('BehaviorTestBehavior', $behavior1 = new BehaviorTestBehavior); + $this->component->Excitement = 'laa'; + $this->assertEquals('laa', $this->component->Excitement); + $this->assertEquals('sol', $this->component->Excitement = 'sol'); + + + $this->component->disableBehaviors(); + + try { + $this->component->Excitement = false; + $this->assertEquals(false, $this->component->Excitement); + $this->fail('exception not raised when getting undefined property'); + } catch(TInvalidOperationException $e) { + } + + $this->component->enableBehaviors(); + $this->component->Excitement = 'faa'; + $this->assertEquals('faa', $this->component->getExcitement()); + + $this->component->disableBehavior('BehaviorTestBehavior'); + + try { + $this->component->Excitement = false; + $this->assertEquals(false, $this->component->Excitement); + $this->fail('exception not raised when getting undefined property'); + } catch(TInvalidOperationException $e) { + } + $this->component->enableBehavior('BehaviorTestBehavior'); + $this->component->Excitement = 'sol'; + $this->assertEquals('sol', $this->component->Excitement); + + + $this->component->attachBehavior('BehaviorTestBehavior2', $behavior2 = new BehaviorTestBehavior); + + $this->assertEquals('sol', $this->component->Excitement); + $this->assertEquals('faa', $behavior2->Excitement); + + // this sets Excitement for both because they are not uniquely named + $this->component->Excitement = 'befaad'; + + $this->assertEquals('befaad', $this->component->Excitement); + $this->assertEquals('befaad', $behavior1->Excitement); + $this->assertEquals('befaad', $behavior2->Excitement); + + + $this->component->detachBehavior('BehaviorTestBehavior2'); + + // behaviors allow on and fx events to be passed through. + $this->assertTrue($this->component->BehaviorTestBehavior->onBehaviorEvent instanceof TPriorityList); + + $this->assertEquals(0, $this->component->BehaviorTestBehavior->getEventHandlers('onBehaviorEvent')->getCount()); + $this->component->onBehaviorEvent = array($this->component,'myEventHandler'); + $this->assertEquals(1, $this->component->BehaviorTestBehavior->getEventHandlers('onBehaviorEvent')->getCount()); + $this->component->onBehaviorEvent[] = array($this->component,'Object.myEventHandler'); + $this->assertEquals(2, $this->component->BehaviorTestBehavior->getEventHandlers('onBehaviorEvent')->getCount()); + + $this->component->BehaviorTestBehavior->getEventHandlers('onBehaviorEvent')->clear(); + } + + + public function testIsSetFunction() { + $this->assertTrue(isset($this->component->fxAttachClassBehavior)); + $this->component->unlisten(); + + $this->assertFalse(isset($this->component->onMyEvent)); + $this->assertFalse(isset($this->component->undefinedEvent)); + $this->assertFalse(isset($this->component->fxAttachClassBehavior)); + + $this->assertFalse(isset($this->component->BehaviorTestBehavior)); + $this->assertFalse(isset($this->component->onBehaviorEvent)); + + $this->component->attachBehavior('BehaviorTestBehavior', new BehaviorTestBehavior); + + $this->assertTrue(isset($this->component->BehaviorTestBehavior)); + $this->assertFalse(isset($this->component->onBehaviorEvent)); + + $this->component->attachEventHandler('onBehaviorEvent','foo'); + $this->assertTrue(isset($this->component->onBehaviorEvent)); + + $this->component->attachEventHandler('onMyEvent','foo'); + $this->assertTrue(isset($this->component->onMyEvent)); + + $this->assertTrue(isset($this->component->Excitement)); + $this->component->Excitement = null; + $this->assertFalse(isset($this->component->Excitement)); + $this->assertFalse(isset($this->component->UndefinedBehaviorProperty)); + + + } + + + public function testUnsetFunction() { + + $this->assertEquals('default', $this->component->getText()); + unset($this->component->Text); + $this->assertNull($this->component->getText()); + + unset($this->component->UndefinedProperty); + + // object events + $this->assertEquals(0, $this->component->onMyEvent->Count); + $this->component->attachEventHandler('onMyEvent','foo'); + $this->assertEquals(1, $this->component->onMyEvent->Count); + unset($this->component->onMyEvent); + $this->assertEquals(0, $this->component->onMyEvent->Count); + + //global events + $this->assertEquals(1, $this->component->fxAttachClassBehavior->Count); + $component = new NewComponent(); + $this->assertEquals(2, $this->component->fxAttachClassBehavior->Count); + unset($this->component->fxAttachClassBehavior); + // retain the other object event + $this->assertEquals(1, $this->component->fxAttachClassBehavior->Count); + $component->unlisten(); + + try { + unset($this->component->Object); + $this->fail('TInvalidOperationException not raised when unsetting get only property'); + } catch(TInvalidOperationException $e) {} + + $this->component->attachBehavior('BehaviorTestBehavior', new BehaviorTestBehavior); + $this->assertTrue($this->component->asa('BehaviorTestBehavior') instanceof BehaviorTestBehavior); + $this->assertFalse($this->component->asa('BehaviorTestBehavior2') instanceof BehaviorTestBehavior); + + $this->assertEquals('faa', $this->component->Excitement); + unset($this->component->Excitement); + $this->assertNull($this->component->Excitement); + $this->component->Excitement = 'sol'; + $this->assertEquals('sol', $this->component->Excitement); + + // Test the disabling of unset within behaviors + $this->component->disableBehaviors(); + unset($this->component->Excitement); + $this->component->enableBehaviors(); + // This should still be 'sol' because the unset happened inside behaviors being disabled + $this->assertEquals('sol', $this->component->Excitement); + $this->component->disableBehavior('BehaviorTestBehavior'); + unset($this->component->Excitement); + $this->component->enableBehavior('BehaviorTestBehavior'); + $this->assertEquals('sol', $this->component->Excitement); + + unset($this->component->Excitement); + $this->assertNull($this->component->Excitement); + + try { + unset($this->component->ReadOnly); + $this->fail('TInvalidOperationException not raised when unsetting get only property'); + } catch(TInvalidOperationException $e) {} + + $this->component->onBehaviorEvent = 'foo'; + $this->assertEquals(1, count($this->component->onBehaviorEvent)); + $this->assertEquals(1, count($this->component->BehaviorTestBehavior->onBehaviorEvent)); + unset($this->component->onBehaviorEvent); + $this->assertEquals(0, count($this->component->onBehaviorEvent)); + $this->assertEquals(0, count($this->component->BehaviorTestBehavior->onBehaviorEvent)); + + // Remove behavior via unset + unset($this->component->BehaviorTestBehavior); + $this->assertFalse($this->component->asa('BehaviorTestBehavior') instanceof BehaviorTestBehavior); + } public function testGetSubProperty() { @@ -101,46 +1465,225 @@ class TComponentTest extends PHPUnit_Framework_TestCase { $this->assertTrue($this->component->hasEvent('OnMyEvent')); $this->assertTrue($this->component->hasEvent('onmyevent')); $this->assertFalse($this->component->hasEvent('onYourEvent')); + + // fx won't throw an error if any of these fx function are called on an object. + // It is a special prefix event designation that every object responds to all events. + $this->assertTrue($this->component->hasEvent('fxAttachClassBehavior')); + $this->assertTrue($this->component->hasEvent('fxattachclassbehavior')); + + $this->assertTrue($this->component->hasEvent('fxNonExistantGlobalEvent')); + $this->assertTrue($this->component->hasEvent('fxnonexistantglobalevent')); + + $this->assertTrue($this->component->hasEvent('dyNonExistantLocalEvent')); + $this->assertTrue($this->component->hasEvent('fxnonexistantlocalevent')); + + + //Test behavior events + $this->assertFalse($this->component->hasEvent('onBehaviorEvent')); + $this->component->attachBehavior('BehaviorTestBehavior', new BehaviorTestBehavior); + $this->assertTrue($this->component->hasEvent('onBehaviorEvent')); + $this->assertTrue($this->component->BehaviorTestBehavior->hasEvent('onBehaviorEvent')); + + $this->component->disableBehavior('BehaviorTestBehavior'); + $this->assertFalse($this->component->hasEvent('onBehaviorEvent')); + $this->component->enableBehavior('BehaviorTestBehavior'); + $this->assertTrue($this->component->hasEvent('onBehaviorEvent')); } public function testHasEventHandler() { $this->assertFalse($this->component->hasEventHandler('OnMyEvent')); $this->component->attachEventHandler('OnMyEvent','foo'); $this->assertTrue($this->component->hasEventHandler('OnMyEvent')); + + $this->assertFalse($this->component->hasEventHandler('fxNonExistantGlobalEvent')); + $this->component->attachEventHandler('fxNonExistantGlobalEvent','foo'); + $this->assertTrue($this->component->hasEventHandler('fxNonExistantGlobalEvent')); + + //Test behavior events + $this->assertFalse($this->component->hasEventHandler('onBehaviorEvent')); + $this->component->attachBehavior('BehaviorTestBehavior', new BehaviorTestBehavior); + $this->assertFalse($this->component->hasEventHandler('onBehaviorEvent')); + $this->assertFalse($this->component->BehaviorTestBehavior->hasEventHandler('onBehaviorEvent')); + + $this->component->attachEventHandler('onBehaviorEvent','foo'); + $this->assertTrue($this->component->hasEventHandler('onBehaviorEvent')); + + $this->component->disableBehavior('BehaviorTestBehavior'); + $this->assertFalse($this->component->hasEvent('onBehaviorEvent')); + $this->assertFalse($this->component->hasEventHandler('onBehaviorEvent')); + $this->component->enableBehavior('BehaviorTestBehavior'); + $this->assertTrue($this->component->hasEvent('onBehaviorEvent')); + $this->assertTrue($this->component->hasEventHandler('onBehaviorEvent')); } public function testGetEventHandlers() { $list=$this->component->getEventHandlers('OnMyEvent'); - $this->assertTrue(($list instanceof TList) && ($list->getCount()===0)); + $this->assertTrue(($list instanceof TPriorityList) && ($list->getCount()===0)); $this->component->attachEventHandler('OnMyEvent','foo'); - $this->assertTrue(($list instanceof TList) && ($list->getCount()===1)); + $this->assertTrue(($list instanceof TPriorityList) && ($list->getCount()===1)); try { $list=$this->component->getEventHandlers('YourEvent'); $this->fail('exception not raised when getting event handlers for undefined event'); } catch(TInvalidOperationException $e) { } + + $list=$this->component->getEventHandlers('fxRandomEvent'); + $this->assertTrue(($list instanceof TPriorityList) && ($list->getCount()===0)); + $this->component->attachEventHandler('fxRandomEvent','foo'); + $this->assertTrue(($list instanceof TPriorityList) && ($list->getCount()===1)); + try { + $list=$this->component->getEventHandlers('fxSomeUndefinedGlobalEvent'); + } catch(TInvalidOperationException $e) { + $this->fail('exception raised when getting event handlers for universal global event'); + } + + + + //Test behavior events + try { + $list=$this->component->getEventHandlers('onBehaviorEvent'); + $this->fail('exception not raised when getting event handlers for undefined event'); + } catch(TInvalidOperationException $e) { + } + $this->assertFalse($this->component->hasEventHandler('onBehaviorEvent')); + + $this->component->attachBehavior('BehaviorTestBehavior', new BehaviorTestBehavior); + $list=$this->component->getEventHandlers('onBehaviorEvent'); + $this->assertTrue(($list instanceof TPriorityList) && ($list->getCount()===0)); + $this->component->attachEventHandler('onBehaviorEvent','foo'); + $this->assertTrue(($list instanceof TPriorityList) && ($list->getCount()===1)); + + $this->component->disableBehavior('BehaviorTestBehavior'); + try { + $list=$this->component->getEventHandlers('onBehaviorEvent'); + $this->fail('exception not raised when getting event handlers for undefined event'); + } catch(TInvalidOperationException $e) { + } + $this->component->enableBehavior('BehaviorTestBehavior'); + $this->assertTrue(($this->component->getEventHandlers('onBehaviorEvent') instanceof TPriorityList) && ($list->getCount()===1)); + } public function testAttachEventHandler() { + $this->component->attachEventHandler('OnMyEvent','foo'); - $this->assertTrue($this->component->getEventHandlers('OnMyEvent')->getCount()===1); + $this->assertEquals(1, $this->component->getEventHandlers('OnMyEvent')->getCount()); try { $this->component->attachEventHandler('YourEvent','foo'); $this->fail('exception not raised when attaching event handlers for undefined event'); } catch(TInvalidOperationException $e) { } - /*$this->component->MyEvent[]='foo2'; - $this->assertTrue($this->component->getEventHandlers('MyEvent')->getCount()===2); - $this->component->getEventHandlers('MyEvent')->add('foo3'); - $this->assertTrue($this->component->getEventHandlers('MyEvent')->getCount()===3); - $this->component->MyEvent[0]='foo4'; - $this->assertTrue($this->component->getEventHandlers('MyEvent')->getCount()===3); - $this->component->getEventHandlers('MyEvent')->insert(0,'foo5'); - $this->assertTrue($this->component->MyEvent->Count===4 && $this->component->MyEvent[0]==='foo5'); - $this->component->MyEvent='foo6'; - $this->assertTrue($this->component->MyEvent->Count===5 && $this->component->MyEvent[4]==='foo6');*/ + + //Testing the priorities of attaching events + $this->component->attachEventHandler('OnMyEvent','foopre', 5); + $this->component->attachEventHandler('OnMyEvent','foopost', 15); + $this->component->attachEventHandler('OnMyEvent','foobar', 10); + $this->assertEquals(4, $this->component->getEventHandlers('OnMyEvent')->getCount()); + $list = $this->component->getEventHandlers('OnMyEvent'); + $this->assertEquals('foopre', $list[0]); + $this->assertEquals('foo', $list[1]); + $this->assertEquals('foobar', $list[2]); + $this->assertEquals('foopost', $list[3]); + + + //Test attaching behavior events + try { + $this->component->attachEventHandler('onBehaviorEvent','foo'); + $this->fail('exception not raised when getting event handlers for undefined event'); + } catch(TInvalidOperationException $e) { + } + $this->component->attachBehavior('BehaviorTestBehavior', new BehaviorTestBehavior); + + $this->component->attachEventHandler('onBehaviorEvent','foo'); + + //Testing the priorities of attaching behavior events + $this->component->attachEventHandler('onBehaviorEvent','foopre', 5); + $this->component->attachEventHandler('onBehaviorEvent','foopost', 15); + $this->component->attachEventHandler('onBehaviorEvent','foobar', 10); + $this->component->attachEventHandler('onBehaviorEvent','foobarfoobar', 10); + $this->assertEquals(5, $this->component->getEventHandlers('onBehaviorEvent')->getCount()); + $list = $this->component->getEventHandlers('onBehaviorEvent'); + $this->assertEquals('foopre', $list[0]); + $this->assertEquals('foo', $list[1]); + $this->assertEquals('foobar', $list[2]); + $this->assertEquals('foobarfoobar', $list[3]); + $this->assertEquals('foopost', $list[4]); + + $this->component->disableBehavior('BehaviorTestBehavior'); + try { + $this->component->attachEventHandler('onBehaviorEvent','bar'); + $this->fail('exception not raised when getting event handlers for undefined event'); + } catch(TInvalidOperationException $e) { + } + $this->component->enableBehavior('BehaviorTestBehavior'); + } + public function testDetachEventHandler() { + + $this->component->attachEventHandler('OnMyEvent','foo'); + $this->assertEquals(1, $this->component->getEventHandlers('OnMyEvent')->getCount()); + + $this->component->attachEventHandler('OnMyEvent','foopre', 5); + $this->component->attachEventHandler('OnMyEvent','foopost', 15); + $this->component->attachEventHandler('OnMyEvent','foobar', 10); + $this->component->attachEventHandler('OnMyEvent','foobarfoobar', 10); + + + + $this->component->detachEventHandler('OnMyEvent','foo'); + $list = $this->component->getEventHandlers('OnMyEvent'); + $this->assertEquals(4, $list->getCount()); + + $this->assertEquals('foopre', $list[0]); + $this->assertEquals('foobar', $list[1]); + $this->assertEquals('foobarfoobar', $list[2]); + $this->assertEquals('foopost', $list[3]); + + $this->component->detachEventHandler('OnMyEvent','foopre', null); + $this->assertEquals(4, $list->getCount()); + + $this->component->detachEventHandler('OnMyEvent','foopre', 5); + $this->assertEquals(3, $list->getCount()); + + + // Now do detaching of behavior on events + try { + $this->component->attachEventHandler('onBehaviorEvent','foo'); + $this->fail('exception not raised when getting event handlers for undefined event'); + } catch(TInvalidOperationException $e) { + } + $this->component->attachBehavior('BehaviorTestBehavior', new BehaviorTestBehavior); + + $this->component->attachEventHandler('onBehaviorEvent','foo'); + $this->assertEquals(1, $this->component->getEventHandlers('onBehaviorEvent')->getCount()); + + $this->component->attachEventHandler('onBehaviorEvent','foopre', 5); + $this->component->attachEventHandler('onBehaviorEvent','foopost', 15); + $this->component->attachEventHandler('onBehaviorEvent','foobar', 10); + $this->component->attachEventHandler('onBehaviorEvent','foobarfoobar', 10); + + + + $this->component->detachEventHandler('onBehaviorEvent','foo'); + $list = $this->component->getEventHandlers('onBehaviorEvent'); + $this->assertEquals(4, $list->getCount()); + + $this->assertEquals('foopre', $list[0]); + $this->assertEquals('foobar', $list[1]); + $this->assertEquals('foobarfoobar', $list[2]); + $this->assertEquals('foopost', $list[3]); + + $this->component->detachEventHandler('onBehaviorEvent','foopre', null); + $this->assertEquals(4, $list->getCount()); + + $this->component->detachEventHandler('onBehaviorEvent','foopre', 5); + $this->assertEquals(3, $list->getCount()); + } + + + + public function testRaiseEvent() { $this->component->attachEventHandler('OnMyEvent',array($this->component,'myEventHandler')); $this->assertFalse($this->component->isEventHandled()); @@ -150,7 +1693,210 @@ class TComponentTest extends PHPUnit_Framework_TestCase { $this->assertFalse($this->component->Object->isEventHandled()); $this->component->raiseEvent('OnMyEvent',$this,null); $this->assertTrue($this->component->Object->isEventHandled()); + + $this->component->resetEventHandled(); + $this->component->Object->resetEventHandled(); + + + // Test a behavior on event + $this->component->attachBehavior('test', new BehaviorTestBehavior); + + $this->component->attachEventHandler('onBehaviorEvent',array($this->component,'myEventHandler')); + $this->assertFalse($this->component->isEventHandled()); + $this->component->raiseEvent('onBehaviorEvent',$this,null); + $this->assertTrue($this->component->isEventHandled()); + $this->component->attachEventHandler('onBehaviorEvent',array($this->component,'Object.myEventHandler')); + $this->assertFalse($this->component->Object->isEventHandled()); + $this->component->raiseEvent('onBehaviorEvent',$this,null); + $this->assertTrue($this->component->Object->isEventHandled()); + + //test behavior enabled/disabled events + $this->component->disableBehavior('test'); + + $this->component->resetEventHandled(); + $this->component->Object->resetEventHandled(); + + try { + $this->component->attachEventHandler('onBehaviorEvent',array($this->component,'myEventHandler')); + $this->fail('exception not raised when getting event handlers for undefined event'); + } catch(TInvalidOperationException $e) {} + $this->assertFalse($this->component->isEventHandled()); + try { + $this->component->raiseEvent('onBehaviorEvent',$this,null); + $this->fail('exception not raised when getting event handlers for undefined event'); + } catch(TInvalidOperationException $e) {} + $this->assertFalse($this->component->isEventHandled()); + + $this->component->enableBehavior('test'); + + + + //Test the return types of this function + + $this->assertFalse($this->component->isEventHandled()); + $this->assertFalse($this->component->Object->isEventHandled()); + $this->assertEquals(array(), $this->component->onBehaviorEvent($this,$this->component)); + $this->assertTrue($this->component->isEventHandled()); + $this->assertTrue($this->component->Object->isEventHandled()); + + // This accumulates all the responses from each of the events + $arr=$this->component->onBehaviorEvent($this, $this->component, TEventResults::EVENT_RESULT_ALL); + $this->assertEquals($this, $arr[0]['sender']); + $this->assertEquals($this->component, $arr[0]['param']); + $this->assertTrue(null === $arr[0]['response']); + + $this->assertEquals($this, $arr[1]['sender']); + $this->assertEquals($this->component, $arr[1]['param']); + $this->assertTrue(null === $arr[1]['response']); + + $this->assertEquals(2, count($arr)); + + // This tests without the default filtering-out of null + $arr=$this->component->onBehaviorEvent($this, $this->component, false); + $this->assertEquals(array(null, null), $arr); + + + unset($this->component->onBehaviorEvent); + $this->assertEquals(0, $this->component->onBehaviorEvent->Count); + + $this->component->onBehaviorEvent = array($this, 'returnValue4'); + $this->component->onBehaviorEvent = array($this, 'returnValue1'); + + // Test the per event post processing function + $arr=$this->component->onBehaviorEvent($this, $this->component, array($this, 'postEventFunction')); + $this->assertEquals(array(exp(4), exp(1)), $arr); + $arr=$this->component->onBehaviorEvent($this, $this->component, array($this, 'postEventFunction2')); + $this->assertEquals(array(sin(4), sin(1)), $arr); + + + //Testing Feed-forward functionality + unset($this->component->onBehaviorEvent); + + $this->component->onBehaviorEvent = array($this, 'ffValue4'); + $this->component->onBehaviorEvent = array($this, 'ffValue2'); + $arr=$this->component->onBehaviorEvent($this, 5, TEventResults::EVENT_RESULT_FEED_FORWARD); + $this->assertEquals(array(20, 40), $arr); + + + unset($this->component->onBehaviorEvent); + + //Order of these events affects the response order in feed forward + $this->component->onBehaviorEvent = array($this, 'ffValue2'); + $this->component->onBehaviorEvent = array($this, 'ffValue4'); + $arr=$this->component->onBehaviorEvent($this, 5, TEventResults::EVENT_RESULT_FEED_FORWARD); + $this->assertEquals(array(10, 40), $arr); + } + + public function returnValue1(){return 1;} + public function returnValue4(){return 4;} + public function postEventFunction($sender, $param, $caller, $response){return exp($response);} + public function postEventFunction2($sender, $param, $caller, $response){return sin($response);} + public function ffValue2($sender, $param){return $param*2;} + public function ffValue4($sender, $param){return $param*4;} + + + public function testGlobalEventListenerInRaiseEvent() { + //TODO Test the Global Event Listener } + + + public function testIDynamicMethodsOnBehavior() { + + //Add Behavior with dynamic call + $this->component->attachBehavior('TDynamicBehavior', new TDynamicBehavior); + + //Check that the behavior is working as it should + $this->assertTrue($this->component->isa('TDynamicBehavior')); + $this->assertNull($this->component->getLastBehaviorDynamicMethodCalled()); + + // call basic behavior implemented method from object (containing behavior) + $this->assertEquals(42, $this->component->TestBehaviorMethod(6, 7)); + + //Test out undefined behavior/host object method + try { + $this->component->objectAndBehaviorUndefinedMethod(); + $this->fail('exception not raised when evaluating an undefined method by the object and behavior'); + } catch(TApplicationException $e) { + } + + // calling undefined dynamic method, caught by the __dycall method in the behavior and implemented + // this behavior catches undefined dynamic event and divides param1 by param 2 + $this->assertEquals(22, $this->component->dyTestDynamicBehaviorMethod(242, 11)); + $this->assertEquals('dyTestDynamicBehaviorMethod', $this->component->getLastBehaviorDynamicMethodCalled()); + + // calling undefined dynamic method, caught by the __dycall in the behavior and ignored + $this->assertNull($this->component->dyUndefinedIntraEvent(242, 11)); + $this->assertEquals('dyUndefinedIntraEvent', $this->component->getLastBehaviorDynamicMethodCalled()); + + //call behavior defined dynamic event + // param1 * 2 * param2 + $this->assertEquals(2420, $this->component->dyTestIntraEvent(121, 10)); + + $this->component->detachBehavior('TDynamicBehavior'); + $this->assertFalse($this->component->isa('TDynamicBehavior')); + + + + //Add Class Behavior with dynamic call + $this->component->attachBehavior('TDynamicClassBehavior', new TDynamicClassBehavior); + + //Check that the behavior is working as it should + $this->assertTrue($this->component->isa('TDynamicClassBehavior')); + $this->assertNull($this->component->getLastBehaviorDynamicMethodCalled()); + + // call basic behavior implemented method from object (containing behavior) + $this->assertEquals(42, $this->component->TestBehaviorMethod(6, 7)); + + //Test out undefined behavior/host object method + try { + $this->component->objectAndBehaviorUndefinedMethod(); + $this->fail('exception not raised when evaluating an undefined method by the object and behavior'); + } catch(TApplicationException $e) { + } + + // calling undefined dynamic method, caught by the __dycall method in the behavior and implemented + // this behavior catches undefined dynamic event and divides param1 by param 2 + $this->assertEquals(22, $this->component->dyTestDynamicClassBehaviorMethod(242, 11)); + $this->assertEquals('dyTestDynamicClassBehaviorMethod', $this->component->getLastBehaviorDynamicMethodCalled()); + + // calling undefined dynamic method, caught by the __dycall in the behavior and ignored + $this->assertNull($this->component->dyUndefinedIntraEvent(242, 11)); + $this->assertEquals('dyUndefinedIntraEvent', $this->component->getLastBehaviorDynamicMethodCalled()); + + //call behavior defined dynamic event + // param1 * 2 * param2 + $this->assertEquals(2420, $this->component->dyTestIntraEvent(121, 10)); + + $this->component->detachBehavior('TDynamicClassBehavior'); + $this->assertFalse($this->component->isa('TDynamicClassBehavior')); + + + } + + // This also tests the priority of the common global raiseEvent events + public function testIDynamicMethodsOnBehaviorGlobalEvents() { + $component = new GlobalRaiseComponent(); + + // common function has a default priority of 10 + $component->attachEventHandler(TComponent::GLOBAL_RAISE_EVENT_LISTENER, array($component, 'commonRaiseEventListener')); + $component->attachEventHandler(TComponent::GLOBAL_RAISE_EVENT_LISTENER, array($component, 'postglobalRaiseEventListener'), 1); + $component->attachEventHandler(TComponent::GLOBAL_RAISE_EVENT_LISTENER, array($component, 'preglobalRaiseEventListener'), -1); + + $this->assertEquals(5, $this->component->fxGlobalListener->getCount()); + $this->assertEquals(1, $this->component->fxPrimaryGlobalEvent->getCount()); + $this->assertEquals(1, $this->component->fxPrimaryGlobalEvent->getCount(), 'fxPrimaryGlobalEvent is not installed on test object'); + + // call the global event on a different object than the test object + $res = $this->component->raiseEvent('fxPrimaryGlobalEvent', $this, null, TEventResults::EVENT_RESULT_ALL); + + $this->assertEquals(6, count($res)); + $this->assertEquals(array('pregl', 'primary', 'postgl', 'fxGL', 'fxcall', 'com'), $component->getCallOrders()); + + $component->unlisten(); + } + + + public function testEvaluateExpression() { $expression="1+2"; @@ -162,6 +1908,9 @@ class TComponentTest extends PHPUnit_Framework_TestCase { } } + + + public function testEvaluateStatements() { $statements='$a="test string"; echo $a;'; $this->assertEquals('test string',$this->component->evaluateStatements($statements)); @@ -172,6 +1921,169 @@ class TComponentTest extends PHPUnit_Framework_TestCase { } catch(Exception $e) { } } + + + public function testDynamicFunctionCall() { + + $this->assertEquals(' aa bb cc __ .. ++ || !! ?? ', $this->component->dyTextFilter(' aa bb cc __ .. ++ || !! ?? ')); + + $this->component->attachBehavior('dy1', new dy1TextReplace); + $this->assertFalse($this->component->dy1->isCalled()); + $this->assertEquals(' aa bb cc __ __ ++ || !! ?? ', $this->component->dyTextFilter(' aa bb cc __ .. ++ || !! ?? ')); + $this->assertTrue($this->component->dy1->isCalled()); + + $this->component->attachBehavior('dy2', new dy2TextReplace); + $this->assertFalse($this->component->dy2->isCalled()); + $this->assertEquals(' aa bb cc __ __ || || !! ?? ', $this->component->dyTextFilter(' aa bb cc __ .. ++ || !! ?? ')); + $this->assertTrue($this->component->dy2->isCalled()); + + $this->component->attachBehavior('dy3', new dy3TextReplace); + $this->assertFalse($this->component->dy3->isCalled()); + $this->assertEquals(' aa bb cc __ __ || || ?? ?? ', $this->component->dyTextFilter(' aa bb cc __ .. ++ || !! ?? ')); + $this->assertTrue($this->component->dy3->isCalled()); + + $this->assertEquals(' aa bb cc __ .. ++ || !! ?? ', $this->component->dyUndefinedEvent(' aa bb cc __ .. ++ || !! ?? ')); + + $this->assertEquals(0.25, $this->component->dyPowerFunction(2,2)); + + + $this->component->detachBehavior('dy1'); + $this->component->detachBehavior('dy2'); + $this->component->detachBehavior('dy3'); + + //test class behaviors of dynamic events and the argument list order + + $this->assertEquals(' aa bb cc __ .. ++ || !! ?? ', $this->component->dyTextFilter(' aa bb cc __ .. ++ || !! ?? ')); + + $this->component->attachBehavior('dy1', new dy1ClassTextReplace); + $this->assertFalse($this->component->dy1->isCalled()); + $this->assertEquals(' aa bb cc .. .. ++ || !! ?? ', $this->component->dyTextFilter(' aa bb cc __ .. ++ || !! ?? ')); + $this->assertTrue($this->component->dy1->isCalled()); + + $this->component->attachBehavior('dy2', new dy2ClassTextReplace); + $this->assertFalse($this->component->dy2->isCalled()); + $this->assertEquals(' aa bb cc .. .. ++ ++ !! ?? ', $this->component->dyTextFilter(' aa bb cc __ .. ++ || !! ?? ')); + $this->assertTrue($this->component->dy2->isCalled()); + + $this->component->attachBehavior('dy3', new dy3ClassTextReplace); + $this->assertFalse($this->component->dy3->isCalled()); + $this->assertEquals(' aa bb cc .. .. ++ ++ !! ^_^ ', $this->component->dyTextFilter(' aa bb cc __ .. ++ || !! ?? ')); + $this->assertTrue($this->component->dy3->isCalled()); + + $this->assertEquals(' aa bb cc __ .. ++ || !! ?? ', $this->component->dyUndefinedEvent(' aa bb cc __ .. ++ || !! ?? ')); + + $this->assertEquals(0.25, $this->component->dyPowerFunction(2,2)); + + + } + + + + + public function testDynamicIntraObjectEvents() { + + $this->component->attachBehavior('IntraEvents', new IntraObjectExtenderBehavior); + + $this->assertNull($this->component->IntraEvents->LastCall); + + //unlisten first, this object listens upon instantiation. + $this->component->unlisten(); + $this->assertEquals(2, $this->component->IntraEvents->LastCall); + + // ensures that IntraEvents nulls the last call variable when calling this getter + $this->assertNull($this->component->IntraEvents->LastCall); + + //listen next to undo the unlisten + $this->component->listen(); + $this->assertEquals(1, $this->component->IntraEvents->LastCall); + + + $this->assertEquals(3, $this->component->evaluateExpression('1+2')); + $this->assertEquals(7, $this->component->IntraEvents->LastCall); + + $statements='$a="test string"; echo $a;'; + $this->assertEquals('test string', $this->component->evaluateStatements($statements)); + $this->assertEquals(8, $this->component->IntraEvents->LastCall); + + $component2 = new NewComponentNoListen(); + $this->assertNull($this->component->createdOnTemplate($component2)); + $this->assertEquals(9, $this->component->IntraEvents->LastCall); + + $this->assertNull($this->component->addParsedObject($component2)); + $this->assertEquals(10, $this->component->IntraEvents->LastCall); + + + + $behavior = new BarBehavior; + $this->assertEquals($behavior, $this->component->attachBehavior('BarBehavior', $behavior)); + $this->assertEquals(11, $this->component->IntraEvents->LastCall); + + $this->assertNull($this->component->disableBehaviors()); + $this->assertNull($this->component->enableBehaviors()); + $this->assertEquals(27, $this->component->IntraEvents->LastCall); + + $this->assertTrue($this->component->disableBehavior('BarBehavior')); + $this->assertEquals(16, $this->component->IntraEvents->LastCall); + + $this->assertTrue($this->component->enableBehavior('BarBehavior')); + $this->assertEquals(15, $this->component->IntraEvents->LastCall); + + $this->assertEquals($behavior, $this->component->detachBehavior('BarBehavior')); + $this->assertEquals(12, $this->component->IntraEvents->LastCall); + + + $this->component->attachEventHandler('OnMyEvent',array($this->component,'myEventHandler')); + $this->component->raiseEvent('OnMyEvent',$this,null); + + //3 + 4 + 5 + 6 = 18 (the behavior adds these together when each raiseEvent dynamic intra event is called) + $this->assertEquals(18, $this->component->IntraEvents->LastCall); + } + + + + public function testJavascriptGetterSetter() { + + $this->assertFalse(isset($this->component->ColorAttribute)); + $this->assertFalse(isset($this->component->JsColorAttribute)); + + $this->component->ColorAttribute = "('#556677', '#abcdef', 503987)"; + $this->assertEquals("('#556677', '#abcdef', 503987)", $this->component->ColorAttribute); + + $this->assertTrue(isset($this->component->ColorAttribute)); + $this->assertTrue(isset($this->component->JsColorAttribute)); + + $this->component->ColorAttribute = "new Array(1, 2, 3, 4, 5)"; + $this->assertEquals("new Array(1, 2, 3, 4, 5)", $this->component->JsColorAttribute); + + $this->component->JsColorAttribute = "['#112233', '#fedcba', 22009837]"; + $this->assertEquals("['#112233', '#fedcba', 22009837]", $this->component->ColorAttribute); + } + + + public function testJavascriptIssetUnset() { + + $this->component->JsColorAttribute = "['#112233', '#fedcba', 22009837]"; + $this->assertEquals("['#112233', '#fedcba', 22009837]", $this->component->ColorAttribute); + + unset($this->component->ColorAttribute); + + $this->assertFalse(isset($this->component->ColorAttribute)); + $this->assertFalse(isset($this->component->JsColorAttribute)); + + $this->component->JsColorAttribute = "['#112233', '#fedcba', 22009837]"; + + $this->assertTrue(isset($this->component->ColorAttribute)); + $this->assertTrue(isset($this->component->JsColorAttribute)); + + unset($this->component->JsColorAttribute); + + $this->assertFalse(isset($this->component->ColorAttribute)); + $this->assertFalse(isset($this->component->JsColorAttribute)); + + } + + + } ?> \ No newline at end of file -- cgit v1.2.3