ShellTest.php 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  1. <?php
  2. /**
  3. * CakePHP : 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 Project
  12. * @since 1.2.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Console;
  16. use Cake\Console\ConsoleIo;
  17. use Cake\Console\ConsoleOptionParser;
  18. use Cake\Console\Shell;
  19. use Cake\Core\Configure;
  20. use Cake\Core\Plugin;
  21. use Cake\Filesystem\Folder;
  22. use Cake\TestSuite\TestCase;
  23. use TestApp\Shell\TestingDispatchShell;
  24. /**
  25. * Class for testing merging vars
  26. */
  27. class MergeShell extends Shell
  28. {
  29. public $tasks = ['DbConfig', 'Fixture'];
  30. public $modelClass = 'Articles';
  31. }
  32. /**
  33. * ShellTestShell class
  34. *
  35. */
  36. class ShellTestShell extends Shell
  37. {
  38. /**
  39. * name property
  40. *
  41. * @var name
  42. */
  43. public $name = 'ShellTestShell';
  44. /**
  45. * stopped property
  46. *
  47. * @var int
  48. */
  49. public $stopped;
  50. /**
  51. * testMessage property
  52. *
  53. * @var string
  54. */
  55. public $testMessage = 'all your base are belong to us';
  56. /**
  57. * stop method
  58. *
  59. * @param int $status
  60. * @return void
  61. */
  62. protected function _stop($status = 0)
  63. {
  64. $this->stopped = $status;
  65. }
  66. protected function _secret()
  67. {
  68. }
  69. //@codingStandardsIgnoreStart
  70. public function doSomething()
  71. {
  72. }
  73. protected function noAccess()
  74. {
  75. }
  76. public function logSomething()
  77. {
  78. $this->log($this->testMessage);
  79. }
  80. //@codingStandardsIgnoreEnd
  81. }
  82. /**
  83. * TestAppleTask class
  84. *
  85. */
  86. class TestAppleTask extends Shell
  87. {
  88. }
  89. /**
  90. * TestBananaTask class
  91. *
  92. */
  93. class TestBananaTask extends Shell
  94. {
  95. }
  96. class_alias(__NAMESPACE__ . '\TestAppleTask', 'Cake\Shell\Task\TestAppleTask');
  97. class_alias(__NAMESPACE__ . '\TestBananaTask', 'Cake\Shell\Task\TestBananaTask');
  98. /**
  99. * ShellTest class
  100. *
  101. */
  102. class ShellTest extends TestCase
  103. {
  104. /**
  105. * Fixtures used in this test case
  106. *
  107. * @var array
  108. */
  109. public $fixtures = [
  110. 'core.articles',
  111. 'core.articles_tags',
  112. 'core.attachments',
  113. 'core.comments',
  114. 'core.posts',
  115. 'core.tags',
  116. 'core.users'
  117. ];
  118. /**
  119. * setUp method
  120. *
  121. * @return void
  122. */
  123. public function setUp()
  124. {
  125. parent::setUp();
  126. $this->io = $this->getMock('Cake\Console\ConsoleIo', [], [], '', false);
  127. $this->Shell = new ShellTestShell($this->io);
  128. if (is_dir(TMP . 'shell_test')) {
  129. $Folder = new Folder(TMP . 'shell_test');
  130. $Folder->delete();
  131. }
  132. }
  133. /**
  134. * testConstruct method
  135. *
  136. * @return void
  137. */
  138. public function testConstruct()
  139. {
  140. $this->assertEquals('ShellTestShell', $this->Shell->name);
  141. $this->assertInstanceOf('Cake\Console\ConsoleIo', $this->Shell->io());
  142. }
  143. /**
  144. * testInitialize method
  145. *
  146. * @return void
  147. */
  148. public function testInitialize()
  149. {
  150. Configure::write('App.namespace', 'TestApp');
  151. Plugin::load('TestPlugin');
  152. $this->Shell->tasks = ['DbConfig' => ['one', 'two']];
  153. $this->Shell->plugin = 'TestPlugin';
  154. $this->Shell->modelClass = 'TestPlugin.TestPluginComments';
  155. $this->Shell->initialize();
  156. $this->Shell->loadModel();
  157. $this->assertTrue(isset($this->Shell->TestPluginComments));
  158. $this->assertInstanceOf(
  159. 'TestPlugin\Model\Table\TestPluginCommentsTable',
  160. $this->Shell->TestPluginComments
  161. );
  162. }
  163. /**
  164. * test LoadModel method
  165. *
  166. * @return void
  167. */
  168. public function testLoadModel()
  169. {
  170. Configure::write('App.namespace', 'TestApp');
  171. $Shell = new MergeShell();
  172. $this->assertInstanceOf(
  173. 'TestApp\Model\Table\ArticlesTable',
  174. $Shell->Articles
  175. );
  176. $this->assertEquals('Articles', $Shell->modelClass);
  177. Plugin::load('TestPlugin');
  178. $result = $this->Shell->loadModel('TestPlugin.TestPluginComments');
  179. $this->assertInstanceOf(
  180. 'TestPlugin\Model\Table\TestPluginCommentsTable',
  181. $result
  182. );
  183. $this->assertInstanceOf(
  184. 'TestPlugin\Model\Table\TestPluginCommentsTable',
  185. $this->Shell->TestPluginComments
  186. );
  187. }
  188. /**
  189. * testIn method
  190. *
  191. * @return void
  192. */
  193. public function testIn()
  194. {
  195. $this->io->expects($this->at(0))
  196. ->method('askChoice')
  197. ->with('Just a test?', ['y', 'n'], 'n')
  198. ->will($this->returnValue('n'));
  199. $this->io->expects($this->at(1))
  200. ->method('ask')
  201. ->with('Just a test?', 'n')
  202. ->will($this->returnValue('n'));
  203. $result = $this->Shell->in('Just a test?', ['y', 'n'], 'n');
  204. $this->assertEquals('n', $result);
  205. $result = $this->Shell->in('Just a test?', null, 'n');
  206. $this->assertEquals('n', $result);
  207. }
  208. /**
  209. * Test in() when not interactive.
  210. *
  211. * @return void
  212. */
  213. public function testInNonInteractive()
  214. {
  215. $this->io->expects($this->never())
  216. ->method('askChoice');
  217. $this->io->expects($this->never())
  218. ->method('ask');
  219. $this->Shell->interactive = false;
  220. $result = $this->Shell->in('Just a test?', 'y/n', 'n');
  221. $this->assertEquals('n', $result);
  222. }
  223. /**
  224. * testVerbose method
  225. *
  226. * @return void
  227. */
  228. public function testVerbose()
  229. {
  230. $this->io->expects($this->once())
  231. ->method('verbose')
  232. ->with('Just a test', 1);
  233. $this->Shell->verbose('Just a test');
  234. }
  235. /**
  236. * testQuiet method
  237. *
  238. * @return void
  239. */
  240. public function testQuiet()
  241. {
  242. $this->io->expects($this->once())
  243. ->method('quiet')
  244. ->with('Just a test', 1);
  245. $this->Shell->quiet('Just a test');
  246. }
  247. /**
  248. * testOut method
  249. *
  250. * @return void
  251. */
  252. public function testOut()
  253. {
  254. $this->io->expects($this->once())
  255. ->method('out')
  256. ->with('Just a test', 1);
  257. $this->Shell->out('Just a test');
  258. }
  259. /**
  260. * testErr method
  261. *
  262. * @return void
  263. */
  264. public function testErr()
  265. {
  266. $this->io->expects($this->once())
  267. ->method('err')
  268. ->with('Just a test', 1);
  269. $this->Shell->err('Just a test');
  270. }
  271. /**
  272. * testInfo method
  273. *
  274. * @return void
  275. */
  276. public function testInfo()
  277. {
  278. $this->io->expects($this->once())
  279. ->method('out')
  280. ->with('<info>Just a test</info>', 1);
  281. $this->Shell->info('Just a test');
  282. }
  283. /**
  284. * testWarn method
  285. *
  286. * @return void
  287. */
  288. public function testWarn()
  289. {
  290. $this->io->expects($this->once())
  291. ->method('err')
  292. ->with('<warning>Just a test</warning>', 1);
  293. $this->Shell->warn('Just a test');
  294. }
  295. /**
  296. * testSuccess method
  297. *
  298. * @return void
  299. */
  300. public function testSuccess()
  301. {
  302. $this->io->expects($this->once())
  303. ->method('out')
  304. ->with('<success>Just a test</success>', 1);
  305. $this->Shell->success('Just a test');
  306. }
  307. /**
  308. * testNl
  309. *
  310. * @return void
  311. */
  312. public function testNl()
  313. {
  314. $this->io->expects($this->once())
  315. ->method('nl')
  316. ->with(2);
  317. $this->Shell->nl(2);
  318. }
  319. /**
  320. * testHr
  321. *
  322. * @return void
  323. */
  324. public function testHr()
  325. {
  326. $this->io->expects($this->once())
  327. ->method('hr')
  328. ->with(2);
  329. $this->Shell->hr(2);
  330. }
  331. /**
  332. * testError
  333. *
  334. * @return void
  335. */
  336. public function testError()
  337. {
  338. $this->io->expects($this->at(0))
  339. ->method('err')
  340. ->with('<error>Error:</error> Foo Not Found');
  341. $this->io->expects($this->at(1))
  342. ->method('err')
  343. ->with("Searched all...");
  344. $this->Shell->error('Foo Not Found', 'Searched all...');
  345. $this->assertSame($this->Shell->stopped, 1);
  346. }
  347. /**
  348. * testLoadTasks method
  349. *
  350. * @return void
  351. */
  352. public function testLoadTasks()
  353. {
  354. $this->assertTrue($this->Shell->loadTasks());
  355. $this->Shell->tasks = null;
  356. $this->assertTrue($this->Shell->loadTasks());
  357. $this->Shell->tasks = false;
  358. $this->assertTrue($this->Shell->loadTasks());
  359. $this->Shell->tasks = true;
  360. $this->assertTrue($this->Shell->loadTasks());
  361. $this->Shell->tasks = [];
  362. $this->assertTrue($this->Shell->loadTasks());
  363. $this->Shell->tasks = ['TestApple'];
  364. $this->assertTrue($this->Shell->loadTasks());
  365. $this->assertInstanceOf('Cake\Shell\Task\TestAppleTask', $this->Shell->TestApple);
  366. $this->Shell->tasks = 'TestBanana';
  367. $this->assertTrue($this->Shell->loadTasks());
  368. $this->assertInstanceOf('Cake\Shell\Task\TestAppleTask', $this->Shell->TestApple);
  369. $this->assertInstanceOf('Cake\Shell\Task\TestBananaTask', $this->Shell->TestBanana);
  370. unset($this->Shell->ShellTestApple, $this->Shell->TestBanana);
  371. $this->Shell->tasks = ['TestApple', 'TestBanana'];
  372. $this->assertTrue($this->Shell->loadTasks());
  373. $this->assertInstanceOf('Cake\Shell\Task\TestAppleTask', $this->Shell->TestApple);
  374. $this->assertInstanceOf('Cake\Shell\Task\TestBananaTask', $this->Shell->TestBanana);
  375. }
  376. /**
  377. * test that __get() makes args and params references
  378. *
  379. * @return void
  380. */
  381. public function testMagicGetArgAndParamReferences()
  382. {
  383. $this->Shell->tasks = ['TestApple'];
  384. $this->Shell->args = ['one'];
  385. $this->Shell->params = ['help' => false];
  386. $this->Shell->loadTasks();
  387. $result = $this->Shell->TestApple;
  388. $this->Shell->args = ['one', 'two'];
  389. $this->assertSame($this->Shell->args, $result->args);
  390. $this->assertSame($this->Shell->params, $result->params);
  391. }
  392. /**
  393. * testShortPath method
  394. *
  395. * @return void
  396. */
  397. public function testShortPath()
  398. {
  399. $path = $expected = DS . 'tmp/ab/cd';
  400. $this->assertPathEquals($expected, $this->Shell->shortPath($path));
  401. $path = $expected = DS . 'tmp/ab/cd/';
  402. $this->assertPathEquals($expected, $this->Shell->shortPath($path));
  403. $path = $expected = DS . 'tmp/ab/index.php';
  404. $this->assertPathEquals($expected, $this->Shell->shortPath($path));
  405. $path = DS . 'tmp/ab/' . DS . 'cd';
  406. $expected = DS . 'tmp/ab/cd';
  407. $this->assertPathEquals($expected, $this->Shell->shortPath($path));
  408. $path = 'tmp/ab';
  409. $expected = 'tmp/ab';
  410. $this->assertPathEquals($expected, $this->Shell->shortPath($path));
  411. $path = 'tmp/ab';
  412. $expected = 'tmp/ab';
  413. $this->assertPathEquals($expected, $this->Shell->shortPath($path));
  414. $path = APP;
  415. $result = $this->Shell->shortPath($path);
  416. $this->assertNotContains(ROOT, $result, 'Short paths should not contain ROOT');
  417. }
  418. /**
  419. * testCreateFile method
  420. *
  421. * @return void
  422. */
  423. public function testCreateFileNonInteractive()
  424. {
  425. $eol = PHP_EOL;
  426. $path = TMP . 'shell_test';
  427. $file = $path . DS . 'file1.php';
  428. new Folder($path, true);
  429. $contents = "<?php{$eol}echo 'test';${eol}\$te = 'st';{$eol}";
  430. $result = $this->Shell->createFile($file, $contents);
  431. $this->assertTrue($result);
  432. $this->assertTrue(file_exists($file));
  433. $this->assertEquals(file_get_contents($file), $contents);
  434. }
  435. /**
  436. * Test that files are not changed with a 'n' reply.
  437. *
  438. * @return void
  439. */
  440. public function testCreateFileNoReply()
  441. {
  442. $eol = PHP_EOL;
  443. $path = TMP . 'shell_test';
  444. $file = $path . DS . 'file1.php';
  445. new Folder($path, true);
  446. $this->io->expects($this->once())
  447. ->method('askChoice')
  448. ->will($this->returnValue('n'));
  449. touch($file);
  450. $this->assertTrue(file_exists($file));
  451. $contents = "My content";
  452. $result = $this->Shell->createFile($file, $contents);
  453. $this->assertTrue(file_exists($file));
  454. $this->assertTextEquals('', file_get_contents($file));
  455. $this->assertFalse($result, 'Did not create file.');
  456. }
  457. /**
  458. * Test that files are changed with a 'y' reply.
  459. *
  460. * @return void
  461. */
  462. public function testCreateFileOverwrite()
  463. {
  464. $eol = PHP_EOL;
  465. $path = TMP . 'shell_test';
  466. $file = $path . DS . 'file1.php';
  467. new Folder($path, true);
  468. $this->io->expects($this->once())
  469. ->method('askChoice')
  470. ->will($this->returnValue('y'));
  471. touch($file);
  472. $this->assertTrue(file_exists($file));
  473. $contents = "My content";
  474. $result = $this->Shell->createFile($file, $contents);
  475. $this->assertTrue(file_exists($file));
  476. $this->assertTextEquals($contents, file_get_contents($file));
  477. $this->assertTrue($result, 'Did create file.');
  478. }
  479. /**
  480. * Test that there is no user prompt in non-interactive mode while file already exists.
  481. *
  482. * @return void
  483. */
  484. public function testCreateFileOverwriteNonInteractive()
  485. {
  486. $path = TMP . 'shell_test';
  487. $file = $path . DS . 'file1.php';
  488. new Folder($path, true);
  489. touch($file);
  490. $this->assertTrue(file_exists($file));
  491. $this->io->expects($this->never())->method('askChoice');
  492. $this->Shell->interactive = false;
  493. $result = $this->Shell->createFile($file, 'My content');
  494. $this->assertTrue($result);
  495. $this->assertEquals(file_get_contents($file), 'My content');
  496. }
  497. /**
  498. * Test that all files are changed with a 'a' reply.
  499. *
  500. * @return void
  501. */
  502. public function testCreateFileOverwriteAll()
  503. {
  504. $eol = PHP_EOL;
  505. $path = TMP . 'shell_test';
  506. $files = [
  507. $path . DS . 'file1.php' => 'My first content',
  508. $path . DS . 'file2.php' => 'My second content',
  509. $path . DS . 'file3.php' => 'My third content'
  510. ];
  511. new Folder($path, true);
  512. $this->io->expects($this->once())
  513. ->method('askChoice')
  514. ->will($this->returnValue('a'));
  515. foreach ($files as $file => $contents) {
  516. touch($file);
  517. $this->assertTrue(file_exists($file));
  518. $result = $this->Shell->createFile($file, $contents);
  519. $this->assertTrue(file_exists($file));
  520. $this->assertTextEquals($contents, file_get_contents($file));
  521. $this->assertTrue($result, 'Did create file.');
  522. }
  523. }
  524. /**
  525. * Test that you can't create files that aren't writable.
  526. *
  527. * @return void
  528. */
  529. public function testCreateFileNoPermissions()
  530. {
  531. $this->skipIf(DS === '\\', 'Cant perform operations using permissions on windows.');
  532. $path = TMP . 'shell_test';
  533. $file = $path . DS . 'no_perms';
  534. if (!is_dir($path)) {
  535. mkdir($path);
  536. }
  537. chmod($path, 0444);
  538. $this->Shell->createFile($file, 'testing');
  539. $this->assertFalse(file_exists($file));
  540. chmod($path, 0744);
  541. rmdir($path);
  542. }
  543. /**
  544. * test hasTask method
  545. *
  546. * @return void
  547. */
  548. public function testHasTask()
  549. {
  550. $this->Shell->tasks = ['Extract', 'DbConfig'];
  551. $this->Shell->loadTasks();
  552. $this->assertTrue($this->Shell->hasTask('extract'));
  553. $this->assertTrue($this->Shell->hasTask('Extract'));
  554. $this->assertFalse($this->Shell->hasTask('random'));
  555. $this->assertTrue($this->Shell->hasTask('db_config'));
  556. $this->assertTrue($this->Shell->hasTask('DbConfig'));
  557. }
  558. /**
  559. * test the hasMethod
  560. *
  561. * @return void
  562. */
  563. public function testHasMethod()
  564. {
  565. $this->assertTrue($this->Shell->hasMethod('doSomething'));
  566. $this->assertFalse($this->Shell->hasMethod('hr'), 'hr is callable');
  567. $this->assertFalse($this->Shell->hasMethod('_secret'), '_secret is callable');
  568. $this->assertFalse($this->Shell->hasMethod('no_access'), 'no_access is callable');
  569. }
  570. /**
  571. * test run command calling main.
  572. *
  573. * @return void
  574. */
  575. public function testRunCommandMain()
  576. {
  577. $io = $this->getMock('Cake\Console\ConsoleIo');
  578. $shell = $this->getMock('Cake\Console\Shell', ['main', 'startup'], [$io]);
  579. $shell->expects($this->once())->method('startup');
  580. $shell->expects($this->once())->method('main')
  581. ->with('cakes')
  582. ->will($this->returnValue(true));
  583. $result = $shell->runCommand(['cakes', '--verbose']);
  584. $this->assertTrue($result);
  585. $this->assertEquals('main', $shell->command);
  586. }
  587. /**
  588. * test run command calling a real method with no subcommands defined.
  589. *
  590. * @return void
  591. */
  592. public function testRunCommandWithMethod()
  593. {
  594. $io = $this->getMock('Cake\Console\ConsoleIo');
  595. $shell = $this->getMock('Cake\Console\Shell', ['hitMe', 'startup'], [$io]);
  596. $shell->expects($this->once())->method('startup');
  597. $shell->expects($this->once())->method('hitMe')
  598. ->with('cakes')
  599. ->will($this->returnValue(true));
  600. $result = $shell->runCommand(['hit_me', 'cakes', '--verbose'], true);
  601. $this->assertTrue($result);
  602. $this->assertEquals('hit_me', $shell->command);
  603. }
  604. /**
  605. * test that a command called with an extra parameter passed merges the extra parameters
  606. * to the shell's one
  607. * Also tests that if an extra `requested` parameter prevents the welcome message from
  608. * being displayed
  609. *
  610. * @return void
  611. */
  612. public function testRunCommandWithExtra()
  613. {
  614. $Parser = $this->getMock('Cake\Console\ConsoleOptionParser', ['help'], ['knife']);
  615. $io = $this->getMock('Cake\Console\ConsoleIo');
  616. $Shell = $this->getMock('Cake\Console\Shell', ['getOptionParser', 'slice', '_welcome', 'param'], [$io]);
  617. $Parser->addSubCommand('slice');
  618. $Shell->expects($this->once())
  619. ->method('getOptionParser')
  620. ->will($this->returnValue($Parser));
  621. $Shell->expects($this->once())
  622. ->method('slice')
  623. ->with('cakes');
  624. $Shell->expects($this->never())->method('_welcome');
  625. $Shell->expects($this->once())->method('param')
  626. ->with('requested')
  627. ->will($this->returnValue(true));
  628. $Shell->runCommand(['slice', 'cakes'], false, ['requested' => true]);
  629. }
  630. /**
  631. * Test the dispatchShell() arguments parser
  632. *
  633. * @return void
  634. */
  635. public function testDispatchShellArgsParser()
  636. {
  637. $Shell = new Shell();
  638. $expected = [['schema', 'create', 'DbAcl'], []];
  639. // Shell::dispatchShell('schema create DbAcl');
  640. $result = $Shell->parseDispatchArguments(['schema create DbAcl']);
  641. $this->assertEquals($expected, $result);
  642. // Shell::dispatchShell('schema', 'create', 'DbAcl');
  643. $result = $Shell->parseDispatchArguments(['schema', 'create', 'DbAcl']);
  644. $this->assertEquals($expected, $result);
  645. // Shell::dispatchShell(['command' => 'schema create DbAcl']);
  646. $result = $Shell->parseDispatchArguments([[
  647. 'command' => 'schema create DbAcl'
  648. ]]);
  649. $this->assertEquals($expected, $result);
  650. // Shell::dispatchShell(['command' => ['schema', 'create', 'DbAcl']]);
  651. $result = $Shell->parseDispatchArguments([[
  652. 'command' => ['schema', 'create', 'DbAcl']
  653. ]]);
  654. $this->assertEquals($expected, $result);
  655. $expected[1] = ['param' => 'value'];
  656. // Shell::dispatchShell(['command' => 'schema create DbAcl', 'extra' => ['param' => 'value']]);
  657. $result = $Shell->parseDispatchArguments([[
  658. 'command' => 'schema create DbAcl',
  659. 'extra' => ['param' => 'value']
  660. ]]);
  661. $this->assertEquals($expected, $result);
  662. // Shell::dispatchShell(['command' => ['schema', 'create', 'DbAcl'], 'extra' => ['param' => 'value']]);
  663. $result = $Shell->parseDispatchArguments([[
  664. 'command' => ['schema', 'create', 'DbAcl'],
  665. 'extra' => ['param' => 'value']
  666. ]]);
  667. $this->assertEquals($expected, $result);
  668. }
  669. /**
  670. * test calling a shell that dispatch another one
  671. *
  672. * @return void
  673. */
  674. public function testDispatchShell()
  675. {
  676. $Shell = new TestingDispatchShell();
  677. ob_start();
  678. $Shell->runCommand(['test_task'], true);
  679. $result = ob_get_clean();
  680. $expected = <<<TEXT
  681. <info>Welcome to CakePHP Console</info>
  682. I am a test task, I dispatch another Shell
  683. I am a dispatched Shell
  684. TEXT;
  685. $this->assertEquals($expected, $result);
  686. ob_start();
  687. $Shell->runCommand(['test_task_dispatch_array'], true);
  688. $result = ob_get_clean();
  689. $this->assertEquals($expected, $result);
  690. ob_start();
  691. $Shell->runCommand(['test_task_dispatch_command_string'], true);
  692. $result = ob_get_clean();
  693. $this->assertEquals($expected, $result);
  694. ob_start();
  695. $Shell->runCommand(['test_task_dispatch_command_array'], true);
  696. $result = ob_get_clean();
  697. $this->assertEquals($expected, $result);
  698. $expected = <<<TEXT
  699. <info>Welcome to CakePHP Console</info>
  700. I am a test task, I dispatch another Shell
  701. I am a dispatched Shell. My param `foo` has the value `bar`
  702. TEXT;
  703. ob_start();
  704. $Shell->runCommand(['test_task_dispatch_with_param'], true);
  705. $result = ob_get_clean();
  706. $this->assertEquals($expected, $result);
  707. $expected = <<<TEXT
  708. <info>Welcome to CakePHP Console</info>
  709. I am a test task, I dispatch another Shell
  710. I am a dispatched Shell. My param `foo` has the value `bar`
  711. My param `fooz` has the value `baz`
  712. TEXT;
  713. ob_start();
  714. $Shell->runCommand(['test_task_dispatch_with_multiple_params'], true);
  715. $result = ob_get_clean();
  716. $this->assertEquals($expected, $result);
  717. $expected = <<<TEXT
  718. <info>Welcome to CakePHP Console</info>
  719. I am a test task, I dispatch another Shell
  720. <info>Welcome to CakePHP Console</info>
  721. I am a dispatched Shell
  722. TEXT;
  723. ob_start();
  724. $Shell->runCommand(['test_task_dispatch_with_requested_off'], true);
  725. $result = ob_get_clean();
  726. $this->assertEquals($expected, $result);
  727. }
  728. /**
  729. * Test that runCommand() doesn't call public methods when the second arg is false.
  730. *
  731. * @return void
  732. */
  733. public function testRunCommandAutoMethodOff()
  734. {
  735. $io = $this->getMock('Cake\Console\ConsoleIo');
  736. $shell = $this->getMock('Cake\Console\Shell', ['hit_me', 'startup'], [$io]);
  737. $shell->expects($this->never())->method('startup');
  738. $shell->expects($this->never())->method('hit_me');
  739. $result = $shell->runCommand(['hit_me', 'baseball'], false);
  740. $this->assertFalse($result);
  741. $result = $shell->runCommand(['hit_me', 'baseball']);
  742. $this->assertFalse($result, 'Default value of runCommand() should be false');
  743. }
  744. /**
  745. * test run command calling a real method with mismatching subcommands defined.
  746. *
  747. * @return void
  748. */
  749. public function testRunCommandWithMethodNotInSubcommands()
  750. {
  751. $parser = $this->getMock('Cake\Console\ConsoleOptionParser', ['help'], ['knife']);
  752. $io = $this->getMock('Cake\Console\ConsoleIo');
  753. $shell = $this->getMock('Cake\Console\Shell', ['getOptionParser', 'roll', 'startup'], [$io]);
  754. $parser->addSubCommand('slice');
  755. $shell->expects($this->any())
  756. ->method('getOptionParser')
  757. ->will($this->returnValue($parser));
  758. $parser->expects($this->once())
  759. ->method('help');
  760. $shell->expects($this->never())->method('startup');
  761. $shell->expects($this->never())->method('roll');
  762. $result = $shell->runCommand(['roll', 'cakes', '--verbose']);
  763. $this->assertFalse($result);
  764. }
  765. /**
  766. * test run command calling a real method with subcommands defined.
  767. *
  768. * @return void
  769. */
  770. public function testRunCommandWithMethodInSubcommands()
  771. {
  772. $parser = $this->getMock('Cake\Console\ConsoleOptionParser', ['help'], ['knife']);
  773. $io = $this->getMock('Cake\Console\ConsoleIo');
  774. $shell = $this->getMock('Cake\Console\Shell', ['getOptionParser', 'slice', 'startup'], [$io]);
  775. $parser->addSubCommand('slice');
  776. $shell->expects($this->any())
  777. ->method('getOptionParser')
  778. ->will($this->returnValue($parser));
  779. $shell->expects($this->once())->method('startup');
  780. $shell->expects($this->once())
  781. ->method('slice')
  782. ->with('cakes');
  783. $shell->runCommand(['slice', 'cakes', '--verbose']);
  784. }
  785. /**
  786. * test run command calling a missing method with subcommands defined.
  787. *
  788. * @return void
  789. */
  790. public function testRunCommandWithMissingMethodInSubcommands()
  791. {
  792. $parser = $this->getMock('Cake\Console\ConsoleOptionParser', ['help'], ['knife']);
  793. $parser->addSubCommand('slice');
  794. $io = $this->getMock('Cake\Console\ConsoleIo');
  795. $shell = $this->getMock('Cake\Console\Shell', ['getOptionParser', 'startup'], [$io]);
  796. $shell->expects($this->any())
  797. ->method('getOptionParser')
  798. ->will($this->returnValue($parser));
  799. $shell->expects($this->never())
  800. ->method('startup');
  801. $parser->expects($this->once())
  802. ->method('help');
  803. $shell->runCommand(['slice', 'cakes', '--verbose']);
  804. }
  805. /**
  806. * test run command causing exception on Shell method.
  807. *
  808. * @return void
  809. */
  810. public function testRunCommandBaseclassMethod()
  811. {
  812. $shell = $this->getMockBuilder('Cake\Console\Shell')
  813. ->setMethods(['startup', 'getOptionParser', 'out', 'hr'])
  814. ->disableOriginalConstructor()
  815. ->getMock();
  816. $shell->io($this->getMock('Cake\Console\ConsoleIo'));
  817. $parser = $this->getMock('Cake\Console\ConsoleOptionParser', [], [], '', false);
  818. $parser->expects($this->once())->method('help');
  819. $shell->expects($this->once())->method('getOptionParser')
  820. ->will($this->returnValue($parser));
  821. $shell->expects($this->never())->method('hr');
  822. $shell->expects($this->once())->method('out');
  823. $shell->runCommand(['hr']);
  824. }
  825. /**
  826. * test run command causing exception on Shell method.
  827. *
  828. * @return void
  829. */
  830. public function testRunCommandMissingMethod()
  831. {
  832. $shell = $this->getMockBuilder('Cake\Console\Shell')
  833. ->setMethods(['startup', 'getOptionParser', 'out', 'hr'])
  834. ->disableOriginalConstructor()
  835. ->getMock();
  836. $shell->io($this->getMock('Cake\Console\ConsoleIo'));
  837. $parser = $this->getMock('Cake\Console\ConsoleOptionParser', [], [], '', false);
  838. $parser->expects($this->once())->method('help');
  839. $shell->expects($this->once())->method('getOptionParser')
  840. ->will($this->returnValue($parser));
  841. $shell->expects($this->once())->method('out');
  842. $result = $shell->runCommand(['idontexist']);
  843. $this->assertFalse($result);
  844. }
  845. /**
  846. * test that a --help causes help to show.
  847. *
  848. * @return void
  849. */
  850. public function testRunCommandTriggeringHelp()
  851. {
  852. $parser = $this->getMock('Cake\Console\ConsoleOptionParser', [], [], '', false);
  853. $parser->expects($this->once())->method('parse')
  854. ->with(['--help'])
  855. ->will($this->returnValue([['help' => true], []]));
  856. $parser->expects($this->once())->method('help');
  857. $shell = $this->getMock('Cake\Console\Shell', ['getOptionParser', 'out', 'startup', '_welcome'], [], '', false);
  858. $shell->io($this->getMock('Cake\Console\ConsoleIo'));
  859. $shell->expects($this->once())->method('getOptionParser')
  860. ->will($this->returnValue($parser));
  861. $shell->expects($this->once())->method('out');
  862. $shell->runCommand(['--help']);
  863. }
  864. /**
  865. * test that runCommand will not call runCommand on tasks that are not subcommands.
  866. *
  867. * @return void
  868. */
  869. public function testRunCommandNotCallUnexposedTask()
  870. {
  871. $shell = $this->getMock('Cake\Console\Shell', ['startup', 'hasTask', 'out'], [], '', false);
  872. $shell->io($this->getMock('Cake\Console\ConsoleIo'));
  873. $task = $this->getMock('Cake\Console\Shell', ['runCommand'], [], '', false);
  874. $task->expects($this->never())
  875. ->method('runCommand');
  876. $shell->expects($this->any())
  877. ->method('hasTask')
  878. ->will($this->returnValue(true));
  879. $shell->expects($this->never())->method('startup');
  880. $shell->expects($this->once())->method('out');
  881. $shell->RunCommand = $task;
  882. $result = $shell->runCommand(['run_command', 'one']);
  883. $this->assertFalse($result);
  884. }
  885. /**
  886. * test that runCommand will call runCommand on the task.
  887. *
  888. * @return void
  889. */
  890. public function testRunCommandHittingTaskInSubcommand()
  891. {
  892. $parser = new ConsoleOptionParser('knife');
  893. $parser->addSubcommand('slice');
  894. $io = $this->getMock('Cake\Console\ConsoleIo');
  895. $shell = $this->getMock('Cake\Console\Shell', ['hasTask', 'startup', 'getOptionParser'], [], '', false);
  896. $shell->io($io);
  897. $task = $this->getMock('Cake\Console\Shell', ['main', 'runCommand'], [], '', false);
  898. $task->io($io);
  899. $task->expects($this->once())
  900. ->method('runCommand')
  901. ->with(['one'], false);
  902. $shell->expects($this->once())->method('getOptionParser')
  903. ->will($this->returnValue($parser));
  904. $shell->expects($this->once())->method('startup');
  905. $shell->expects($this->any())
  906. ->method('hasTask')
  907. ->will($this->returnValue(true));
  908. $shell->Slice = $task;
  909. $shell->runCommand(['slice', 'one']);
  910. }
  911. /**
  912. * test wrapBlock wrapping text.
  913. *
  914. * @return void
  915. */
  916. public function testWrapText()
  917. {
  918. $text = 'This is the song that never ends. This is the song that never ends. This is the song that never ends.';
  919. $result = $this->Shell->wrapText($text, ['width' => 33]);
  920. $expected = <<<TEXT
  921. This is the song that never ends.
  922. This is the song that never ends.
  923. This is the song that never ends.
  924. TEXT;
  925. $this->assertTextEquals($expected, $result, 'Text not wrapped.');
  926. $result = $this->Shell->wrapText($text, ['indent' => ' ', 'width' => 33]);
  927. $expected = <<<TEXT
  928. This is the song that never ends.
  929. This is the song that never ends.
  930. This is the song that never ends.
  931. TEXT;
  932. $this->assertTextEquals($expected, $result, 'Text not wrapped.');
  933. }
  934. /**
  935. * Testing camel cased naming of tasks
  936. *
  937. * @return void
  938. */
  939. public function testShellNaming()
  940. {
  941. $this->Shell->tasks = ['TestApple'];
  942. $this->Shell->loadTasks();
  943. $expected = 'TestApple';
  944. $this->assertEquals($expected, $this->Shell->TestApple->name);
  945. }
  946. /**
  947. * Test reading params
  948. *
  949. * @dataProvider paramReadingDataProvider
  950. */
  951. public function testParamReading($toRead, $expected)
  952. {
  953. $this->Shell->params = [
  954. 'key' => 'value',
  955. 'help' => false,
  956. 'emptykey' => '',
  957. 'truthy' => true
  958. ];
  959. $this->assertSame($expected, $this->Shell->param($toRead));
  960. }
  961. /**
  962. * Data provider for testing reading values with Shell::param()
  963. *
  964. * @return array
  965. */
  966. public function paramReadingDataProvider()
  967. {
  968. return [
  969. [
  970. 'key',
  971. 'value',
  972. ],
  973. [
  974. 'help',
  975. false,
  976. ],
  977. [
  978. 'emptykey',
  979. '',
  980. ],
  981. [
  982. 'truthy',
  983. true,
  984. ],
  985. [
  986. 'does_not_exist',
  987. null,
  988. ]
  989. ];
  990. }
  991. /**
  992. * Test that option parsers are created with the correct name/command.
  993. *
  994. * @return void
  995. */
  996. public function testGetOptionParser()
  997. {
  998. $this->Shell->name = 'test';
  999. $this->Shell->plugin = 'plugin';
  1000. $parser = $this->Shell->getOptionParser();
  1001. $this->assertEquals('plugin.test', $parser->command());
  1002. }
  1003. /**
  1004. * Test file and console and logging quiet output
  1005. *
  1006. * @return void
  1007. */
  1008. public function testQuietLog()
  1009. {
  1010. $io = $this->getMock('Cake\Console\ConsoleIo', [], [], '', false);
  1011. $io->expects($this->once())
  1012. ->method('level')
  1013. ->with(Shell::QUIET);
  1014. $io->expects($this->at(0))
  1015. ->method('setLoggers')
  1016. ->with(true);
  1017. $io->expects($this->at(3))
  1018. ->method('setLoggers')
  1019. ->with(ConsoleIo::QUIET);
  1020. $this->Shell = $this->getMock(__NAMESPACE__ . '\ShellTestShell', ['welcome'], [$io]);
  1021. $this->Shell->runCommand(['foo', '--quiet']);
  1022. }
  1023. /**
  1024. * Tests __debugInfo
  1025. *
  1026. * @return void
  1027. */
  1028. public function testDebugInfo()
  1029. {
  1030. $expected = [
  1031. 'name' => 'ShellTestShell',
  1032. 'plugin' => null,
  1033. 'command' => null,
  1034. 'tasks' => [],
  1035. 'params' => [],
  1036. 'args' => [],
  1037. 'interactive' => true
  1038. ];
  1039. $result = $this->Shell->__debugInfo();
  1040. $this->assertEquals($expected, $result);
  1041. }
  1042. }