ObjectCollectionTest.php 16 KB

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