RoutesCommandTest.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP : 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. * @link https://cakephp.org CakePHP Project
  13. * @since 3.1.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\Command;
  17. use Cake\Console\CommandInterface;
  18. use Cake\Console\TestSuite\ConsoleIntegrationTestTrait;
  19. use Cake\Routing\Route\Route;
  20. use Cake\Routing\Router;
  21. use Cake\TestSuite\TestCase;
  22. /**
  23. * RoutesCommandTest
  24. */
  25. class RoutesCommandTest extends TestCase
  26. {
  27. use ConsoleIntegrationTestTrait;
  28. /**
  29. * setUp method
  30. */
  31. public function setUp(): void
  32. {
  33. parent::setUp();
  34. $this->setAppNamespace();
  35. }
  36. /**
  37. * tearDown
  38. */
  39. public function tearDown(): void
  40. {
  41. parent::tearDown();
  42. Router::reload();
  43. }
  44. /**
  45. * Ensure help for `routes` works
  46. */
  47. public function testRouteListHelp(): void
  48. {
  49. $this->exec('routes -h');
  50. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  51. $this->assertOutputContains('list of routes');
  52. $this->assertErrorEmpty();
  53. }
  54. /**
  55. * Test checking an nonexistent route.
  56. */
  57. public function testRouteList(): void
  58. {
  59. $this->exec('routes');
  60. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  61. $this->assertOutputContainsRow([
  62. '<info>Route name</info>',
  63. '<info>URI template</info>',
  64. '<info>Plugin</info>',
  65. '<info>Prefix</info>',
  66. '<info>Controller</info>',
  67. '<info>Action</info>',
  68. '<info>Method(s)</info>',
  69. ]);
  70. $this->assertOutputContainsRow([
  71. 'articles:_action',
  72. '/app/articles/{action}/*',
  73. '',
  74. '',
  75. 'Articles',
  76. 'index',
  77. '',
  78. ]);
  79. $this->assertOutputContainsRow([
  80. 'bake._controller:_action',
  81. '/bake/{controller}/{action}',
  82. 'Bake',
  83. '',
  84. '',
  85. 'index',
  86. '',
  87. ]);
  88. $this->assertOutputContainsRow([
  89. 'testName',
  90. '/app/tests/{action}/*',
  91. '',
  92. '',
  93. 'Tests',
  94. 'index',
  95. '',
  96. ]);
  97. }
  98. /**
  99. * Test routes with --verbose option
  100. */
  101. public function testRouteListVerbose(): void
  102. {
  103. $this->exec('routes -v');
  104. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  105. $this->assertOutputContainsRow([
  106. '<info>Route name</info>',
  107. '<info>URI template</info>',
  108. '<info>Plugin</info>',
  109. '<info>Prefix</info>',
  110. '<info>Controller</info>',
  111. '<info>Action</info>',
  112. '<info>Method(s)</info>',
  113. '<info>Defaults</info>',
  114. ]);
  115. $this->assertOutputContainsRow([
  116. 'articles:_action',
  117. '/app/articles/{action}/*',
  118. '',
  119. '',
  120. 'Articles',
  121. 'index',
  122. '',
  123. '{"action":"index","controller":"Articles","plugin":null}',
  124. ]);
  125. }
  126. /**
  127. * Test routes with --sort option
  128. */
  129. public function testRouteListSorted(): void
  130. {
  131. Router::createRouteBuilder('/')->connect(
  132. new Route('/a/route/sorted', [], ['_name' => '_aRoute'])
  133. );
  134. $this->exec('routes -s');
  135. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  136. $this->assertOutputContains('_aRoute', $this->_out->messages()[3]);
  137. }
  138. /**
  139. * Ensure help for `routes` works
  140. */
  141. public function testCheckHelp(): void
  142. {
  143. $this->exec('routes check -h');
  144. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  145. $this->assertOutputContains('Check a URL');
  146. $this->assertErrorEmpty();
  147. }
  148. /**
  149. * Ensure routes check with no input
  150. */
  151. public function testCheckNoInput(): void
  152. {
  153. $this->exec('routes check');
  154. $this->assertExitCode(CommandInterface::CODE_ERROR);
  155. $this->assertErrorContains('`url` argument is required');
  156. }
  157. /**
  158. * Test checking an existing route.
  159. */
  160. public function testCheck(): void
  161. {
  162. $this->exec('routes check /app/articles/check');
  163. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  164. $this->assertOutputContainsRow([
  165. '<info>Route name</info>',
  166. '<info>URI template</info>',
  167. '<info>Defaults</info>',
  168. ]);
  169. $this->assertOutputContainsRow([
  170. 'articles:_action',
  171. '/app/articles/check',
  172. '{"action":"check","controller":"Articles","pass":[],"plugin":null}',
  173. ]);
  174. }
  175. /**
  176. * Test checking an existing route with named route.
  177. */
  178. public function testCheckWithNamedRoute(): void
  179. {
  180. $this->exec('routes check /app/tests/index');
  181. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  182. $this->assertOutputContainsRow([
  183. '<info>Route name</info>',
  184. '<info>URI template</info>',
  185. '<info>Defaults</info>',
  186. ]);
  187. $this->assertOutputContainsRow([
  188. 'testName',
  189. '/app/tests/index',
  190. '{"_name":"testName","action":"index","controller":"Tests","pass":[],"plugin":null}',
  191. ]);
  192. }
  193. /**
  194. * Test checking an existing route with redirect route.
  195. */
  196. public function testCheckWithRedirectRoute(): void
  197. {
  198. $this->exec('routes check /app/redirect');
  199. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  200. $this->assertOutputContainsRow([
  201. '<info>URI template</info>',
  202. '<info>Redirect</info>',
  203. ]);
  204. $this->assertOutputContainsRow([
  205. '/app/redirect',
  206. 'http://example.com/test.html',
  207. ]);
  208. }
  209. /**
  210. * Test checking an nonexistent route.
  211. */
  212. public function testCheckNotFound(): void
  213. {
  214. $this->exec('routes check /nope');
  215. $this->assertExitCode(CommandInterface::CODE_ERROR);
  216. $this->assertErrorContains('did not match');
  217. }
  218. /**
  219. * Ensure help for `routes` works
  220. */
  221. public function testGenerareHelp(): void
  222. {
  223. $this->exec('routes generate -h');
  224. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  225. $this->assertOutputContains('Check a routing array');
  226. $this->assertErrorEmpty();
  227. }
  228. /**
  229. * Test generating URLs
  230. */
  231. public function testGenerateNoPassArgs(): void
  232. {
  233. $this->exec('routes generate controller:Articles action:index');
  234. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  235. $this->assertOutputContains('> /app/articles');
  236. $this->assertErrorEmpty();
  237. }
  238. /**
  239. * Test generating URLs with passed arguments
  240. */
  241. public function testGeneratePassedArguments(): void
  242. {
  243. $this->exec('routes generate controller:Articles action:view 2 3');
  244. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  245. $this->assertOutputContains('> /app/articles/view/2/3');
  246. $this->assertErrorEmpty();
  247. }
  248. /**
  249. * Test generating URLs with bool params
  250. */
  251. public function testGenerateBoolParams(): void
  252. {
  253. $this->exec('routes generate controller:Articles action:index _ssl:true _host:example.com');
  254. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  255. $this->assertOutputContains('> https://example.com/app/articles');
  256. }
  257. /**
  258. * Test generating URLs
  259. */
  260. public function testGenerateMissing(): void
  261. {
  262. $this->exec('routes generate plugin:Derp controller:Derp');
  263. $this->assertExitCode(CommandInterface::CODE_ERROR);
  264. $this->assertErrorContains('do not match');
  265. }
  266. /**
  267. * Test routes duplicate warning
  268. */
  269. public function testRouteDuplicateWarning(): void
  270. {
  271. $builder = Router::createRouteBuilder('/');
  272. $builder->connect(
  273. new Route('/unique-path', [], ['_name' => '_aRoute'])
  274. );
  275. $builder->connect(
  276. new Route('/unique-path', [], ['_name' => '_bRoute'])
  277. );
  278. $this->exec('routes');
  279. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  280. $this->assertOutputContainsRow([
  281. '<info>Route name</info>',
  282. '<info>URI template</info>',
  283. '<info>Plugin</info>',
  284. '<info>Prefix</info>',
  285. '<info>Controller</info>',
  286. '<info>Action</info>',
  287. '<info>Method(s)</info>',
  288. ]);
  289. $this->assertOutputContainsRow([
  290. '_aRoute',
  291. '/unique-path',
  292. '',
  293. '',
  294. '',
  295. '',
  296. '',
  297. ]);
  298. $this->assertOutputContainsRow([
  299. '_bRoute',
  300. '/unique-path',
  301. '',
  302. '',
  303. '',
  304. '',
  305. '',
  306. ]);
  307. }
  308. }