DispatcherTest.php 10 KB

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