/lib/Cake/Test/Case/Event/CakeEventManagerTest.php

https://bitbucket.org/00firestar00/ejfirestar.com · PHP · 415 lines · 238 code · 49 blank · 128 comment · 0 complexity · e1f3c121dea0a4afb90ba6daf5bce024 MD5 · raw file

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