/lib/Cake/Test/TestCase/Event/EventManagerTest.php

https://github.com/shama/cakephp · PHP · 419 lines · 240 code · 49 blank · 130 comment · 0 complexity · 3d69af9ad3778b55b037139df74659f7 MD5 · raw file

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