CommandCollectionTest.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://cakephp.org CakePHP(tm) Project
  12. * @since 3.5.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\Console;
  16. use Cake\Console\CommandCollection;
  17. use Cake\Core\Configure;
  18. use Cake\Core\Plugin;
  19. use Cake\Shell\I18nShell;
  20. use Cake\Shell\RoutesShell;
  21. use Cake\TestSuite\TestCase;
  22. use stdClass;
  23. /**
  24. * Test case for the CommandCollection
  25. */
  26. class CommandCollectionTest extends TestCase
  27. {
  28. public function setUp()
  29. {
  30. parent::setUp();
  31. Configure::write('App.namespace', 'TestApp');
  32. }
  33. /**
  34. * Test constructor with valid classnames
  35. *
  36. * @return void
  37. */
  38. public function testConstructor()
  39. {
  40. $collection = new CommandCollection([
  41. 'i18n' => I18nShell::class,
  42. 'routes' => RoutesShell::class
  43. ]);
  44. $this->assertTrue($collection->has('routes'));
  45. $this->assertTrue($collection->has('i18n'));
  46. $this->assertCount(2, $collection);
  47. }
  48. /**
  49. * Constructor with invalid class names should blow up
  50. *
  51. * @return void
  52. * @expectedException InvalidArgumentException
  53. * @expectedExceptionMessage Cannot use 'stdClass' for command 'nope' it is not a subclass of Cake\Console\Shell
  54. */
  55. public function testConstructorInvalidClass()
  56. {
  57. new CommandCollection([
  58. 'i18n' => I18nShell::class,
  59. 'nope' => stdClass::class
  60. ]);
  61. }
  62. /**
  63. * Test basic add/get
  64. *
  65. * @return void
  66. */
  67. public function testAdd()
  68. {
  69. $collection = new CommandCollection();
  70. $this->assertSame($collection, $collection->add('routes', RoutesShell::class));
  71. $this->assertTrue($collection->has('routes'));
  72. $this->assertSame(RoutesShell::class, $collection->get('routes'));
  73. }
  74. /**
  75. * Test that add() replaces.
  76. *
  77. * @return void
  78. */
  79. public function testAddReplace()
  80. {
  81. $collection = new CommandCollection();
  82. $this->assertSame($collection, $collection->add('routes', RoutesShell::class));
  83. $this->assertSame($collection, $collection->add('routes', I18nShell::class));
  84. $this->assertTrue($collection->has('routes'));
  85. $this->assertSame(I18nShell::class, $collection->get('routes'));
  86. }
  87. /**
  88. * Test adding with instances
  89. *
  90. * @return void
  91. */
  92. public function testAddInstance()
  93. {
  94. $collection = new CommandCollection();
  95. $io = $this->getMockBuilder('Cake\Console\ConsoleIo')
  96. ->disableOriginalConstructor()
  97. ->getMock();
  98. $shell = new RoutesShell($io);
  99. $collection->add('routes', $shell);
  100. $this->assertTrue($collection->has('routes'));
  101. $this->assertSame($shell, $collection->get('routes'));
  102. }
  103. /**
  104. * Instances that are not shells should fail.
  105. *
  106. * @expectedException InvalidArgumentException
  107. * @expectedExceptionMessage Cannot use 'stdClass' for command 'routes' it is not a subclass of Cake\Console\Shell
  108. */
  109. public function testAddInvalidInstance()
  110. {
  111. $collection = new CommandCollection();
  112. $shell = new stdClass();
  113. $collection->add('routes', $shell);
  114. }
  115. /**
  116. * Class names that are not shells should fail
  117. *
  118. * @expectedException InvalidArgumentException
  119. * @expectedExceptionMessage Cannot use 'stdClass' for command 'routes' it is not a subclass of Cake\Console\Shell
  120. */
  121. public function testInvalidShellClassName()
  122. {
  123. $collection = new CommandCollection();
  124. $collection->add('routes', stdClass::class);
  125. }
  126. /**
  127. * Test removing a command
  128. *
  129. * @return void
  130. */
  131. public function testRemove()
  132. {
  133. $collection = new CommandCollection();
  134. $collection->add('routes', RoutesShell::class);
  135. $this->assertSame($collection, $collection->remove('routes'));
  136. $this->assertFalse($collection->has('routes'));
  137. }
  138. /**
  139. * Removing an unknown command does not fail
  140. *
  141. * @return void
  142. */
  143. public function testRemoveUnknown()
  144. {
  145. $collection = new CommandCollection();
  146. $this->assertSame($collection, $collection->remove('nope'));
  147. $this->assertFalse($collection->has('nope'));
  148. }
  149. /**
  150. * test getIterator
  151. *
  152. * @return void
  153. */
  154. public function testGetIterator()
  155. {
  156. $in = [
  157. 'i18n' => I18nShell::class,
  158. 'routes' => RoutesShell::class
  159. ];
  160. $collection = new CommandCollection($in);
  161. $out = [];
  162. foreach ($collection as $key => $value) {
  163. $out[$key] = $value;
  164. }
  165. $this->assertEquals($in, $out);
  166. }
  167. /**
  168. * test autodiscovering app shells
  169. *
  170. * @return void
  171. */
  172. public function testAutoDiscoverApp()
  173. {
  174. $collection = new CommandCollection();
  175. $collection->addMany($collection->autoDiscover());
  176. $this->assertTrue($collection->has('i18m'));
  177. $this->assertTrue($collection->has('sample'));
  178. $this->assertTrue($collection->has('testing_dispatch'));
  179. $this->assertSame('TestApp\Shell\I18mShell', $collection->get('i18m'));
  180. $this->assertSame('TestApp\Shell\SampleShell', $collection->get('sample'));
  181. }
  182. /**
  183. * test autodiscovering core shells
  184. *
  185. * @return void
  186. */
  187. public function testAutoDiscoverCore()
  188. {
  189. $collection = new CommandCollection();
  190. $collection->addMany($collection->autoDiscover());
  191. $this->assertTrue($collection->has('routes'));
  192. $this->assertTrue($collection->has('i18n'));
  193. $this->assertTrue($collection->has('orm_cache'));
  194. $this->assertTrue($collection->has('server'));
  195. $this->assertTrue($collection->has('cache'));
  196. $this->assertFalse($collection->has('command_list'), 'Hidden commands should stay hidden');
  197. // These have to be strings as ::class uses the local namespace.
  198. $this->assertSame('Cake\Shell\RoutesShell', $collection->get('routes'));
  199. $this->assertSame('Cake\Shell\I18nShell', $collection->get('i18n'));
  200. }
  201. /**
  202. * test autodiscovering plugin shells
  203. *
  204. * @return void
  205. */
  206. public function testAutoDiscoverPlugin()
  207. {
  208. Plugin::load('TestPlugin');
  209. Plugin::load('Company/TestPluginThree');
  210. $collection = new CommandCollection();
  211. $collection->addMany($collection->autoDiscover());
  212. $this->assertTrue(
  213. $collection->has('example'),
  214. 'Used short name for unique plugin shell'
  215. );
  216. $this->assertTrue(
  217. $collection->has('test_plugin.example'),
  218. 'Long names are stored for unique shells'
  219. );
  220. $this->assertTrue(
  221. $collection->has('sample'),
  222. 'Has app shell'
  223. );
  224. $this->assertTrue(
  225. $collection->has('test_plugin.sample'),
  226. 'Duplicate shell was given a full alias'
  227. );
  228. $this->assertTrue(
  229. $collection->has('company'),
  230. 'Used short name for unique plugin shell'
  231. );
  232. $this->assertTrue(
  233. $collection->has('company/test_plugin_three.company'),
  234. 'Long names are stored as well'
  235. );
  236. $this->assertEquals('TestPlugin\Shell\ExampleShell', $collection->get('example'));
  237. $this->assertEquals($collection->get('example'), $collection->get('test_plugin.example'));
  238. $this->assertEquals(
  239. 'TestApp\Shell\SampleShell',
  240. $collection->get('sample'),
  241. 'Should prefer app shells over plugin ones'
  242. );
  243. $this->assertEquals('TestPlugin\Shell\SampleShell', $collection->get('test_plugin.sample'));
  244. }
  245. }