RoutesCommandTest.php 9.9 KB

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