ConsoleIntegrationTestTraitTest.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @since 3.5.0
  13. * @license https://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Console\TestSuite;
  16. use Cake\Console\CommandInterface;
  17. use Cake\Console\TestSuite\ConsoleIntegrationTestTrait;
  18. use Cake\Console\TestSuite\MissingConsoleInputException;
  19. use Cake\TestSuite\TestCase;
  20. use PHPUnit\Framework\AssertionFailedError;
  21. use stdClass;
  22. class ConsoleIntegrationTestTraitTest extends TestCase
  23. {
  24. use ConsoleIntegrationTestTrait;
  25. /**
  26. * setUp
  27. */
  28. public function setUp(): void
  29. {
  30. parent::setUp();
  31. $this->setAppNamespace();
  32. }
  33. /**
  34. * tests exec when using the command runner
  35. */
  36. public function testExecWithCommandRunner(): void
  37. {
  38. $this->exec('');
  39. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  40. $this->assertOutputContains('Current Paths');
  41. $this->assertExitSuccess();
  42. }
  43. /**
  44. * tests exec
  45. */
  46. public function testExec(): void
  47. {
  48. $this->exec('sample');
  49. $this->assertOutputContains('SampleCommand');
  50. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  51. }
  52. /**
  53. * tests that exec catches a StopException
  54. */
  55. public function testExecCommandWithStopException(): void
  56. {
  57. $this->exec('abort_command');
  58. $this->assertExitCode(127);
  59. $this->assertErrorContains('Command aborted');
  60. }
  61. /**
  62. * tests that exec with a format specifier
  63. */
  64. public function testExecCommandWithFormatSpecifier(): void
  65. {
  66. $this->exec('format_specifier_command');
  67. $this->assertOutputContains('format specifier');
  68. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  69. }
  70. /**
  71. * tests a valid core command
  72. */
  73. public function testExecCoreCommand(): void
  74. {
  75. $this->exec('routes');
  76. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  77. }
  78. /**
  79. * tests exec with an arg and an option
  80. */
  81. public function testExecWithArgsAndOption(): void
  82. {
  83. $this->exec('integration arg --opt="some string"');
  84. $this->assertErrorEmpty();
  85. $this->assertOutputContains('arg: arg');
  86. $this->assertOutputContains('opt: some string');
  87. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  88. }
  89. /**
  90. * tests exec with an arg and an option
  91. */
  92. public function testExecWithJsonArg(): void
  93. {
  94. $this->exec("integration '{\"key\":\"value\"}'");
  95. $this->assertErrorEmpty();
  96. $this->assertOutputContains('arg: {"key":"value"}');
  97. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  98. }
  99. /**
  100. * tests exec with missing required argument
  101. */
  102. public function testExecWithMissingRequiredArg(): void
  103. {
  104. $this->exec('integration');
  105. $this->assertErrorContains('Missing required argument');
  106. $this->assertErrorContains('`arg` argument is required');
  107. $this->assertExitCode(CommandInterface::CODE_ERROR);
  108. }
  109. /**
  110. * tests exec with input
  111. */
  112. public function testExecWithInput(): void
  113. {
  114. $this->exec('bridge', ['javascript']);
  115. $this->assertErrorContains('No!');
  116. $this->assertExitCode(CommandInterface::CODE_ERROR);
  117. }
  118. /**
  119. * tests exec with fewer inputs than questions
  120. */
  121. public function testExecWithMissingInput(): void
  122. {
  123. $this->expectException(MissingConsoleInputException::class);
  124. $this->expectExceptionMessage('no more input');
  125. $this->exec('bridge', ['cake']);
  126. }
  127. /**
  128. * tests exec with multiple inputs
  129. */
  130. public function testExecWithMultipleInput(): void
  131. {
  132. $this->exec('bridge', ['cake', 'blue']);
  133. $this->assertOutputContains('You may pass');
  134. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  135. }
  136. public function testExecWithMockServiceDependencies(): void
  137. {
  138. $this->mockService(stdClass::class, function () {
  139. return json_decode('{"console-mock":true}');
  140. });
  141. $this->exec('dependency');
  142. $this->assertOutputContains('constructor inject: {"console-mock":true}');
  143. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  144. }
  145. /**
  146. * tests assertOutputRegExp assertion
  147. */
  148. public function testAssertOutputRegExp(): void
  149. {
  150. $this->exec('sample');
  151. $this->assertOutputRegExp('/^[A-Z]+/mi');
  152. }
  153. /**
  154. * tests commandStringToArgs
  155. */
  156. public function testCommandStringToArgs(): void
  157. {
  158. $result = $this->commandStringToArgs('command --something=nothing --with-spaces="quote me on that" \'quoted \"arg\"\'');
  159. $expected = [
  160. 'command',
  161. '--something=nothing',
  162. '--with-spaces=quote me on that',
  163. 'quoted \"arg\"',
  164. ];
  165. $this->assertSame($expected, $result);
  166. $json = json_encode(['key' => '"val"', 'this' => true]);
  167. $result = $this->commandStringToArgs(" --json='$json'");
  168. $expected = [
  169. '--json=' . $json,
  170. ];
  171. $this->assertSame($expected, $result);
  172. }
  173. /**
  174. * tests failure messages for assertions
  175. *
  176. * @param string $assertion Assertion method
  177. * @param string $message Expected failure message
  178. * @param string $command Command to test
  179. * @param mixed ...$rest
  180. * @dataProvider assertionFailureMessagesProvider
  181. */
  182. public function testAssertionFailureMessages($assertion, $message, $command, ...$rest): void
  183. {
  184. $this->expectException(AssertionFailedError::class);
  185. $this->expectExceptionMessageMatches('#' . $message . '.?#');
  186. $this->exec($command);
  187. call_user_func_array($this->$assertion(...), $rest);
  188. }
  189. /**
  190. * data provider for assertion failure messages
  191. *
  192. * @return array
  193. */
  194. public static function assertionFailureMessagesProvider(): array
  195. {
  196. return [
  197. 'assertExitCode' => ['assertExitCode', 'Failed asserting that `1` matches exit code `0`', 'routes', CommandInterface::CODE_ERROR],
  198. 'assertOutputEmpty' => ['assertOutputEmpty', 'Failed asserting that output is empty', 'routes'],
  199. 'assertOutputContains' => ['assertOutputContains', 'Failed asserting that \'missing\' is in output', 'routes', 'missing'],
  200. 'assertOutputNotContains' => ['assertOutputNotContains', 'Failed asserting that \'controller\' is not in output', 'routes', 'controller'],
  201. 'assertOutputRegExp' => ['assertOutputRegExp', 'Failed asserting that `/missing/` PCRE pattern found in output', 'routes', '/missing/'],
  202. 'assertOutputContainsRow' => ['assertOutputContainsRow', 'Failed asserting that `.*` row was in output', 'routes', ['test', 'missing']],
  203. 'assertErrorContains' => ['assertErrorContains', 'Failed asserting that \'test\' is in error output', 'routes', 'test'],
  204. 'assertErrorRegExp' => ['assertErrorRegExp', 'Failed asserting that `/test/` PCRE pattern found in error output', 'routes', '/test/'],
  205. ];
  206. }
  207. }