RoutesCommandTest.php 11 KB

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