DispatcherTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * Redistributions of files must retain the above copyright notice
  8. *
  9. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  10. * @link https://cakephp.org CakePHP(tm) Project
  11. * @since 1.2.0
  12. * @license https://opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Cake\Test\TestCase\Routing;
  15. use Cake\Core\Configure;
  16. use Cake\Core\Plugin;
  17. use Cake\Http\Response;
  18. use Cake\Http\ServerRequest;
  19. use Cake\Network\Session;
  20. use Cake\Routing\Dispatcher;
  21. use Cake\Routing\Filter\ControllerFactoryFilter;
  22. use Cake\TestSuite\TestCase;
  23. /**
  24. * DispatcherTest class
  25. */
  26. class DispatcherTest extends TestCase
  27. {
  28. /**
  29. * setUp method
  30. *
  31. * @return void
  32. */
  33. public function setUp()
  34. {
  35. parent::setUp();
  36. $_GET = [];
  37. Configure::write('App.base', false);
  38. Configure::write('App.baseUrl', false);
  39. Configure::write('App.dir', 'app');
  40. Configure::write('App.webroot', 'webroot');
  41. static::setAppNamespace();
  42. $this->dispatcher = new Dispatcher();
  43. $this->dispatcher->addFilter(new ControllerFactoryFilter());
  44. }
  45. /**
  46. * tearDown method
  47. *
  48. * @return void
  49. */
  50. public function tearDown()
  51. {
  52. parent::tearDown();
  53. Plugin::unload();
  54. }
  55. /**
  56. * testMissingController method
  57. *
  58. * @return void
  59. */
  60. public function testMissingController()
  61. {
  62. $this->expectException(\Cake\Routing\Exception\MissingControllerException::class);
  63. $this->expectExceptionMessage('Controller class SomeController could not be found.');
  64. $request = new ServerRequest([
  65. 'url' => 'some_controller/home',
  66. 'params' => [
  67. 'controller' => 'SomeController',
  68. 'action' => 'home',
  69. ]
  70. ]);
  71. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  72. $this->dispatcher->dispatch($request, $response, ['return' => 1]);
  73. }
  74. /**
  75. * testMissingControllerInterface method
  76. *
  77. * @return void
  78. */
  79. public function testMissingControllerInterface()
  80. {
  81. $this->expectException(\Cake\Routing\Exception\MissingControllerException::class);
  82. $this->expectExceptionMessage('Controller class Interface could not be found.');
  83. $request = new ServerRequest([
  84. 'url' => 'interface/index',
  85. 'params' => [
  86. 'controller' => 'Interface',
  87. 'action' => 'index',
  88. ]
  89. ]);
  90. $url = new ServerRequest('dispatcher_test_interface/index');
  91. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  92. $this->dispatcher->dispatch($request, $response, ['return' => 1]);
  93. }
  94. /**
  95. * testMissingControllerInterface method
  96. *
  97. * @return void
  98. */
  99. public function testMissingControllerAbstract()
  100. {
  101. $this->expectException(\Cake\Routing\Exception\MissingControllerException::class);
  102. $this->expectExceptionMessage('Controller class Abstract could not be found.');
  103. $request = new ServerRequest([
  104. 'url' => 'abstract/index',
  105. 'params' => [
  106. 'controller' => 'Abstract',
  107. 'action' => 'index',
  108. ]
  109. ]);
  110. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  111. $this->dispatcher->dispatch($request, $response, ['return' => 1]);
  112. }
  113. /**
  114. * Test that lowercase controller names result in missing controller errors.
  115. *
  116. * In case-insensitive file systems, lowercase controller names will kind of work.
  117. * This causes annoying deployment issues for lots of folks.
  118. *
  119. * @return void
  120. */
  121. public function testMissingControllerLowercase()
  122. {
  123. $this->expectException(\Cake\Routing\Exception\MissingControllerException::class);
  124. $this->expectExceptionMessage('Controller class somepages could not be found.');
  125. $request = new ServerRequest([
  126. 'url' => 'pages/home',
  127. 'params' => [
  128. 'controller' => 'somepages',
  129. 'action' => 'display',
  130. 'pass' => ['home'],
  131. ]
  132. ]);
  133. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  134. $this->dispatcher->dispatch($request, $response, ['return' => 1]);
  135. }
  136. /**
  137. * testDispatch method
  138. *
  139. * @return void
  140. */
  141. public function testDispatchBasic()
  142. {
  143. $url = new ServerRequest([
  144. 'url' => 'pages/home',
  145. 'params' => [
  146. 'controller' => 'Pages',
  147. 'action' => 'display',
  148. 'pass' => ['extract'],
  149. ]
  150. ]);
  151. $response = $this->getMockBuilder('Cake\Http\Response')
  152. ->setMethods(['send'])
  153. ->getMock();
  154. $response->expects($this->once())
  155. ->method('send');
  156. $result = $this->dispatcher->dispatch($url, $response);
  157. $this->assertNull($result);
  158. }
  159. /**
  160. * Test that Dispatcher handles actions that return response objects.
  161. *
  162. * @return void
  163. */
  164. public function testDispatchActionReturnsResponse()
  165. {
  166. $request = new ServerRequest([
  167. 'url' => 'some_pages/responseGenerator',
  168. 'params' => [
  169. 'controller' => 'SomePages',
  170. 'action' => 'responseGenerator',
  171. 'pass' => []
  172. ]
  173. ]);
  174. $response = $this->getMockBuilder('Cake\Http\Response')
  175. ->setMethods(['_sendHeader'])
  176. ->getMock();
  177. ob_start();
  178. $this->dispatcher->dispatch($request, $response);
  179. $result = ob_get_clean();
  180. $this->assertEquals('new response', $result);
  181. }
  182. /**
  183. * test forbidden controller names.
  184. *
  185. * @return void
  186. */
  187. public function testDispatchBadPluginName()
  188. {
  189. $this->expectException(\Cake\Routing\Exception\MissingControllerException::class);
  190. $this->expectExceptionMessage('Controller class TestPlugin.Tests could not be found.');
  191. Plugin::load('TestPlugin');
  192. $request = new ServerRequest([
  193. 'url' => 'TestPlugin.Tests/index',
  194. 'params' => [
  195. 'plugin' => '',
  196. 'controller' => 'TestPlugin.Tests',
  197. 'action' => 'index',
  198. 'pass' => [],
  199. 'return' => 1
  200. ]
  201. ]);
  202. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  203. $this->dispatcher->dispatch($request, $response);
  204. }
  205. /**
  206. * test forbidden controller names.
  207. *
  208. * @return void
  209. */
  210. public function testDispatchBadName()
  211. {
  212. $this->expectException(\Cake\Routing\Exception\MissingControllerException::class);
  213. $this->expectExceptionMessage('Controller class TestApp\Controller\PostsController could not be found.');
  214. $request = new ServerRequest([
  215. 'url' => 'TestApp%5CController%5CPostsController/index',
  216. 'params' => [
  217. 'plugin' => '',
  218. 'controller' => 'TestApp\Controller\PostsController',
  219. 'action' => 'index',
  220. 'pass' => [],
  221. 'return' => 1
  222. ]
  223. ]);
  224. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  225. $this->dispatcher->dispatch($request, $response);
  226. }
  227. /**
  228. * Test dispatcher filters being called.
  229. *
  230. * @return void
  231. */
  232. public function testDispatcherFilter()
  233. {
  234. $filter = $this->getMockBuilder('Cake\Routing\DispatcherFilter')
  235. ->setMethods(['beforeDispatch', 'afterDispatch'])
  236. ->getMock();
  237. $filter->expects($this->at(0))
  238. ->method('beforeDispatch');
  239. $filter->expects($this->at(1))
  240. ->method('afterDispatch');
  241. $this->dispatcher->addFilter($filter);
  242. $request = new ServerRequest([
  243. 'url' => '/',
  244. 'params' => [
  245. 'controller' => 'Pages',
  246. 'action' => 'display',
  247. 'home',
  248. 'pass' => []
  249. ]
  250. ]);
  251. $response = $this->getMockBuilder('Cake\Http\Response')
  252. ->setMethods(['send'])
  253. ->getMock();
  254. $this->dispatcher->dispatch($request, $response);
  255. }
  256. /**
  257. * Test dispatcher filters being called and changing the response.
  258. *
  259. * @return void
  260. */
  261. public function testBeforeDispatchAbortDispatch()
  262. {
  263. $response = $this->getMockBuilder('Cake\Http\Response')
  264. ->setMethods(['send'])
  265. ->getMock();
  266. $response->expects($this->once())
  267. ->method('send');
  268. $filter = $this->getMockBuilder('Cake\Routing\DispatcherFilter')
  269. ->setMethods(['beforeDispatch', 'afterDispatch'])
  270. ->getMock();
  271. $filter->expects($this->once())
  272. ->method('beforeDispatch')
  273. ->will($this->returnValue($response));
  274. $filter->expects($this->never())
  275. ->method('afterDispatch');
  276. $request = new ServerRequest([
  277. 'url' => '/',
  278. 'params' => [
  279. 'controller' => 'Pages',
  280. 'action' => 'display',
  281. 'home',
  282. 'pass' => []
  283. ]
  284. ]);
  285. $res = new Response();
  286. $this->dispatcher->addFilter($filter);
  287. $this->dispatcher->dispatch($request, $res);
  288. }
  289. /**
  290. * Test dispatcher filters being called and changing the response.
  291. *
  292. * @return void
  293. */
  294. public function testAfterDispatchReplaceResponse()
  295. {
  296. $response = $this->getMockBuilder('Cake\Http\Response')
  297. ->setMethods(['_sendHeader', 'send'])
  298. ->getMock();
  299. $response->expects($this->once())
  300. ->method('send');
  301. $filter = $this->getMockBuilder('Cake\Routing\DispatcherFilter')
  302. ->setMethods(['beforeDispatch', 'afterDispatch'])
  303. ->getMock();
  304. $filter->expects($this->once())
  305. ->method('afterDispatch')
  306. ->will($this->returnValue($response));
  307. $request = new ServerRequest([
  308. 'url' => '/posts',
  309. 'params' => [
  310. 'plugin' => null,
  311. 'controller' => 'Posts',
  312. 'action' => 'index',
  313. 'pass' => [],
  314. ],
  315. 'session' => new Session
  316. ]);
  317. $this->dispatcher->addFilter($filter);
  318. $this->dispatcher->dispatch($request, $response);
  319. }
  320. }