CakeEventManagerTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. <?php
  2. /**
  3. * ControllerTestCaseTest file
  4. *
  5. * Test Case for ControllerTestCase class
  6. *
  7. * PHP version 5
  8. *
  9. * CakePHP : Rapid Development Framework (http://cakephp.org)
  10. * Copyright 2005-2012, Cake Software Foundation, Inc.
  11. *
  12. * Licensed under The MIT License
  13. * Redistributions of files must retain the above copyright notice.
  14. *
  15. * @copyright Copyright 2005-2012, Cake Software Foundation, Inc.
  16. * @link http://cakephp.org CakePHP Project
  17. * @package Cake.Test.Case.Event
  18. * @since CakePHP v 2.1
  19. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  20. */
  21. App::uses('CakeEvent', 'Event');
  22. App::uses('CakeEventManager', 'Event');
  23. App::uses('CakeEventListener', 'Event');
  24. /**
  25. * Mock class used to test event dispatching
  26. *
  27. * @package Cake.Test.Case.Event
  28. */
  29. class CakeEventTestListener {
  30. public $callStack = array();
  31. /**
  32. * Test function to be used in event dispatching
  33. *
  34. * @return void
  35. */
  36. public function listenerFunction() {
  37. $this->callStack[] = __FUNCTION__;
  38. }
  39. /**
  40. * Test function to be used in event dispatching
  41. *
  42. * @return void
  43. */
  44. public function secondListenerFunction() {
  45. $this->callStack[] = __FUNCTION__;
  46. }
  47. /**
  48. * Auxiliary function to help in stopPropagation testing
  49. *
  50. * @param CakeEvent $event
  51. * @return void
  52. */
  53. public function stopListener($event) {
  54. $event->stopPropagation();
  55. }
  56. }
  57. /**
  58. * Mock used for testing the subscriber objects
  59. *
  60. * @package Cake.Test.Case.Event
  61. */
  62. class CustomTestEventListerner extends CakeEventTestListener implements CakeEventListener {
  63. public function implementedEvents() {
  64. return array(
  65. 'fake.event' => 'listenerFunction',
  66. 'another.event' => array('callable' => 'secondListenerFunction', 'passParams' => true),
  67. 'multiple.handlers' => array(
  68. array('callable' => 'listenerFunction'),
  69. array('callable' => 'thirdListenerFunction')
  70. )
  71. );
  72. }
  73. /**
  74. * Test function to be used in event dispatching
  75. *
  76. * @return void
  77. */
  78. public function thirdListenerFunction() {
  79. $this->callStack[] = __FUNCTION__;
  80. }
  81. }
  82. /**
  83. * Tests the CakeEventManager class functionality
  84. *
  85. */
  86. class CakeEventManagerTest extends CakeTestCase {
  87. /**
  88. * Tests the attach() method for a single event key in multiple queues
  89. *
  90. * @return void
  91. */
  92. public function testAttachListeners() {
  93. $manager = new CakeEventManager;
  94. $manager->attach('fakeFunction', 'fake.event');
  95. $expected = array(
  96. array('callable' => 'fakeFunction', 'passParams' => false)
  97. );
  98. $this->assertEquals($expected, $manager->listeners('fake.event'));
  99. $manager->attach('fakeFunction2', 'fake.event');
  100. $expected[] = array('callable' => 'fakeFunction2', 'passParams' => false);
  101. $this->assertEquals($expected, $manager->listeners('fake.event'));
  102. $manager->attach('inQ5', 'fake.event', array('priority' => 5));
  103. $manager->attach('inQ1', 'fake.event', array('priority' => 1));
  104. $manager->attach('otherInQ5', 'fake.event', array('priority' => 5));
  105. $expected = array_merge(
  106. array(
  107. array('callable' => 'inQ1', 'passParams' => false),
  108. array('callable' => 'inQ5', 'passParams' => false),
  109. array('callable' => 'otherInQ5', 'passParams' => false)
  110. ),
  111. $expected
  112. );
  113. $this->assertEquals($expected, $manager->listeners('fake.event'));
  114. }
  115. /**
  116. * Tests the attach() method for multiple event key in multiple queues
  117. *
  118. * @return void
  119. */
  120. public function testAttachMultipleEventKeys() {
  121. $manager = new CakeEventManager;
  122. $manager->attach('fakeFunction', 'fake.event');
  123. $manager->attach('fakeFunction2', 'another.event');
  124. $manager->attach('fakeFunction3', 'another.event', array('priority' => 1, 'passParams' => true));
  125. $expected = array(
  126. array('callable' => 'fakeFunction', 'passParams' => false)
  127. );
  128. $this->assertEquals($expected, $manager->listeners('fake.event'));
  129. $expected = array(
  130. array('callable' => 'fakeFunction3', 'passParams' => true),
  131. array('callable' => 'fakeFunction2', 'passParams' => false)
  132. );
  133. $this->assertEquals($expected, $manager->listeners('another.event'));
  134. }
  135. /**
  136. * Tests detaching an event from a event key queue
  137. *
  138. * @return void
  139. */
  140. public function testDetach() {
  141. $manager = new CakeEventManager;
  142. $manager->attach(array('AClass', 'aMethod'), 'fake.event');
  143. $manager->attach(array('AClass', 'anotherMethod'), 'another.event');
  144. $manager->attach('fakeFunction', 'another.event', array('priority' => 1));
  145. $manager->detach(array('AClass', 'aMethod'), 'fake.event');
  146. $this->assertEquals(array(), $manager->listeners('fake.event'));
  147. $manager->detach(array('AClass', 'anotherMethod'), 'another.event');
  148. $expected = array(
  149. array('callable' => 'fakeFunction', 'passParams' => false)
  150. );
  151. $this->assertEquals($expected, $manager->listeners('another.event'));
  152. $manager->detach('fakeFunction', 'another.event');
  153. $this->assertEquals(array(), $manager->listeners('another.event'));
  154. }
  155. /**
  156. * Tests detaching an event from all event queues
  157. *
  158. * @return void
  159. */
  160. public function testDetachFromAll() {
  161. $manager = new CakeEventManager;
  162. $manager->attach(array('AClass', 'aMethod'), 'fake.event');
  163. $manager->attach(array('AClass', 'aMethod'), 'another.event');
  164. $manager->attach('fakeFunction', 'another.event', array('priority' => 1));
  165. $manager->detach(array('AClass', 'aMethod'));
  166. $expected = array(
  167. array('callable' => 'fakeFunction', 'passParams' => false)
  168. );
  169. $this->assertEquals($expected, $manager->listeners('another.event'));
  170. $this->assertEquals(array(), $manager->listeners('fake.event'));
  171. }
  172. /**
  173. * Tests event dispatching
  174. *
  175. * @return void
  176. */
  177. public function testDispatch() {
  178. $manager = new CakeEventManager;
  179. $listener = $this->getMock('CakeEventTestListener');
  180. $anotherListener = $this->getMock('CakeEventTestListener');
  181. $manager->attach(array($listener, 'listenerFunction'), 'fake.event');
  182. $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event');
  183. $event = new CakeEvent('fake.event');
  184. $listener->expects($this->once())->method('listenerFunction')->with($event);
  185. $anotherListener->expects($this->once())->method('listenerFunction')->with($event);
  186. $manager->dispatch($event);
  187. }
  188. /**
  189. * Tests event dispatching using event key name
  190. *
  191. * @return void
  192. */
  193. public function testDispatchWithKeyName() {
  194. $manager = new CakeEventManager;
  195. $listener = new CakeEventTestListener;
  196. $manager->attach(array($listener, 'listenerFunction'), 'fake.event');
  197. $event = 'fake.event';
  198. $manager->dispatch($event);
  199. $expected = array('listenerFunction');
  200. $this->assertEquals($expected, $listener->callStack);
  201. }
  202. /**
  203. * Tests event dispatching with a return value
  204. *
  205. * @return void
  206. */
  207. public function testDispatchReturnValue() {
  208. $this->skipIf(
  209. version_compare(PHPUnit_Runner_Version::id(), '3.7', '<'),
  210. 'These tests fail in PHPUnit 3.6'
  211. );
  212. $manager = new CakeEventManager;
  213. $listener = $this->getMock('CakeEventTestListener');
  214. $anotherListener = $this->getMock('CakeEventTestListener');
  215. $manager->attach(array($listener, 'listenerFunction'), 'fake.event');
  216. $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event');
  217. $event = new CakeEvent('fake.event');
  218. $listener->expects($this->at(0))->method('listenerFunction')
  219. ->with($event)
  220. ->will($this->returnValue('something special'));
  221. $anotherListener->expects($this->at(0))
  222. ->method('listenerFunction')
  223. ->with($event);
  224. $manager->dispatch($event);
  225. $this->assertEquals('something special', $event->result);
  226. }
  227. /**
  228. * Tests that returning false in a callback stops the event
  229. *
  230. * @return void
  231. */
  232. public function testDispatchFalseStopsEvent() {
  233. $this->skipIf(
  234. version_compare(PHPUnit_Runner_Version::id(), '3.7', '<'),
  235. 'These tests fail in PHPUnit 3.6'
  236. );
  237. $manager = new CakeEventManager;
  238. $listener = $this->getMock('CakeEventTestListener');
  239. $anotherListener = $this->getMock('CakeEventTestListener');
  240. $manager->attach(array($listener, 'listenerFunction'), 'fake.event');
  241. $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event');
  242. $event = new CakeEvent('fake.event');
  243. $listener->expects($this->at(0))->method('listenerFunction')
  244. ->with($event)
  245. ->will($this->returnValue(false));
  246. $anotherListener->expects($this->never())
  247. ->method('listenerFunction');
  248. $manager->dispatch($event);
  249. $this->assertTrue($event->isStopped());
  250. }
  251. /**
  252. * Tests event dispatching using priorities
  253. *
  254. * @return void
  255. */
  256. public function testDispatchPrioritized() {
  257. $manager = new CakeEventManager;
  258. $listener = new CakeEventTestListener;
  259. $manager->attach(array($listener, 'listenerFunction'), 'fake.event');
  260. $manager->attach(array($listener, 'secondListenerFunction'), 'fake.event', array('priority' => 5));
  261. $event = new CakeEvent('fake.event');
  262. $manager->dispatch($event);
  263. $expected = array('secondListenerFunction', 'listenerFunction');
  264. $this->assertEquals($expected, $listener->callStack);
  265. }
  266. /**
  267. * Tests event dispatching with passed params
  268. *
  269. * @return void
  270. */
  271. public function testDispatchPassingParams() {
  272. $manager = new CakeEventManager;
  273. $listener = $this->getMock('CakeEventTestListener');
  274. $anotherListener = $this->getMock('CakeEventTestListener');
  275. $manager->attach(array($listener, 'listenerFunction'), 'fake.event');
  276. $manager->attach(array($anotherListener, 'secondListenerFunction'), 'fake.event', array('passParams' => true));
  277. $event = new CakeEvent('fake.event', $this, array('some' => 'data'));
  278. $listener->expects($this->once())->method('listenerFunction')->with($event);
  279. $anotherListener->expects($this->once())->method('secondListenerFunction')->with('data');
  280. $manager->dispatch($event);
  281. }
  282. /**
  283. * Tests subscribing a listener object and firing the events it subscribed to
  284. *
  285. * @return void
  286. */
  287. public function testAttachSubscriber() {
  288. $manager = new CakeEventManager;
  289. $listener = $this->getMock('CustomTestEventListerner', array('secondListenerFunction'));
  290. $manager->attach($listener);
  291. $event = new CakeEvent('fake.event');
  292. $manager->dispatch($event);
  293. $expected = array('listenerFunction');
  294. $this->assertEquals($expected, $listener->callStack);
  295. $listener->expects($this->at(0))->method('secondListenerFunction')->with('data');
  296. $event = new CakeEvent('another.event', $this, array('some' => 'data'));
  297. $manager->dispatch($event);
  298. $manager = new CakeEventManager;
  299. $listener = $this->getMock('CustomTestEventListerner', array('listenerFunction', 'thirdListenerFunction'));
  300. $manager->attach($listener);
  301. $event = new CakeEvent('multiple.handlers');
  302. $listener->expects($this->once())->method('listenerFunction')->with($event);
  303. $listener->expects($this->once())->method('thirdListenerFunction')->with($event);
  304. $manager->dispatch($event);
  305. }
  306. /**
  307. * Tests subscribing a listener object and firing the events it subscribed to
  308. *
  309. * @return void
  310. */
  311. public function testDetachSubscriber() {
  312. $manager = new CakeEventManager;
  313. $listener = $this->getMock('CustomTestEventListerner', array('secondListenerFunction'));
  314. $manager->attach($listener);
  315. $expected = array(
  316. array('callable' => array($listener, 'secondListenerFunction'), 'passParams' => true)
  317. );
  318. $this->assertEquals($expected, $manager->listeners('another.event'));
  319. $expected = array(
  320. array('callable' => array($listener, 'listenerFunction'), 'passParams' => false)
  321. );
  322. $this->assertEquals($expected, $manager->listeners('fake.event'));
  323. $manager->detach($listener);
  324. $this->assertEquals(array(), $manager->listeners('fake.event'));
  325. $this->assertEquals(array(), $manager->listeners('another.event'));
  326. }
  327. /**
  328. * Tests that it is possible to get/set the manager singleton
  329. *
  330. * @return void
  331. */
  332. public function testGlobalDispatcherGetter() {
  333. $this->assertInstanceOf('CakeEventManager', CakeEventManager::instance());
  334. $manager = new CakeEventManager;
  335. CakeEventManager::instance($manager);
  336. $this->assertSame($manager, CakeEventManager::instance());
  337. }
  338. /**
  339. * Tests that the global event manager gets the event too from any other manager
  340. *
  341. * @return void
  342. */
  343. public function testDispatchWithGlobal() {
  344. $generalManager = $this->getMock('CakeEventManager', array('dispatch'));
  345. $manager = new CakeEventManager;
  346. $event = new CakeEvent('fake.event');
  347. CakeEventManager::instance($generalManager);
  348. $generalManager->expects($this->once())->method('dispatch')->with($event);
  349. $manager->dispatch($event);
  350. }
  351. /**
  352. * Tests that stopping an event will not notify the rest of the listeners
  353. *
  354. * @return void
  355. */
  356. public function testStopPropagation() {
  357. $manager = new CakeEventManager;
  358. $listener = new CakeEventTestListener;
  359. $manager->attach(array($listener, 'listenerFunction'), 'fake.event');
  360. $manager->attach(array($listener, 'stopListener'), 'fake.event', array('priority' => 8));
  361. $manager->attach(array($listener, 'secondListenerFunction'), 'fake.event', array('priority' => 5));
  362. $event = new CakeEvent('fake.event');
  363. $manager->dispatch($event);
  364. $expected = array('secondListenerFunction');
  365. $this->assertEquals($expected, $listener->callStack);
  366. }
  367. }