DispatcherTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. <?php
  2. /**
  3. * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  4. * Copyright (c) Cake Software Foundation, Inc. (http://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. (http://cakefoundation.org)
  10. * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  11. * @since 1.2.0
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. namespace Cake\Test\TestCase\Routing;
  15. use Cake\Controller\Controller;
  16. use Cake\Core\App;
  17. use Cake\Core\Configure;
  18. use Cake\Core\Plugin;
  19. use Cake\Event\Event;
  20. use Cake\Network\Request;
  21. use Cake\Network\Response;
  22. use Cake\Network\Session;
  23. use Cake\Routing\Dispatcher;
  24. use Cake\Routing\Filter\ControllerFactoryFilter;
  25. use Cake\Routing\Router;
  26. use Cake\TestSuite\TestCase;
  27. use Cake\Utility\Inflector;
  28. /**
  29. * A testing stub that doesn't send headers.
  30. */
  31. class DispatcherMockResponse extends Response
  32. {
  33. protected function _sendHeader($name, $value = null)
  34. {
  35. return $name . ' ' . $value;
  36. }
  37. }
  38. /**
  39. * TestDispatcher class
  40. */
  41. class TestDispatcher extends Dispatcher
  42. {
  43. /**
  44. * Controller instance, made publicly available for testing
  45. *
  46. * @var Controller
  47. */
  48. public $controller;
  49. /**
  50. * invoke method
  51. *
  52. * @param \Cake\Controller\Controller $controller
  53. * @return \Cake\Network\Response $response
  54. */
  55. protected function _invoke(Controller $controller)
  56. {
  57. $this->controller = $controller;
  58. return parent::_invoke($controller);
  59. }
  60. }
  61. /**
  62. * MyPluginAppController class
  63. *
  64. */
  65. class MyPluginAppController extends Controller
  66. {
  67. }
  68. interface DispatcherTestInterfaceController
  69. {
  70. public function index();
  71. }
  72. /**
  73. * MyPluginController class
  74. *
  75. */
  76. class MyPluginController extends MyPluginAppController
  77. {
  78. /**
  79. * name property
  80. *
  81. * @var string
  82. */
  83. public $name = 'MyPlugin';
  84. /**
  85. * index method
  86. *
  87. * @return void
  88. */
  89. public function index()
  90. {
  91. return true;
  92. }
  93. /**
  94. * add method
  95. *
  96. * @return void
  97. */
  98. public function add()
  99. {
  100. return true;
  101. }
  102. /**
  103. * admin_add method
  104. *
  105. * @param mixed $id
  106. * @return void
  107. */
  108. public function admin_add($id = null)
  109. {
  110. return $id;
  111. }
  112. }
  113. /**
  114. * OtherPagesController class
  115. *
  116. */
  117. class OtherPagesController extends MyPluginAppController
  118. {
  119. /**
  120. * name property
  121. *
  122. * @var string
  123. */
  124. public $name = 'OtherPages';
  125. /**
  126. * display method
  127. *
  128. * @param string $page
  129. * @return void
  130. */
  131. public function display($page = null)
  132. {
  133. return $page;
  134. }
  135. /**
  136. * index method
  137. *
  138. * @return void
  139. */
  140. public function index()
  141. {
  142. return true;
  143. }
  144. }
  145. /**
  146. * ArticlesTestAppController class
  147. *
  148. */
  149. class ArticlesTestAppController extends Controller
  150. {
  151. }
  152. /**
  153. * ArticlesTestController class
  154. *
  155. */
  156. class ArticlesTestController extends ArticlesTestAppController
  157. {
  158. /**
  159. * name property
  160. *
  161. * @var string
  162. */
  163. public $name = 'ArticlesTest';
  164. /**
  165. * admin_index method
  166. *
  167. * @return void
  168. */
  169. public function admin_index()
  170. {
  171. return true;
  172. }
  173. /**
  174. * fake index method.
  175. *
  176. * @return void
  177. */
  178. public function index()
  179. {
  180. return true;
  181. }
  182. }
  183. /**
  184. * DispatcherTest class
  185. *
  186. */
  187. class DispatcherTest extends TestCase
  188. {
  189. /**
  190. * setUp method
  191. *
  192. * @return void
  193. */
  194. public function setUp()
  195. {
  196. parent::setUp();
  197. $_GET = [];
  198. Configure::write('App.base', false);
  199. Configure::write('App.baseUrl', false);
  200. Configure::write('App.dir', 'app');
  201. Configure::write('App.webroot', 'webroot');
  202. Configure::write('App.namespace', 'TestApp');
  203. $this->dispatcher = new TestDispatcher();
  204. $this->dispatcher->addFilter(new ControllerFactoryFilter());
  205. }
  206. /**
  207. * tearDown method
  208. *
  209. * @return void
  210. */
  211. public function tearDown()
  212. {
  213. parent::tearDown();
  214. Plugin::unload();
  215. }
  216. /**
  217. * testMissingController method
  218. *
  219. * @expectedException \Cake\Routing\Exception\MissingControllerException
  220. * @expectedExceptionMessage Controller class SomeController could not be found.
  221. * @return void
  222. */
  223. public function testMissingController()
  224. {
  225. $request = new Request([
  226. 'url' => 'some_controller/home',
  227. 'params' => [
  228. 'controller' => 'SomeController',
  229. 'action' => 'home',
  230. ]
  231. ]);
  232. $response = $this->getMock('Cake\Network\Response');
  233. $this->dispatcher->dispatch($request, $response, ['return' => 1]);
  234. }
  235. /**
  236. * testMissingControllerInterface method
  237. *
  238. * @expectedException \Cake\Routing\Exception\MissingControllerException
  239. * @expectedExceptionMessage Controller class DispatcherTestInterface could not be found.
  240. * @return void
  241. */
  242. public function testMissingControllerInterface()
  243. {
  244. $request = new Request([
  245. 'url' => 'dispatcher_test_interface/index',
  246. 'params' => [
  247. 'controller' => 'DispatcherTestInterface',
  248. 'action' => 'index',
  249. ]
  250. ]);
  251. $url = new Request('dispatcher_test_interface/index');
  252. $response = $this->getMock('Cake\Network\Response');
  253. $this->dispatcher->dispatch($request, $response, ['return' => 1]);
  254. }
  255. /**
  256. * testMissingControllerInterface method
  257. *
  258. * @expectedException \Cake\Routing\Exception\MissingControllerException
  259. * @expectedExceptionMessage Controller class Abstract could not be found.
  260. * @return void
  261. */
  262. public function testMissingControllerAbstract()
  263. {
  264. $request = new Request([
  265. 'url' => 'abstract/index',
  266. 'params' => [
  267. 'controller' => 'Abstract',
  268. 'action' => 'index',
  269. ]
  270. ]);
  271. $response = $this->getMock('Cake\Network\Response');
  272. $this->dispatcher->dispatch($request, $response, ['return' => 1]);
  273. }
  274. /**
  275. * testDispatch method
  276. *
  277. * @return void
  278. */
  279. public function testDispatchBasic()
  280. {
  281. $url = new Request([
  282. 'url' => 'pages/home',
  283. 'params' => [
  284. 'controller' => 'Pages',
  285. 'action' => 'display',
  286. 'pass' => ['extract'],
  287. 'return' => 1
  288. ]
  289. ]);
  290. $response = $this->getMock('Cake\Network\Response');
  291. $this->dispatcher->dispatch($url, $response);
  292. $expected = 'Pages';
  293. $this->assertEquals($expected, $this->dispatcher->controller->name);
  294. }
  295. /**
  296. * Test that Dispatcher handles actions that return response objects.
  297. *
  298. * @return void
  299. */
  300. public function testDispatchActionReturnsResponse()
  301. {
  302. $request = new Request([
  303. 'url' => 'some_pages/responseGenerator',
  304. 'params' => [
  305. 'controller' => 'SomePages',
  306. 'action' => 'responseGenerator',
  307. 'pass' => []
  308. ]
  309. ]);
  310. $response = $this->getMock('Cake\Network\Response', ['_sendHeader']);
  311. ob_start();
  312. $this->dispatcher->dispatch($request, $response);
  313. $result = ob_get_clean();
  314. $this->assertEquals('new response', $result);
  315. }
  316. /**
  317. * testPrefixDispatch method
  318. *
  319. * @return void
  320. */
  321. public function testPrefixDispatch()
  322. {
  323. $request = new Request([
  324. 'url' => 'admin/posts/index',
  325. 'params' => [
  326. 'prefix' => 'Admin',
  327. 'controller' => 'Posts',
  328. 'action' => 'index',
  329. 'pass' => [],
  330. 'return' => 1
  331. ]
  332. ]);
  333. $response = $this->getMock('Cake\Network\Response');
  334. $this->dispatcher->dispatch($request, $response);
  335. $this->assertInstanceOf(
  336. 'TestApp\Controller\Admin\PostsController',
  337. $this->dispatcher->controller
  338. );
  339. $expected = '/admin/posts/index';
  340. $this->assertSame($expected, $request->here);
  341. }
  342. /**
  343. * test prefix dispatching in a plugin.
  344. *
  345. * @return void
  346. */
  347. public function testPrefixDispatchPlugin()
  348. {
  349. Plugin::load('TestPlugin');
  350. $request = new Request([
  351. 'url' => 'admin/test_plugin/comments/index',
  352. 'params' => [
  353. 'plugin' => 'TestPlugin',
  354. 'prefix' => 'Admin',
  355. 'controller' => 'Comments',
  356. 'action' => 'index',
  357. 'pass' => [],
  358. 'return' => 1
  359. ]
  360. ]);
  361. $response = $this->getMock('Cake\Network\Response');
  362. $this->dispatcher->dispatch($request, $response);
  363. $this->assertInstanceOf(
  364. 'TestPlugin\Controller\Admin\CommentsController',
  365. $this->dispatcher->controller
  366. );
  367. }
  368. /**
  369. * Test dispatcher filters being called.
  370. *
  371. * @return void
  372. */
  373. public function testDispatcherFilter()
  374. {
  375. $filter = $this->getMock(
  376. 'Cake\Routing\DispatcherFilter',
  377. ['beforeDispatch', 'afterDispatch']
  378. );
  379. $filter->expects($this->at(0))
  380. ->method('beforeDispatch');
  381. $filter->expects($this->at(1))
  382. ->method('afterDispatch');
  383. $this->dispatcher->addFilter($filter);
  384. $request = new Request([
  385. 'url' => '/',
  386. 'params' => [
  387. 'controller' => 'pages',
  388. 'action' => 'display',
  389. 'home',
  390. 'pass' => []
  391. ]
  392. ]);
  393. $response = $this->getMock('Cake\Network\Response', ['send']);
  394. $this->dispatcher->dispatch($request, $response);
  395. }
  396. /**
  397. * Test dispatcher filters being called and changing the response.
  398. *
  399. * @return void
  400. */
  401. public function testBeforeDispatchAbortDispatch()
  402. {
  403. $response = $this->getMock('Cake\Network\Response', ['send']);
  404. $response->expects($this->once())
  405. ->method('send');
  406. $filter = $this->getMock(
  407. 'Cake\Routing\DispatcherFilter',
  408. ['beforeDispatch', 'afterDispatch']
  409. );
  410. $filter->expects($this->once())
  411. ->method('beforeDispatch')
  412. ->will($this->returnValue($response));
  413. $filter->expects($this->never())
  414. ->method('afterDispatch');
  415. $request = new Request();
  416. $res = new Response();
  417. $this->dispatcher->addFilter($filter);
  418. $this->dispatcher->dispatch($request, $res);
  419. }
  420. /**
  421. * Test dispatcher filters being called and changing the response.
  422. *
  423. * @return void
  424. */
  425. public function testAfterDispatchReplaceResponse()
  426. {
  427. $response = $this->getMock('Cake\Network\Response', ['_sendHeader', 'send']);
  428. $response->expects($this->once())
  429. ->method('send');
  430. $filter = $this->getMock(
  431. 'Cake\Routing\DispatcherFilter',
  432. ['beforeDispatch', 'afterDispatch']
  433. );
  434. $filter->expects($this->once())
  435. ->method('afterDispatch')
  436. ->will($this->returnValue($response));
  437. $request = new Request([
  438. 'url' => '/posts',
  439. 'params' => [
  440. 'plugin' => null,
  441. 'controller' => 'Posts',
  442. 'action' => 'index',
  443. 'pass' => [],
  444. ],
  445. 'session' => new Session
  446. ]);
  447. $this->dispatcher->addFilter($filter);
  448. $this->dispatcher->dispatch($request, $response);
  449. }
  450. }