ComponentTest.php 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) Tests <https://book.cakephp.org/view/1196/Testing>
  5. * Copyright 2005-2011, Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * Redistributions of files must retain the above copyright notice
  9. *
  10. * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
  12. * @since 1.2.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Controller;
  16. use Cake\Controller\Component\FlashComponent;
  17. use Cake\Controller\ComponentRegistry;
  18. use Cake\Controller\Controller;
  19. use Cake\Core\Exception\Exception;
  20. use Cake\Event\EventManager;
  21. use Cake\TestSuite\TestCase;
  22. use TestApp\Controller\Component\AppleComponent;
  23. use TestApp\Controller\Component\BananaComponent;
  24. use TestApp\Controller\Component\ConfiguredComponent;
  25. use TestApp\Controller\Component\OrangeComponent;
  26. use TestApp\Controller\Component\SomethingWithFlashComponent;
  27. use TestApp\Controller\ComponentTestController;
  28. /**
  29. * ComponentTest class
  30. */
  31. class ComponentTest extends TestCase
  32. {
  33. /**
  34. * setUp method
  35. *
  36. * @return void
  37. */
  38. public function setUp(): void
  39. {
  40. parent::setUp();
  41. static::setAppNamespace();
  42. }
  43. /**
  44. * test accessing inner components.
  45. *
  46. * @return void
  47. */
  48. public function testInnerComponentConstruction(): void
  49. {
  50. $Collection = new ComponentRegistry(new Controller());
  51. $Component = new AppleComponent($Collection);
  52. $this->assertInstanceOf(OrangeComponent::class, $Component->Orange, 'class is wrong');
  53. }
  54. /**
  55. * test component loading
  56. *
  57. * @return void
  58. */
  59. public function testNestedComponentLoading(): void
  60. {
  61. $Collection = new ComponentRegistry(new Controller());
  62. $Apple = new AppleComponent($Collection);
  63. $this->assertInstanceOf(OrangeComponent::class, $Apple->Orange, 'class is wrong');
  64. $this->assertInstanceOf(BananaComponent::class, $Apple->Orange->Banana, 'class is wrong');
  65. $this->assertEmpty($Apple->Session);
  66. $this->assertEmpty($Apple->Orange->Session);
  67. }
  68. /**
  69. * test that component components are not enabled in the collection.
  70. *
  71. * @return void
  72. */
  73. public function testInnerComponentsAreNotEnabled(): void
  74. {
  75. $mock = $this->getMockBuilder(EventManager::class)->getMock();
  76. $controller = new Controller();
  77. $controller->setEventManager($mock);
  78. $mock->expects($this->once())
  79. ->method('on')
  80. ->with($this->isInstanceOf(AppleComponent::class));
  81. $Collection = new ComponentRegistry($controller);
  82. $Apple = $Collection->load('Apple');
  83. $this->assertInstanceOf(OrangeComponent::class, $Apple->Orange, 'class is wrong');
  84. }
  85. /**
  86. * test a component being used more than once.
  87. *
  88. * @return void
  89. */
  90. public function testMultipleComponentInitialize(): void
  91. {
  92. $Collection = new ComponentRegistry(new Controller());
  93. $Banana = $Collection->load('Banana');
  94. $Orange = $Collection->load('Orange');
  95. $this->assertSame($Banana, $Orange->Banana, 'Should be references');
  96. $Banana->testField = 'OrangeField';
  97. $this->assertSame($Banana->testField, $Orange->Banana->testField, 'References are broken');
  98. }
  99. /**
  100. * Test a duplicate component being loaded more than once with same and differing configurations.
  101. *
  102. * @return void
  103. */
  104. public function testDuplicateComponentInitialize(): void
  105. {
  106. $this->expectException(\RuntimeException::class);
  107. $this->expectExceptionMessage('The "Banana" alias has already been loaded. The `property` key');
  108. $Collection = new ComponentRegistry();
  109. $Collection->load('Banana', ['property' => ['closure' => function (): void {
  110. }]]);
  111. $Collection->load('Banana', ['property' => ['closure' => function (): void {
  112. }]]);
  113. $this->assertInstanceOf(BananaComponent::class, $Collection->Banana, 'class is wrong');
  114. $Collection->load('Banana', ['property' => ['differs']]);
  115. }
  116. /**
  117. * Test mutually referencing components.
  118. *
  119. * @return void
  120. */
  121. public function testSomethingReferencingFlashComponent(): void
  122. {
  123. $Controller = new ComponentTestController();
  124. $Controller->loadComponent('SomethingWithFlash');
  125. $Controller->startupProcess();
  126. $this->assertInstanceOf(SomethingWithFlashComponent::class, $Controller->SomethingWithFlash);
  127. $this->assertInstanceOf(FlashComponent::class, $Controller->SomethingWithFlash->Flash);
  128. }
  129. /**
  130. * Tests __debugInfo
  131. *
  132. * @return void
  133. */
  134. public function testDebugInfo(): void
  135. {
  136. $Collection = new ComponentRegistry();
  137. $Component = new AppleComponent($Collection);
  138. $expected = [
  139. 'components' => [
  140. 'Orange',
  141. ],
  142. 'implementedEvents' => [
  143. 'Controller.startup' => 'startup',
  144. ],
  145. '_config' => [],
  146. ];
  147. $result = $Component->__debugInfo();
  148. $this->assertEquals($expected, $result);
  149. }
  150. /**
  151. * Tests null return for unknown magic properties.
  152. *
  153. * @return void
  154. */
  155. public function testMagicReturnsNull(): void
  156. {
  157. $Component = new AppleComponent(new ComponentRegistry());
  158. $this->assertNull($Component->ShouldBeNull);
  159. }
  160. /**
  161. * Tests config via constructor
  162. *
  163. * @return void
  164. */
  165. public function testConfigViaConstructor(): void
  166. {
  167. $Component = new ConfiguredComponent(new ComponentRegistry(), ['chicken' => 'soup']);
  168. $this->assertEquals(['chicken' => 'soup'], $Component->configCopy);
  169. $this->assertEquals(['chicken' => 'soup'], $Component->getConfig());
  170. }
  171. /**
  172. * Lazy load a component without events.
  173. *
  174. * @return void
  175. */
  176. public function testLazyLoading(): void
  177. {
  178. $Component = new ConfiguredComponent(
  179. new ComponentRegistry(new Controller()),
  180. [],
  181. ['Apple', 'Banana', 'Orange']
  182. );
  183. $this->assertInstanceOf(AppleComponent::class, $Component->Apple, 'class is wrong');
  184. $this->assertInstanceOf(OrangeComponent::class, $Component->Orange, 'class is wrong');
  185. $this->assertInstanceOf(BananaComponent::class, $Component->Banana, 'class is wrong');
  186. }
  187. /**
  188. * Lazy load a component that does not exist.
  189. *
  190. * @return void
  191. */
  192. public function testLazyLoadingDoesNotExists(): void
  193. {
  194. $this->expectException(\Cake\Controller\Exception\MissingComponentException::class);
  195. $this->expectExceptionMessage('Component class YouHaveNoBananasComponent could not be found.');
  196. $Component = new ConfiguredComponent(new ComponentRegistry(), [], ['YouHaveNoBananas']);
  197. $bananas = $Component->YouHaveNoBananas;
  198. }
  199. /**
  200. * Lazy loaded components can have config options
  201. *
  202. * @return void
  203. */
  204. public function testConfiguringInnerComponent(): void
  205. {
  206. $Component = new ConfiguredComponent(new ComponentRegistry(), [], ['Configured' => ['foo' => 'bar']]);
  207. $this->assertInstanceOf(ConfiguredComponent::class, $Component->Configured, 'class is wrong');
  208. $this->assertNotSame($Component, $Component->Configured, 'Component instance was reused');
  209. $this->assertEquals(['foo' => 'bar', 'enabled' => false], $Component->Configured->getConfig());
  210. }
  211. /**
  212. * Test enabling events for lazy loaded components
  213. *
  214. * @return void
  215. */
  216. public function testEventsInnerComponent(): void
  217. {
  218. $eventManager = $this->getMockBuilder(EventManager::class)->getMock();
  219. $eventManager->expects($this->once())
  220. ->method('on')
  221. ->with($this->isInstanceOf(AppleComponent::class));
  222. $controller = new Controller();
  223. $controller->setEventManager($eventManager);
  224. $Collection = new ComponentRegistry($controller);
  225. $Component = new ConfiguredComponent($Collection, [], ['Apple' => ['enabled' => true]]);
  226. $this->assertInstanceOf(AppleComponent::class, $Component->Apple, 'class is wrong');
  227. }
  228. /**
  229. * Disabled events do not register for event listeners.
  230. *
  231. * @return void
  232. */
  233. public function testNoEventsInnerComponent(): void
  234. {
  235. $eventManager = $this->getMockBuilder(EventManager::class)->getMock();
  236. $eventManager->expects($this->never())->method('on');
  237. $controller = new Controller();
  238. $controller->setEventManager($eventManager);
  239. $Collection = new ComponentRegistry($controller);
  240. $Component = new ConfiguredComponent($Collection, [], ['Apple' => ['enabled' => false]]);
  241. $this->assertInstanceOf(AppleComponent::class, $Component->Apple, 'class is wrong');
  242. }
  243. /**
  244. * Test that calling getController() without setting a controller throws exception
  245. *
  246. * @return void
  247. */
  248. public function testGetControllerException()
  249. {
  250. $this->expectException(Exception::class);
  251. $this->expectExceptionMessage('Controller not set for ComponentRegistry');
  252. $collection = new ComponentRegistry();
  253. $collection->getController();
  254. }
  255. }