ObjectCollectionTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. <?php
  2. /**
  3. * ObjectCollectionTest file
  4. *
  5. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  6. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7. *
  8. * Licensed under The MIT License
  9. * For full copyright and license information, please see the LICENSE.txt
  10. * Redistributions of files must retain the above copyright notice.
  11. *
  12. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  13. * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  14. * @since 2.0.0
  15. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  16. */
  17. namespace Cake\Test\TestCase\Utility;
  18. use Cake\Core\Object;
  19. use Cake\Event\Event;
  20. use Cake\TestSuite\TestCase;
  21. use Cake\Utility\ObjectCollection;
  22. /**
  23. * A generic object class
  24. */
  25. class GenericObject {
  26. /**
  27. * Constructor
  28. *
  29. * @param GenericObjectCollection $collection
  30. * @param array $settings
  31. */
  32. public function __construct(GenericObjectCollection $collection, $settings = array()) {
  33. $this->_Collection = $collection;
  34. }
  35. }
  36. /**
  37. * First Extension of Generic Object
  38. */
  39. class FirstGenericObject extends GenericObject {
  40. /**
  41. * A generic callback
  42. */
  43. public function callback() {
  44. }
  45. }
  46. /**
  47. * Second Extension of Generic Object
  48. */
  49. class SecondGenericObject extends GenericObject {
  50. public function callback() {
  51. }
  52. }
  53. /**
  54. * Third Extension of Generic Object
  55. */
  56. class ThirdGenericObject extends GenericObject {
  57. public function callback() {
  58. }
  59. }
  60. /**
  61. * A collection of Generic objects
  62. */
  63. class GenericObjectCollection extends ObjectCollection {
  64. /**
  65. * Loads a generic object
  66. *
  67. * @param string $object Object name
  68. * @param array $settings Settings array
  69. * @return array List of loaded objects
  70. */
  71. public function load($object, $settings = array()) {
  72. list(, $name) = pluginSplit($object);
  73. if (isset($this->_loaded[$name])) {
  74. return $this->_loaded[$name];
  75. }
  76. $objectClass = $name . 'GenericObject';
  77. if (strpos($objectClass, 'Mock') === false) {
  78. $objectClass = __NAMESPACE__ . '\\' . $objectClass;
  79. }
  80. $this->_loaded[$name] = new $objectClass($this, $settings);
  81. $enable = isset($settings['enabled']) ? $settings['enabled'] : true;
  82. if ($enable === true) {
  83. $this->enable($name);
  84. }
  85. return $this->_loaded[$name];
  86. }
  87. /**
  88. * Helper method for adding/overwriting enabled objects including
  89. * settings
  90. *
  91. * @param string $name Name of the object
  92. * @param Object $object The object to use
  93. * @param array $settings Settings to apply for the object
  94. * @return array Loaded objects
  95. */
  96. public function setObject($name, $object, $settings = array()) {
  97. $this->_loaded[$name] = $object;
  98. if (isset($settings['priority'])) {
  99. $this->setPriority($name, $settings['priority']);
  100. }
  101. $enable = isset($settings['enabled']) ? $settings['enabled'] : true;
  102. if ($enable === true) {
  103. $this->enable($name);
  104. }
  105. return $this->_loaded;
  106. }
  107. }
  108. class ObjectCollectionTest extends TestCase {
  109. /**
  110. * setUp
  111. *
  112. * @return void
  113. */
  114. public function setUp() {
  115. parent::setUp();
  116. $this->Objects = new GenericObjectCollection();
  117. }
  118. /**
  119. * tearDown
  120. *
  121. * @return void
  122. */
  123. public function tearDown() {
  124. parent::tearDown();
  125. unset($this->Objects);
  126. }
  127. /**
  128. * test triggering callbacks on loaded helpers
  129. *
  130. * @return void
  131. */
  132. public function testLoad() {
  133. $result = $this->Objects->load('First');
  134. $this->assertInstanceOf(__NAMESPACE__ . '\FirstGenericObject', $result);
  135. $this->assertInstanceOf(__NAMESPACE__ . '\FirstGenericObject', $this->Objects->First);
  136. $result = $this->Objects->loaded();
  137. $this->assertEquals(array('First'), $result, 'loaded() results are wrong.');
  138. $this->assertTrue($this->Objects->enabled('First'));
  139. $result = $this->Objects->load('First');
  140. $this->assertSame($result, $this->Objects->First);
  141. }
  142. /**
  143. * test unload()
  144. *
  145. * @return void
  146. */
  147. public function testUnload() {
  148. $this->Objects->load('First');
  149. $this->Objects->load('Second');
  150. $result = $this->Objects->loaded();
  151. $this->assertEquals(array('First', 'Second'), $result, 'loaded objects are wrong');
  152. $this->Objects->unload('First');
  153. $this->assertFalse(isset($this->Objects->First));
  154. $this->assertTrue(isset($this->Objects->Second));
  155. $result = $this->Objects->loaded();
  156. $this->assertEquals(array('Second'), $result, 'loaded objects are wrong');
  157. $result = $this->Objects->loaded();
  158. $this->assertEquals(array('Second'), $result, 'enabled objects are wrong');
  159. }
  160. /**
  161. * Tests set()
  162. *
  163. * @return void
  164. */
  165. public function testSet() {
  166. $this->Objects->load('First');
  167. $result = $this->Objects->loaded();
  168. $this->assertEquals(array('First'), $result, 'loaded objects are wrong');
  169. $result = $this->Objects->set('First', new SecondGenericObject($this->Objects));
  170. $this->assertInstanceOf(__NAMESPACE__ . '\SecondGenericObject', $result['First'], 'set failed');
  171. $result = $this->Objects->set('Second', new SecondGenericObject($this->Objects));
  172. $this->assertInstanceOf(__NAMESPACE__ . '\SecondGenericObject', $result['Second'], 'set failed');
  173. $this->assertEquals(2, count($result));
  174. }
  175. /**
  176. * creates mock classes for testing
  177. *
  178. * @return void
  179. */
  180. protected function _makeMockClasses() {
  181. $this->FirstGenericObject = $this->getMock(
  182. __NAMESPACE__ . '\FirstGenericObject',
  183. array(), array(), '', false
  184. );
  185. $this->SecondGenericObject = $this->getMock(
  186. __NAMESPACE__ . '\SecondGenericObject',
  187. array(), array(), '', false
  188. );
  189. $this->ThirdGenericObject = $this->getMock(
  190. __NAMESPACE__ . '\ThirdGenericObject',
  191. array(), array(), '', false
  192. );
  193. }
  194. /**
  195. * test triggering callbacks.
  196. *
  197. * @return void
  198. */
  199. public function testTrigger() {
  200. $this->_makeMockClasses();
  201. $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject);
  202. $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject);
  203. $this->Objects->TriggerMockFirst->expects($this->once())
  204. ->method('callback')
  205. ->will($this->returnValue(true));
  206. $this->Objects->TriggerMockSecond->expects($this->once())
  207. ->method('callback')
  208. ->will($this->returnValue(true));
  209. $this->assertTrue($this->Objects->trigger('callback'));
  210. }
  211. /**
  212. * test trigger and disabled objects
  213. *
  214. * @return void
  215. */
  216. public function testTriggerWithDisabledObjects() {
  217. $this->_makeMockClasses();
  218. $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject);
  219. $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject, array('enabled' => false));
  220. $this->Objects->TriggerMockFirst->expects($this->once())
  221. ->method('callback')
  222. ->will($this->returnValue(true));
  223. $this->Objects->TriggerMockSecond->expects($this->never())
  224. ->method('callback')
  225. ->will($this->returnValue(true));
  226. $this->assertTrue($this->Objects->trigger('callback', array()));
  227. }
  228. /**
  229. * test that the collectReturn option works.
  230. *
  231. * @return void
  232. */
  233. public function testTriggerWithCollectReturn() {
  234. $this->_makeMockClasses();
  235. $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject);
  236. $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject);
  237. $this->Objects->TriggerMockFirst->expects($this->once())
  238. ->method('callback')
  239. ->will($this->returnValue(array('one', 'two')));
  240. $this->Objects->TriggerMockSecond->expects($this->once())
  241. ->method('callback')
  242. ->will($this->returnValue(array('three', 'four')));
  243. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  244. $expected = array(
  245. array('one', 'two'),
  246. array('three', 'four')
  247. );
  248. $this->assertEquals($expected, $result);
  249. }
  250. /**
  251. * test that trigger with break & breakOn works.
  252. *
  253. * @return void
  254. */
  255. public function testTriggerWithBreak() {
  256. $this->_makeMockClasses();
  257. $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject);
  258. $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject);
  259. $this->Objects->TriggerMockFirst->expects($this->once())
  260. ->method('callback')
  261. ->will($this->returnValue(false));
  262. $this->Objects->TriggerMockSecond->expects($this->never())
  263. ->method('callback');
  264. $result = $this->Objects->trigger(
  265. 'callback',
  266. array(),
  267. array('break' => true, 'breakOn' => false)
  268. );
  269. $this->assertFalse($result);
  270. }
  271. /**
  272. * test that trigger with modParams works.
  273. *
  274. * @return void
  275. */
  276. public function testTriggerWithModParams() {
  277. $this->_makeMockClasses();
  278. $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject);
  279. $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject);
  280. $this->Objects->TriggerMockFirst->expects($this->once())
  281. ->method('callback')
  282. ->with(array('value'))
  283. ->will($this->returnValue(array('new value')));
  284. $this->Objects->TriggerMockSecond->expects($this->once())
  285. ->method('callback')
  286. ->with(array('new value'))
  287. ->will($this->returnValue(array('newer value')));
  288. $result = $this->Objects->trigger(
  289. 'callback',
  290. array(array('value')),
  291. array('modParams' => 0)
  292. );
  293. $this->assertEquals(array('newer value'), $result);
  294. }
  295. /**
  296. * test that setting modParams to an index that doesn't exist doesn't cause errors.
  297. *
  298. * @expectedException \Cake\Error\Exception
  299. * @return void
  300. */
  301. public function testTriggerModParamsInvalidIndex() {
  302. $this->_makeMockClasses();
  303. $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject);
  304. $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject);
  305. $this->Objects->TriggerMockFirst->expects($this->never())
  306. ->method('callback');
  307. $this->Objects->TriggerMockSecond->expects($this->never())
  308. ->method('callback');
  309. $this->Objects->trigger(
  310. 'callback',
  311. array(array('value')),
  312. array('modParams' => 2)
  313. );
  314. }
  315. /**
  316. * test that returning null doesn't modify parameters.
  317. *
  318. * @return void
  319. */
  320. public function testTriggerModParamsNullIgnored() {
  321. $this->_makeMockClasses();
  322. $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject);
  323. $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject);
  324. $this->Objects->TriggerMockFirst->expects($this->once())
  325. ->method('callback')
  326. ->with(array('value'))
  327. ->will($this->returnValue(null));
  328. $this->Objects->TriggerMockSecond->expects($this->once())
  329. ->method('callback')
  330. ->with(array('value'))
  331. ->will($this->returnValue(array('new value')));
  332. $result = $this->Objects->trigger(
  333. 'callback',
  334. array(array('value')),
  335. array('modParams' => 0)
  336. );
  337. $this->assertEquals(array('new value'), $result);
  338. }
  339. /**
  340. * test order of callbacks triggering based on priority.
  341. *
  342. * @return void
  343. */
  344. public function testTriggerPriority() {
  345. $this->_makeMockClasses();
  346. $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject);
  347. $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject, array('priority' => 5));
  348. $this->Objects->TriggerMockFirst->expects($this->any())
  349. ->method('callback')
  350. ->will($this->returnValue('1st'));
  351. $this->Objects->TriggerMockSecond->expects($this->any())
  352. ->method('callback')
  353. ->will($this->returnValue('2nd'));
  354. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  355. $expected = array(
  356. '2nd',
  357. '1st'
  358. );
  359. $this->assertEquals($expected, $result);
  360. $this->Objects->setObject('TriggerMockThird', $this->ThirdGenericObject, array('priority' => 7));
  361. $this->Objects->TriggerMockThird->expects($this->any())
  362. ->method('callback')
  363. ->will($this->returnValue('3rd'));
  364. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  365. $expected = array(
  366. '2nd',
  367. '3rd',
  368. '1st'
  369. );
  370. $this->assertEquals($expected, $result);
  371. $this->Objects->disable('TriggerMockFirst');
  372. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  373. $expected = array(
  374. '2nd',
  375. '3rd'
  376. );
  377. $this->assertEquals($expected, $result);
  378. $this->Objects->enable('TriggerMockFirst');
  379. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  380. $expected = array(
  381. '2nd',
  382. '3rd',
  383. '1st'
  384. );
  385. $this->assertEquals($expected, $result);
  386. $this->Objects->disable('TriggerMockThird');
  387. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  388. $expected = array(
  389. '2nd',
  390. '1st'
  391. );
  392. $this->assertEquals($expected, $result);
  393. $this->Objects->enable('TriggerMockThird', false);
  394. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  395. $expected = array(
  396. '2nd',
  397. '1st',
  398. '3rd'
  399. );
  400. $this->assertEquals($expected, $result);
  401. $this->Objects->setPriority('TriggerMockThird', 1);
  402. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  403. $expected = array(
  404. '3rd',
  405. '2nd',
  406. '1st'
  407. );
  408. $this->assertEquals($expected, $result);
  409. $this->Objects->disable('TriggerMockThird');
  410. $this->Objects->setPriority('TriggerMockThird', 11);
  411. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  412. $expected = array(
  413. '2nd',
  414. '1st'
  415. );
  416. $this->assertEquals($expected, $result);
  417. $this->Objects->enable('TriggerMockThird');
  418. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  419. $expected = array(
  420. '2nd',
  421. '1st',
  422. '3rd'
  423. );
  424. $this->assertEquals($expected, $result);
  425. $this->Objects->setPriority('TriggerMockThird');
  426. $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true));
  427. $expected = array(
  428. '2nd',
  429. '1st',
  430. '3rd'
  431. );
  432. $this->assertEquals($expected, $result);
  433. }
  434. /**
  435. * test normalizeObjectArray
  436. *
  437. * @return void
  438. */
  439. public function testnormalizeObjectArray() {
  440. $components = array(
  441. 'Html',
  442. 'Foo.Bar' => array('one', 'two'),
  443. 'Something',
  444. 'Banana.Apple' => array('foo' => 'bar')
  445. );
  446. $result = ObjectCollection::normalizeObjectArray($components);
  447. $expected = array(
  448. 'Html' => array('class' => 'Html', 'settings' => array()),
  449. 'Bar' => array('class' => 'Foo.Bar', 'settings' => array('one', 'two')),
  450. 'Something' => array('class' => 'Something', 'settings' => array()),
  451. 'Apple' => array('class' => 'Banana.Apple', 'settings' => array('foo' => 'bar')),
  452. );
  453. $this->assertEquals($expected, $result);
  454. // This is the result after Controller::_mergeVars
  455. $components = array(
  456. 'Html' => null,
  457. 'Foo.Bar' => array('one', 'two'),
  458. 'Something' => null,
  459. 'Banana.Apple' => array('foo' => 'bar')
  460. );
  461. $result = ObjectCollection::normalizeObjectArray($components);
  462. $this->assertEquals($expected, $result);
  463. }
  464. /**
  465. * tests that passing an instance of Cake\Event\Event to trigger will prepend the subject to the list of arguments
  466. *
  467. * @return void
  468. */
  469. public function testDispatchEventWithSubject() {
  470. $this->_makeMockClasses();
  471. $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject);
  472. $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject);
  473. $subjectClass = new Object();
  474. $this->Objects->TriggerMockFirst->expects($this->once())
  475. ->method('callback')
  476. ->with($subjectClass, 'first argument')
  477. ->will($this->returnValue(true));
  478. $this->Objects->TriggerMockSecond->expects($this->once())
  479. ->method('callback')
  480. ->with($subjectClass, 'first argument')
  481. ->will($this->returnValue(true));
  482. $event = new Event('callback', $subjectClass, array('first argument'));
  483. $this->assertTrue($this->Objects->trigger($event));
  484. }
  485. /**
  486. * tests that passing an instance of Cake\Event\Event to trigger with omitSubject property
  487. * will NOT prepend the subject to the list of arguments
  488. *
  489. * @return void
  490. */
  491. public function testDispatchEventNoSubject() {
  492. $this->_makeMockClasses();
  493. $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject);
  494. $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject);
  495. $subjectClass = new Object();
  496. $this->Objects->TriggerMockFirst->expects($this->once())
  497. ->method('callback')
  498. ->with('first argument')
  499. ->will($this->returnValue(true));
  500. $this->Objects->TriggerMockSecond->expects($this->once())
  501. ->method('callback')
  502. ->with('first argument')
  503. ->will($this->returnValue(true));
  504. $event = new Event('callback', $subjectClass, array('first argument'));
  505. $event->omitSubject = true;
  506. $this->assertTrue($this->Objects->trigger($event));
  507. }
  508. }