RoutesCommandTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  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\Core\Configure;
  20. use Cake\Routing\Route\Route;
  21. use Cake\Routing\Router;
  22. use Cake\TestSuite\TestCase;
  23. /**
  24. * RoutesCommandTest
  25. */
  26. class RoutesCommandTest extends TestCase
  27. {
  28. use ConsoleIntegrationTestTrait;
  29. /**
  30. * setUp method
  31. */
  32. public function setUp(): void
  33. {
  34. parent::setUp();
  35. $this->setAppNamespace();
  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(CommandInterface::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(CommandInterface::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>Valid Action</info>',
  70. '<info>Method(s)</info>',
  71. ]);
  72. $this->assertOutputContainsRow([
  73. 'articles:_action',
  74. '/app/articles/{action}/*',
  75. '',
  76. '',
  77. 'Articles',
  78. 'index',
  79. 'X',
  80. '',
  81. ]);
  82. $this->assertOutputContainsRow([
  83. 'bake._controller:_action',
  84. '/bake/{controller}/{action}',
  85. 'Bake',
  86. '',
  87. '',
  88. 'index',
  89. '',
  90. '',
  91. ]);
  92. $this->assertOutputContainsRow([
  93. 'testName',
  94. '/app/tests/{action}/*',
  95. '',
  96. '',
  97. 'Tests',
  98. 'index',
  99. '',
  100. '',
  101. ]);
  102. }
  103. /**
  104. * Test routes with --verbose option
  105. */
  106. public function testRouteListVerbose(): void
  107. {
  108. $this->exec('routes -v');
  109. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  110. $this->assertOutputContainsRow([
  111. '<info>Route name</info>',
  112. '<info>URI template</info>',
  113. '<info>Plugin</info>',
  114. '<info>Prefix</info>',
  115. '<info>Controller</info>',
  116. '<info>Action</info>',
  117. '<info>Valid Action</info>',
  118. '<info>Method(s)</info>',
  119. '<info>Middlewares</info>',
  120. '<info>Defaults</info>',
  121. ]);
  122. $this->assertOutputContainsRow([
  123. 'articles:_action',
  124. '/app/articles/{action}/*',
  125. '',
  126. '',
  127. 'Articles',
  128. 'index',
  129. 'X',
  130. '',
  131. 'dumb, sample',
  132. '{"action":"index","controller":"Articles","plugin":null}',
  133. ]);
  134. }
  135. /**
  136. * Test routes with --sort option
  137. */
  138. public function testRouteListSorted(): void
  139. {
  140. Configure::write('TestApp.routes', function ($routes): void {
  141. $routes->connect(
  142. new Route('/a/route/sorted', [], ['_name' => '_aRoute'])
  143. );
  144. });
  145. $this->exec('routes -s');
  146. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  147. $this->assertOutputContains('_aRoute', $this->_out->messages()[3]);
  148. }
  149. /**
  150. * Test routes with --with-middlewares option
  151. */
  152. public function testRouteWithMiddlewares(): void
  153. {
  154. $this->exec('routes -m');
  155. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  156. $this->assertOutputContainsRow([
  157. 'articles:_action',
  158. '/app/articles/{action}/*',
  159. '',
  160. '',
  161. 'Articles',
  162. 'index',
  163. 'X',
  164. '',
  165. 'dumb, sample',
  166. ]);
  167. }
  168. /**
  169. * Ensure help for `routes` works
  170. */
  171. public function testCheckHelp(): void
  172. {
  173. $this->exec('routes check -h');
  174. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  175. $this->assertOutputContains('Check a URL');
  176. $this->assertErrorEmpty();
  177. }
  178. /**
  179. * Ensure routes check with no input
  180. */
  181. public function testCheckNoInput(): void
  182. {
  183. $this->exec('routes check');
  184. $this->assertExitCode(CommandInterface::CODE_ERROR);
  185. $this->assertErrorContains('`url` argument is required');
  186. }
  187. /**
  188. * Test checking an existing route.
  189. */
  190. public function testCheck(): void
  191. {
  192. $this->exec('routes check /app/articles/check');
  193. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  194. $this->assertOutputContainsRow([
  195. '<info>Route name</info>',
  196. '<info>URI template</info>',
  197. '<info>Defaults</info>',
  198. ]);
  199. $this->assertOutputContainsRow([
  200. 'articles:_action',
  201. '/app/articles/check',
  202. '{"_middleware":["dumb","sample"],"action":"check","controller":"Articles","pass":[],"plugin":null}',
  203. ]);
  204. }
  205. /**
  206. * Test checking an existing route with named route.
  207. */
  208. public function testCheckWithNamedRoute(): void
  209. {
  210. $this->exec('routes check /app/tests/index');
  211. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  212. $this->assertOutputContainsRow([
  213. '<info>Route name</info>',
  214. '<info>URI template</info>',
  215. '<info>Defaults</info>',
  216. ]);
  217. $this->assertOutputContainsRow([
  218. 'testName',
  219. '/app/tests/index',
  220. '{"_middleware":["dumb","sample"],"_name":"testName","action":"index","controller":"Tests","pass":[],"plugin":null}',
  221. ]);
  222. }
  223. /**
  224. * Test checking an existing route with redirect route.
  225. */
  226. public function testCheckWithRedirectRoute(): void
  227. {
  228. $this->exec('routes check /app/redirect');
  229. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  230. $this->assertOutputContainsRow([
  231. '<info>URI template</info>',
  232. '<info>Redirect</info>',
  233. ]);
  234. $this->assertOutputContainsRow([
  235. '/app/redirect',
  236. 'http://example.com/test.html',
  237. ]);
  238. }
  239. /**
  240. * Test checking an nonexistent route.
  241. */
  242. public function testCheckNotFound(): void
  243. {
  244. $this->exec('routes check /nope');
  245. $this->assertExitCode(CommandInterface::CODE_ERROR);
  246. $this->assertErrorContains('did not match');
  247. }
  248. /**
  249. * Ensure help for `routes` works
  250. */
  251. public function testGenerareHelp(): void
  252. {
  253. $this->exec('routes generate -h');
  254. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  255. $this->assertOutputContains('Check a routing array');
  256. $this->assertErrorEmpty();
  257. }
  258. /**
  259. * Test generating URLs
  260. */
  261. public function testGenerateNoPassArgs(): void
  262. {
  263. $this->exec('routes generate controller:Articles action:index');
  264. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  265. $this->assertOutputContains('> /app/articles');
  266. $this->assertErrorEmpty();
  267. }
  268. /**
  269. * Test generating URLs with passed arguments
  270. */
  271. public function testGeneratePassedArguments(): void
  272. {
  273. $this->exec('routes generate controller:Articles action:view 2 3');
  274. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  275. $this->assertOutputContains('> /app/articles/view/2/3');
  276. $this->assertErrorEmpty();
  277. }
  278. /**
  279. * Test generating URLs with bool params
  280. */
  281. public function testGenerateBoolParams(): void
  282. {
  283. $this->exec('routes generate controller:Articles action:index _https:true _host:example.com');
  284. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  285. $this->assertOutputContains('> https://example.com/app/articles');
  286. }
  287. /**
  288. * Test generating URLs
  289. */
  290. public function testGenerateMissing(): void
  291. {
  292. $this->exec('routes generate plugin:Derp controller:Derp');
  293. $this->assertExitCode(CommandInterface::CODE_ERROR);
  294. $this->assertErrorContains('do not match');
  295. }
  296. /**
  297. * Test routes duplicate warning
  298. */
  299. public function testRouteDuplicateWarning(): void
  300. {
  301. Configure::write('TestApp.routes', function ($builder): void {
  302. $builder->connect(
  303. new Route('/unique-path', [], ['_name' => '_aRoute'])
  304. );
  305. $builder->connect(
  306. new Route('/unique-path', [], ['_name' => '_bRoute'])
  307. );
  308. $builder->connect(
  309. new Route('/blog', ['_method' => 'GET'], ['_name' => 'blog-get'])
  310. );
  311. $builder->connect(
  312. new Route('/blog', [], ['_name' => 'blog-all'])
  313. );
  314. $builder->connect(
  315. new Route('/events', ['_method' => ['POST', 'PUT']], ['_name' => 'events-post'])
  316. );
  317. $builder->connect(
  318. new Route('/events', ['_method' => 'GET'], ['_name' => 'events-get'])
  319. );
  320. });
  321. $this->exec('routes');
  322. $this->assertExitCode(CommandInterface::CODE_SUCCESS);
  323. $this->assertOutputContainsRow([
  324. '<info>Route name</info>',
  325. '<info>URI template</info>',
  326. '<info>Plugin</info>',
  327. '<info>Prefix</info>',
  328. '<info>Controller</info>',
  329. '<info>Action</info>',
  330. '<info>Valid Action</info>',
  331. '<info>Method(s)</info>',
  332. ]);
  333. $this->assertOutputContainsRow([
  334. '_aRoute',
  335. '/unique-path',
  336. '',
  337. '',
  338. '',
  339. '',
  340. '',
  341. ]);
  342. $this->assertOutputContainsRow([
  343. '_bRoute',
  344. '/unique-path',
  345. '',
  346. '',
  347. '',
  348. '',
  349. '',
  350. ]);
  351. $this->assertOutputContainsRow([
  352. 'blog-get',
  353. '/blog',
  354. '',
  355. '',
  356. '',
  357. '',
  358. '',
  359. ]);
  360. $this->assertOutputContainsRow([
  361. 'blog-all',
  362. '/blog',
  363. '',
  364. '',
  365. '',
  366. '',
  367. '',
  368. ]);
  369. }
  370. }