CakeEventManagerTest.php 15 KB

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