DispatcherTest.php 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
  1. <?php
  2. /**
  3. * DispatcherTest file
  4. *
  5. * PHP 5
  6. *
  7. * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  8. * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * Redistributions of files must retain the above copyright notice
  12. *
  13. * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  15. * @package Cake.Test.Case.Routing
  16. * @since CakePHP(tm) v 1.2.0.4206
  17. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  18. */
  19. App::uses('Dispatcher', 'Routing');
  20. if (!class_exists('AppController', false)) {
  21. require_once CAKE . 'Test' . DS . 'test_app' . DS . 'Controller' . DS . 'AppController.php';
  22. } elseif (!defined('APP_CONTROLLER_EXISTS')) {
  23. define('APP_CONTROLLER_EXISTS', true);
  24. }
  25. /**
  26. * A testing stub that doesn't send headers.
  27. *
  28. * @package Cake.Test.Case.Routing
  29. */
  30. class DispatcherMockCakeResponse extends CakeResponse {
  31. protected function _sendHeader($name, $value = null) {
  32. return $name . ' ' . $value;
  33. }
  34. }
  35. /**
  36. * TestDispatcher class
  37. *
  38. * @package Cake.Test.Case.Routing
  39. */
  40. class TestDispatcher extends Dispatcher {
  41. /**
  42. * Controller instance, made publicly available for testing
  43. *
  44. * @var Controller
  45. */
  46. public $controller;
  47. /**
  48. * invoke method
  49. *
  50. * @param Controller $controller
  51. * @param CakeRequest $request
  52. * @param CakeResponse $response
  53. * @return void
  54. */
  55. protected function _invoke(Controller $controller, CakeRequest $request, CakeResponse $response) {
  56. $this->controller = $controller;
  57. return parent::_invoke($controller, $request, $response);
  58. }
  59. /**
  60. * Helper function to test single method attaching for dispatcher filters
  61. *
  62. * @param CakeEvent $event
  63. * @return void
  64. */
  65. public function filterTest($event) {
  66. $event->data['request']->params['eventName'] = $event->name();
  67. }
  68. /**
  69. * Helper function to test single method attaching for dispatcher filters
  70. *
  71. * @param CakeEvent
  72. * @return void
  73. */
  74. public function filterTest2($event) {
  75. $event->stopPropagation();
  76. return $event->data['response'];
  77. }
  78. }
  79. /**
  80. * MyPluginAppController class
  81. *
  82. * @package Cake.Test.Case.Routing
  83. */
  84. class MyPluginAppController extends AppController {
  85. }
  86. abstract class DispatcherTestAbstractController extends Controller {
  87. abstract public function index();
  88. }
  89. interface DispatcherTestInterfaceController {
  90. public function index();
  91. }
  92. /**
  93. * MyPluginController class
  94. *
  95. * @package Cake.Test.Case.Routing
  96. */
  97. class MyPluginController extends MyPluginAppController {
  98. /**
  99. * name property
  100. *
  101. * @var string 'MyPlugin'
  102. */
  103. public $name = 'MyPlugin';
  104. /**
  105. * uses property
  106. *
  107. * @var array
  108. */
  109. public $uses = array();
  110. /**
  111. * index method
  112. *
  113. * @return void
  114. */
  115. public function index() {
  116. return true;
  117. }
  118. /**
  119. * add method
  120. *
  121. * @return void
  122. */
  123. public function add() {
  124. return true;
  125. }
  126. /**
  127. * admin_add method
  128. *
  129. * @param mixed $id
  130. * @return void
  131. */
  132. public function admin_add($id = null) {
  133. return $id;
  134. }
  135. }
  136. /**
  137. * SomePagesController class
  138. *
  139. * @package Cake.Test.Case.Routing
  140. */
  141. class SomePagesController extends AppController {
  142. /**
  143. * name property
  144. *
  145. * @var string 'SomePages'
  146. */
  147. public $name = 'SomePages';
  148. /**
  149. * uses property
  150. *
  151. * @var array
  152. */
  153. public $uses = array();
  154. /**
  155. * display method
  156. *
  157. * @param string $page
  158. * @return void
  159. */
  160. public function display($page = null) {
  161. return $page;
  162. }
  163. /**
  164. * index method
  165. *
  166. * @return void
  167. */
  168. public function index() {
  169. return true;
  170. }
  171. /**
  172. * Test method for returning responses.
  173. *
  174. * @return CakeResponse
  175. */
  176. public function responseGenerator() {
  177. return new CakeResponse(array('body' => 'new response'));
  178. }
  179. }
  180. /**
  181. * OtherPagesController class
  182. *
  183. * @package Cake.Test.Case.Routing
  184. */
  185. class OtherPagesController extends MyPluginAppController {
  186. /**
  187. * name property
  188. *
  189. * @var string 'OtherPages'
  190. */
  191. public $name = 'OtherPages';
  192. /**
  193. * uses property
  194. *
  195. * @var array
  196. */
  197. public $uses = array();
  198. /**
  199. * display method
  200. *
  201. * @param string $page
  202. * @return void
  203. */
  204. public function display($page = null) {
  205. return $page;
  206. }
  207. /**
  208. * index method
  209. *
  210. * @return void
  211. */
  212. public function index() {
  213. return true;
  214. }
  215. }
  216. /**
  217. * TestDispatchPagesController class
  218. *
  219. * @package Cake.Test.Case.Routing
  220. */
  221. class TestDispatchPagesController extends AppController {
  222. /**
  223. * name property
  224. *
  225. * @var string 'TestDispatchPages'
  226. */
  227. public $name = 'TestDispatchPages';
  228. /**
  229. * uses property
  230. *
  231. * @var array
  232. */
  233. public $uses = array();
  234. /**
  235. * admin_index method
  236. *
  237. * @return void
  238. */
  239. public function admin_index() {
  240. return true;
  241. }
  242. /**
  243. * camelCased method
  244. *
  245. * @return void
  246. */
  247. public function camelCased() {
  248. return true;
  249. }
  250. }
  251. /**
  252. * ArticlesTestAppController class
  253. *
  254. * @package Cake.Test.Case.Routing
  255. */
  256. class ArticlesTestAppController extends AppController {
  257. }
  258. /**
  259. * ArticlesTestController class
  260. *
  261. * @package Cake.Test.Case.Routing
  262. */
  263. class ArticlesTestController extends ArticlesTestAppController {
  264. /**
  265. * name property
  266. *
  267. * @var string 'ArticlesTest'
  268. */
  269. public $name = 'ArticlesTest';
  270. /**
  271. * uses property
  272. *
  273. * @var array
  274. */
  275. public $uses = array();
  276. /**
  277. * admin_index method
  278. *
  279. * @return void
  280. */
  281. public function admin_index() {
  282. return true;
  283. }
  284. /**
  285. * fake index method.
  286. *
  287. * @return void
  288. */
  289. public function index() {
  290. return true;
  291. }
  292. }
  293. /**
  294. * SomePostsController class
  295. *
  296. * @package Cake.Test.Case.Routing
  297. */
  298. class SomePostsController extends AppController {
  299. /**
  300. * name property
  301. *
  302. * @var string 'SomePosts'
  303. */
  304. public $name = 'SomePosts';
  305. /**
  306. * uses property
  307. *
  308. * @var array
  309. */
  310. public $uses = array();
  311. /**
  312. * autoRender property
  313. *
  314. * @var bool false
  315. */
  316. public $autoRender = false;
  317. /**
  318. * beforeFilter method
  319. *
  320. * @return void
  321. */
  322. public function beforeFilter() {
  323. if ($this->params['action'] == 'index') {
  324. $this->params['action'] = 'view';
  325. } else {
  326. $this->params['action'] = 'change';
  327. }
  328. $this->params['pass'] = array('changed');
  329. }
  330. /**
  331. * index method
  332. *
  333. * @return void
  334. */
  335. public function index() {
  336. return true;
  337. }
  338. /**
  339. * change method
  340. *
  341. * @return void
  342. */
  343. public function change() {
  344. return true;
  345. }
  346. }
  347. /**
  348. * TestCachedPagesController class
  349. *
  350. * @package Cake.Test.Case.Routing
  351. */
  352. class TestCachedPagesController extends Controller {
  353. /**
  354. * name property
  355. *
  356. * @var string 'TestCachedPages'
  357. */
  358. public $name = 'TestCachedPages';
  359. /**
  360. * uses property
  361. *
  362. * @var array
  363. */
  364. public $uses = array();
  365. /**
  366. * helpers property
  367. *
  368. * @var array
  369. */
  370. public $helpers = array('Cache', 'Html');
  371. /**
  372. * cacheAction property
  373. *
  374. * @var array
  375. */
  376. public $cacheAction = array(
  377. 'index' => '+2 sec',
  378. 'test_nocache_tags' => '+2 sec',
  379. 'view' => '+2 sec'
  380. );
  381. /**
  382. * Mock out the response object so it doesn't send headers.
  383. *
  384. * @var string
  385. */
  386. protected $_responseClass = 'DispatcherMockCakeResponse';
  387. /**
  388. * viewPath property
  389. *
  390. * @var string 'posts'
  391. */
  392. public $viewPath = 'Posts';
  393. /**
  394. * index method
  395. *
  396. * @return void
  397. */
  398. public function index() {
  399. $this->render();
  400. }
  401. /**
  402. * test_nocache_tags method
  403. *
  404. * @return void
  405. */
  406. public function test_nocache_tags() {
  407. $this->render();
  408. }
  409. /**
  410. * view method
  411. *
  412. * @return void
  413. */
  414. public function view($id = null) {
  415. $this->render('index');
  416. }
  417. /**
  418. * test cached forms / tests view object being registered
  419. *
  420. * @return void
  421. */
  422. public function cache_form() {
  423. $this->cacheAction = 10;
  424. $this->helpers[] = 'Form';
  425. }
  426. /**
  427. * Test cached views with themes.
  428. */
  429. public function themed() {
  430. $this->cacheAction = 10;
  431. $this->viewClass = 'Theme';
  432. $this->theme = 'TestTheme';
  433. }
  434. }
  435. /**
  436. * TimesheetsController class
  437. *
  438. * @package Cake.Test.Case.Routing
  439. */
  440. class TimesheetsController extends Controller {
  441. /**
  442. * name property
  443. *
  444. * @var string 'Timesheets'
  445. */
  446. public $name = 'Timesheets';
  447. /**
  448. * uses property
  449. *
  450. * @var array
  451. */
  452. public $uses = array();
  453. /**
  454. * index method
  455. *
  456. * @return void
  457. */
  458. public function index() {
  459. return true;
  460. }
  461. }
  462. /**
  463. * DispatcherTest class
  464. *
  465. * @package Cake.Test.Case.Routing
  466. */
  467. class DispatcherTest extends CakeTestCase {
  468. /**
  469. * setUp method
  470. *
  471. * @return void
  472. */
  473. public function setUp() {
  474. $this->_get = $_GET;
  475. $_GET = array();
  476. $this->_post = $_POST;
  477. $this->_files = $_FILES;
  478. $this->_server = $_SERVER;
  479. $this->_app = Configure::read('App');
  480. Configure::write('App.base', false);
  481. Configure::write('App.baseUrl', false);
  482. Configure::write('App.dir', 'app');
  483. Configure::write('App.webroot', 'webroot');
  484. $this->_cache = Configure::read('Cache');
  485. Configure::write('Cache.disable', true);
  486. $this->_debug = Configure::read('debug');
  487. App::build();
  488. App::objects('plugin', null, false);
  489. }
  490. /**
  491. * tearDown method
  492. *
  493. * @return void
  494. */
  495. public function tearDown() {
  496. $_GET = $this->_get;
  497. $_POST = $this->_post;
  498. $_FILES = $this->_files;
  499. $_SERVER = $this->_server;
  500. App::build();
  501. CakePlugin::unload();
  502. Configure::write('App', $this->_app);
  503. Configure::write('Cache', $this->_cache);
  504. Configure::write('debug', $this->_debug);
  505. Configure::write('Dispatcher.filters', array());
  506. }
  507. /**
  508. * testParseParamsWithoutZerosAndEmptyPost method
  509. *
  510. * @return void
  511. */
  512. public function testParseParamsWithoutZerosAndEmptyPost() {
  513. $Dispatcher = new Dispatcher();
  514. $request = new CakeRequest("/testcontroller/testaction/params1/params2/params3");
  515. $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $request));
  516. $Dispatcher->parseParams($event);
  517. $this->assertSame($request['controller'], 'testcontroller');
  518. $this->assertSame($request['action'], 'testaction');
  519. $this->assertSame($request['pass'][0], 'params1');
  520. $this->assertSame($request['pass'][1], 'params2');
  521. $this->assertSame($request['pass'][2], 'params3');
  522. $this->assertFalse(!empty($request['form']));
  523. }
  524. /**
  525. * testParseParamsReturnsPostedData method
  526. *
  527. * @return void
  528. */
  529. public function testParseParamsReturnsPostedData() {
  530. $_POST['testdata'] = "My Posted Content";
  531. $Dispatcher = new Dispatcher();
  532. $request = new CakeRequest("/");
  533. $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $request));
  534. $Dispatcher->parseParams($event);
  535. $Dispatcher->parseParams($event);
  536. $this->assertEquals("My Posted Content", $request['data']['testdata']);
  537. }
  538. /**
  539. * testParseParamsWithSingleZero method
  540. *
  541. * @return void
  542. */
  543. public function testParseParamsWithSingleZero() {
  544. $Dispatcher = new Dispatcher();
  545. $test = new CakeRequest("/testcontroller/testaction/1/0/23");
  546. $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $test));
  547. $Dispatcher->parseParams($event);
  548. $this->assertSame($test['controller'], 'testcontroller');
  549. $this->assertSame($test['action'], 'testaction');
  550. $this->assertSame($test['pass'][0], '1');
  551. $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][1]);
  552. $this->assertSame($test['pass'][2], '23');
  553. }
  554. /**
  555. * testParseParamsWithManySingleZeros method
  556. *
  557. * @return void
  558. */
  559. public function testParseParamsWithManySingleZeros() {
  560. $Dispatcher = new Dispatcher();
  561. $test = new CakeRequest("/testcontroller/testaction/0/0/0/0/0/0");
  562. $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $test));
  563. $Dispatcher->parseParams($event);
  564. $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][0]);
  565. $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][1]);
  566. $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][2]);
  567. $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][3]);
  568. $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][4]);
  569. $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][5]);
  570. }
  571. /**
  572. * testParseParamsWithManyZerosInEachSectionOfUrl method
  573. *
  574. * @return void
  575. */
  576. public function testParseParamsWithManyZerosInEachSectionOfUrl() {
  577. $Dispatcher = new Dispatcher();
  578. $test = new CakeRequest("/testcontroller/testaction/000/0000/00000/000000/000000/0000000");
  579. $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $test));
  580. $Dispatcher->parseParams($event);
  581. $this->assertRegExp('/\\A(?:000)\\z/', $test['pass'][0]);
  582. $this->assertRegExp('/\\A(?:0000)\\z/', $test['pass'][1]);
  583. $this->assertRegExp('/\\A(?:00000)\\z/', $test['pass'][2]);
  584. $this->assertRegExp('/\\A(?:000000)\\z/', $test['pass'][3]);
  585. $this->assertRegExp('/\\A(?:000000)\\z/', $test['pass'][4]);
  586. $this->assertRegExp('/\\A(?:0000000)\\z/', $test['pass'][5]);
  587. }
  588. /**
  589. * testParseParamsWithMixedOneToManyZerosInEachSectionOfUrl method
  590. *
  591. * @return void
  592. */
  593. public function testParseParamsWithMixedOneToManyZerosInEachSectionOfUrl() {
  594. $Dispatcher = new Dispatcher();
  595. $test = new CakeRequest("/testcontroller/testaction/01/0403/04010/000002/000030/0000400");
  596. $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $test));
  597. $Dispatcher->parseParams($event);
  598. $this->assertRegExp('/\\A(?:01)\\z/', $test['pass'][0]);
  599. $this->assertRegExp('/\\A(?:0403)\\z/', $test['pass'][1]);
  600. $this->assertRegExp('/\\A(?:04010)\\z/', $test['pass'][2]);
  601. $this->assertRegExp('/\\A(?:000002)\\z/', $test['pass'][3]);
  602. $this->assertRegExp('/\\A(?:000030)\\z/', $test['pass'][4]);
  603. $this->assertRegExp('/\\A(?:0000400)\\z/', $test['pass'][5]);
  604. }
  605. /**
  606. * testQueryStringOnRoot method
  607. *
  608. * @return void
  609. */
  610. public function testQueryStringOnRoot() {
  611. Router::reload();
  612. Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
  613. Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
  614. Router::connect('/:controller/:action/*');
  615. $_GET = array('coffee' => 'life', 'sleep' => 'sissies');
  616. $Dispatcher = new Dispatcher();
  617. $request = new CakeRequest('posts/home/?coffee=life&sleep=sissies');
  618. $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $request));
  619. $Dispatcher->parseParams($event);
  620. $this->assertRegExp('/posts/', $request['controller']);
  621. $this->assertRegExp('/home/', $request['action']);
  622. $this->assertTrue(isset($request['url']['sleep']));
  623. $this->assertTrue(isset($request['url']['coffee']));
  624. $Dispatcher = new Dispatcher();
  625. $request = new CakeRequest('/?coffee=life&sleep=sissy');
  626. $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $request));
  627. $Dispatcher->parseParams($event);
  628. $this->assertRegExp('/pages/', $request['controller']);
  629. $this->assertRegExp('/display/', $request['action']);
  630. $this->assertTrue(isset($request['url']['sleep']));
  631. $this->assertTrue(isset($request['url']['coffee']));
  632. $this->assertEquals('life', $request['url']['coffee']);
  633. }
  634. /**
  635. * testMissingController method
  636. *
  637. * @expectedException MissingControllerException
  638. * @expectedExceptionMessage Controller class SomeControllerController could not be found.
  639. * @return void
  640. */
  641. public function testMissingController() {
  642. Router::connect('/:controller/:action/*');
  643. $Dispatcher = new TestDispatcher();
  644. Configure::write('App.baseUrl', '/index.php');
  645. $url = new CakeRequest('some_controller/home/param:value/param2:value2');
  646. $response = $this->getMock('CakeResponse');
  647. $Dispatcher->dispatch($url, $response, array('return' => 1));
  648. }
  649. /**
  650. * testMissingControllerInterface method
  651. *
  652. * @expectedException MissingControllerException
  653. * @expectedExceptionMessage Controller class DispatcherTestInterfaceController could not be found.
  654. * @return void
  655. */
  656. public function testMissingControllerInterface() {
  657. Router::connect('/:controller/:action/*');
  658. $Dispatcher = new TestDispatcher();
  659. Configure::write('App.baseUrl', '/index.php');
  660. $url = new CakeRequest('dispatcher_test_interface/index');
  661. $response = $this->getMock('CakeResponse');
  662. $Dispatcher->dispatch($url, $response, array('return' => 1));
  663. }
  664. /**
  665. * testMissingControllerInterface method
  666. *
  667. * @expectedException MissingControllerException
  668. * @expectedExceptionMessage Controller class DispatcherTestAbstractController could not be found.
  669. * @return void
  670. */
  671. public function testMissingControllerAbstract() {
  672. Router::connect('/:controller/:action/*');
  673. $Dispatcher = new TestDispatcher();
  674. Configure::write('App.baseUrl', '/index.php');
  675. $url = new CakeRequest('dispatcher_test_abstract/index');
  676. $response = $this->getMock('CakeResponse');
  677. $Dispatcher->dispatch($url, $response, array('return' => 1));
  678. }
  679. /**
  680. * testDispatch method
  681. *
  682. * @return void
  683. */
  684. public function testDispatchBasic() {
  685. App::build(array(
  686. 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS)
  687. ));
  688. $Dispatcher = new TestDispatcher();
  689. Configure::write('App.baseUrl', '/index.php');
  690. $url = new CakeRequest('pages/home/param:value/param2:value2');
  691. $response = $this->getMock('CakeResponse');
  692. $Dispatcher->dispatch($url, $response, array('return' => 1));
  693. $expected = 'Pages';
  694. $this->assertEquals($expected, $Dispatcher->controller->name);
  695. $expected = array('0' => 'home', 'param' => 'value', 'param2' => 'value2');
  696. $this->assertSame($expected, $Dispatcher->controller->passedArgs);
  697. Configure::write('App.baseUrl', '/pages/index.php');
  698. $url = new CakeRequest('pages/home');
  699. $Dispatcher->dispatch($url, $response, array('return' => 1));
  700. $expected = 'Pages';
  701. $this->assertEquals($expected, $Dispatcher->controller->name);
  702. $url = new CakeRequest('pages/home/');
  703. $Dispatcher->dispatch($url, $response, array('return' => 1));
  704. $this->assertNull($Dispatcher->controller->plugin);
  705. $expected = 'Pages';
  706. $this->assertEquals($expected, $Dispatcher->controller->name);
  707. unset($Dispatcher);
  708. require CAKE . 'Config' . DS . 'routes.php';
  709. $Dispatcher = new TestDispatcher();
  710. Configure::write('App.baseUrl', '/timesheets/index.php');
  711. $url = new CakeRequest('timesheets');
  712. $Dispatcher->dispatch($url, $response, array('return' => 1));
  713. $expected = 'Timesheets';
  714. $this->assertEquals($expected, $Dispatcher->controller->name);
  715. $url = new CakeRequest('timesheets/');
  716. $Dispatcher->dispatch($url, $response, array('return' => 1));
  717. $this->assertEquals('Timesheets', $Dispatcher->controller->name);
  718. $this->assertEquals('/timesheets/index.php', $url->base);
  719. $url = new CakeRequest('test_dispatch_pages/camelCased');
  720. $Dispatcher->dispatch($url, $response, array('return' => 1));
  721. $this->assertEquals('TestDispatchPages', $Dispatcher->controller->name);
  722. $url = new CakeRequest('test_dispatch_pages/camelCased/something. .');
  723. $Dispatcher->dispatch($url, $response, array('return' => 1));
  724. $this->assertEquals('something. .', $Dispatcher->controller->params['pass'][0], 'Period was chopped off. %s');
  725. }
  726. /**
  727. * Test that Dispatcher handles actions that return response objects.
  728. *
  729. * @return void
  730. */
  731. public function testDispatchActionReturnsResponse() {
  732. Router::connect('/:controller/:action');
  733. $Dispatcher = new Dispatcher();
  734. $request = new CakeRequest('some_pages/responseGenerator');
  735. $response = $this->getMock('CakeResponse', array('_sendHeader'));
  736. ob_start();
  737. $Dispatcher->dispatch($request, $response);
  738. $result = ob_get_clean();
  739. $this->assertEquals('new response', $result);
  740. }
  741. /**
  742. * testAdminDispatch method
  743. *
  744. * @return void
  745. */
  746. public function testAdminDispatch() {
  747. $_POST = array();
  748. $Dispatcher = new TestDispatcher();
  749. Configure::write('Routing.prefixes', array('admin'));
  750. Configure::write('App.baseUrl','/cake/repo/branches/1.2.x.x/index.php');
  751. $url = new CakeRequest('admin/test_dispatch_pages/index/param:value/param2:value2');
  752. $response = $this->getMock('CakeResponse');
  753. Router::reload();
  754. $Dispatcher->dispatch($url, $response, array('return' => 1));
  755. $this->assertEquals('TestDispatchPages', $Dispatcher->controller->name);
  756. $this->assertSame($Dispatcher->controller->passedArgs, array('param' => 'value', 'param2' => 'value2'));
  757. $this->assertTrue($Dispatcher->controller->params['admin']);
  758. $expected = '/cake/repo/branches/1.2.x.x/index.php/admin/test_dispatch_pages/index/param:value/param2:value2';
  759. $this->assertSame($expected, $Dispatcher->controller->here);
  760. $expected = '/cake/repo/branches/1.2.x.x/index.php';
  761. $this->assertSame($expected, $Dispatcher->controller->base);
  762. }
  763. /**
  764. * testPluginDispatch method
  765. *
  766. * @return void
  767. */
  768. public function testPluginDispatch() {
  769. $_POST = array();
  770. Router::reload();
  771. $Dispatcher = new TestDispatcher();
  772. Router::connect(
  773. '/my_plugin/:controller/*',
  774. array('plugin' => 'my_plugin', 'controller' => 'pages', 'action' => 'display')
  775. );
  776. $url = new CakeRequest('my_plugin/some_pages/home/param:value/param2:value2');
  777. $response = $this->getMock('CakeResponse');
  778. $Dispatcher->dispatch($url, $response, array('return' => 1));
  779. $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $url));
  780. $Dispatcher->parseParams($event);
  781. $expected = array(
  782. 'pass' => array('home'),
  783. 'named' => array('param' => 'value', 'param2' => 'value2'), 'plugin' => 'my_plugin',
  784. 'controller' => 'some_pages', 'action' => 'display'
  785. );
  786. foreach ($expected as $key => $value) {
  787. $this->assertEquals($value, $url[$key], 'Value mismatch ' . $key . ' %');
  788. }
  789. $this->assertSame($Dispatcher->controller->plugin, 'MyPlugin');
  790. $this->assertSame($Dispatcher->controller->name, 'SomePages');
  791. $this->assertSame($Dispatcher->controller->params['controller'], 'some_pages');
  792. $this->assertSame($Dispatcher->controller->passedArgs, array('0' => 'home', 'param' => 'value', 'param2' => 'value2'));
  793. }
  794. /**
  795. * testAutomaticPluginDispatch method
  796. *
  797. * @return void
  798. */
  799. public function testAutomaticPluginDispatch() {
  800. $_POST = array();
  801. $_SERVER['PHP_SELF'] = '/cake/repo/branches/1.2.x.x/index.php';
  802. Router::reload();
  803. $Dispatcher = new TestDispatcher();
  804. Router::connect(
  805. '/my_plugin/:controller/:action/*',
  806. array('plugin' => 'my_plugin', 'controller' => 'pages', 'action' => 'display')
  807. );
  808. $Dispatcher->base = false;
  809. $url = new CakeRequest('my_plugin/other_pages/index/param:value/param2:value2');
  810. $response = $this->getMock('CakeResponse');
  811. $Dispatcher->dispatch($url, $response, array('return' => 1));
  812. $this->assertSame($Dispatcher->controller->plugin, 'MyPlugin');
  813. $this->assertSame($Dispatcher->controller->name, 'OtherPages');
  814. $this->assertSame($Dispatcher->controller->action, 'index');
  815. $this->assertSame($Dispatcher->controller->passedArgs, array('param' => 'value', 'param2' => 'value2'));
  816. $expected = '/cake/repo/branches/1.2.x.x/my_plugin/other_pages/index/param:value/param2:value2';
  817. $this->assertSame($expected, $url->here);
  818. $expected = '/cake/repo/branches/1.2.x.x';
  819. $this->assertSame($expected, $url->base);
  820. }
  821. /**
  822. * testAutomaticPluginControllerDispatch method
  823. *
  824. * @return void
  825. */
  826. public function testAutomaticPluginControllerDispatch() {
  827. $plugins = App::objects('plugin');
  828. $plugins[] = 'MyPlugin';
  829. $plugins[] = 'ArticlesTest';
  830. CakePlugin::load('MyPlugin', array('path' => '/fake/path'));
  831. Router::reload();
  832. $Dispatcher = new TestDispatcher();
  833. $Dispatcher->base = false;
  834. $url = new CakeRequest('my_plugin/my_plugin/add/param:value/param2:value2');
  835. $response = $this->getMock('CakeResponse');
  836. $Dispatcher->dispatch($url, $response, array('return' => 1));
  837. $this->assertSame($Dispatcher->controller->plugin, 'MyPlugin');
  838. $this->assertSame($Dispatcher->controller->name, 'MyPlugin');
  839. $this->assertSame($Dispatcher->controller->action, 'add');
  840. $this->assertEquals(array('param' => 'value', 'param2' => 'value2'), $Dispatcher->controller->params['named']);
  841. Router::reload();
  842. require CAKE . 'Config' . DS . 'routes.php';
  843. $Dispatcher = new TestDispatcher();
  844. $Dispatcher->base = false;
  845. // Simulates the Route for a real plugin, installed in APP/plugins
  846. Router::connect('/my_plugin/:controller/:action/*', array('plugin' => 'my_plugin'));
  847. $plugin = 'MyPlugin';
  848. $pluginUrl = Inflector::underscore($plugin);
  849. $url = new CakeRequest($pluginUrl);
  850. $Dispatcher->dispatch($url, $response, array('return' => 1));
  851. $this->assertSame($Dispatcher->controller->plugin, 'MyPlugin');
  852. $this->assertSame($Dispatcher->controller->name, 'MyPlugin');
  853. $this->assertSame($Dispatcher->controller->action, 'index');
  854. $expected = $pluginUrl;
  855. $this->assertEquals($expected, $Dispatcher->controller->params['controller']);
  856. Configure::write('Routing.prefixes', array('admin'));
  857. Router::reload();
  858. require CAKE . 'Config' . DS . 'routes.php';
  859. $Dispatcher = new TestDispatcher();
  860. $url = new CakeRequest('admin/my_plugin/my_plugin/add/5/param:value/param2:value2');
  861. $response = $this->getMock('CakeResponse');
  862. $Dispatcher->dispatch($url, $response, array('return' => 1));
  863. $this->assertEquals('my_plugin', $Dispatcher->controller->params['plugin']);
  864. $this->assertEquals('my_plugin', $Dispatcher->controller->params['controller']);
  865. $this->assertEquals('admin_add', $Dispatcher->controller->params['action']);
  866. $this->assertEquals(array(5), $Dispatcher->controller->params['pass']);
  867. $this->assertEquals(array('param' => 'value', 'param2' => 'value2'), $Dispatcher->controller->params['named']);
  868. $this->assertSame($Dispatcher->controller->plugin, 'MyPlugin');
  869. $this->assertSame($Dispatcher->controller->name, 'MyPlugin');
  870. $this->assertSame($Dispatcher->controller->action, 'admin_add');
  871. $expected = array(0 => 5, 'param' => 'value', 'param2' => 'value2');
  872. $this->assertEquals($expected, $Dispatcher->controller->passedArgs);
  873. Configure::write('Routing.prefixes', array('admin'));
  874. CakePlugin::load('ArticlesTest', array('path' => '/fake/path'));
  875. Router::reload();
  876. require CAKE . 'Config' . DS . 'routes.php';
  877. $Dispatcher = new TestDispatcher();
  878. $Dispatcher->dispatch(new CakeRequest('admin/articles_test'), $response, array('return' => 1));
  879. $this->assertSame($Dispatcher->controller->plugin, 'ArticlesTest');
  880. $this->assertSame($Dispatcher->controller->name, 'ArticlesTest');
  881. $this->assertSame($Dispatcher->controller->action, 'admin_index');
  882. $expected = array(
  883. 'pass' => array(),
  884. 'named' => array(),
  885. 'controller' => 'articles_test',
  886. 'plugin' => 'articles_test',
  887. 'action' => 'admin_index',
  888. 'prefix' => 'admin',
  889. 'admin' => true,
  890. 'return' => 1
  891. );
  892. foreach ($expected as $key => $value) {
  893. $this->assertEquals($expected[$key], $Dispatcher->controller->request[$key], 'Value mismatch ' . $key);
  894. }
  895. }
  896. /**
  897. * test Plugin dispatching without controller name and using
  898. * plugin short form instead.
  899. *
  900. * @return void
  901. */
  902. public function testAutomaticPluginDispatchWithShortAccess() {
  903. CakePlugin::load('MyPlugin', array('path' => '/fake/path'));
  904. Router::reload();
  905. $Dispatcher = new TestDispatcher();
  906. $Dispatcher->base = false;
  907. $url = new CakeRequest('my_plugin/');
  908. $response = $this->getMock('CakeResponse');
  909. $Dispatcher->dispatch($url, $response, array('return' => 1));
  910. $this->assertEquals('my_plugin', $Dispatcher->controller->params['controller']);
  911. $this->assertEquals('my_plugin', $Dispatcher->controller->params['plugin']);
  912. $this->assertEquals('index', $Dispatcher->controller->params['action']);
  913. $this->assertFalse(isset($Dispatcher->controller->params['pass'][0]));
  914. }
  915. /**
  916. * test plugin shortcut urls with controllers that need to be loaded,
  917. * the above test uses a controller that has already been included.
  918. *
  919. * @return void
  920. */
  921. public function testPluginShortCutUrlsWithControllerThatNeedsToBeLoaded() {
  922. $loaded = class_exists('TestPluginController', false);
  923. $this->skipIf($loaded, 'TestPluginController already loaded.');
  924. Router::reload();
  925. App::build(array(
  926. 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
  927. ), App::RESET);
  928. CakePlugin::load(array('TestPlugin', 'TestPluginTwo'));
  929. $Dispatcher = new TestDispatcher();
  930. $Dispatcher->base = false;
  931. $url = new CakeRequest('test_plugin/');
  932. $response = $this->getMock('CakeResponse');
  933. $Dispatcher->dispatch($url, $response, array('return' => 1));
  934. $this->assertEquals('test_plugin', $Dispatcher->controller->params['controller']);
  935. $this->assertEquals('test_plugin', $Dispatcher->controller->params['plugin']);
  936. $this->assertEquals('index', $Dispatcher->controller->params['action']);
  937. $this->assertFalse(isset($Dispatcher->controller->params['pass'][0]));
  938. $url = new CakeRequest('/test_plugin/tests/index');
  939. $Dispatcher->dispatch($url, $response, array('return' => 1));
  940. $this->assertEquals('tests', $Dispatcher->controller->params['controller']);
  941. $this->assertEquals('test_plugin', $Dispatcher->controller->params['plugin']);
  942. $this->assertEquals('index', $Dispatcher->controller->params['action']);
  943. $this->assertFalse(isset($Dispatcher->controller->params['pass'][0]));
  944. $url = new CakeRequest('/test_plugin/tests/index/some_param');
  945. $Dispatcher->dispatch($url, $response, array('return' => 1));
  946. $this->assertEquals('tests', $Dispatcher->controller->params['controller']);
  947. $this->assertEquals('test_plugin', $Dispatcher->controller->params['plugin']);
  948. $this->assertEquals('index', $Dispatcher->controller->params['action']);
  949. $this->assertEquals('some_param', $Dispatcher->controller->params['pass'][0]);
  950. App::build();
  951. }
  952. /**
  953. * testAutomaticPluginControllerMissingActionDispatch method
  954. *
  955. * @expectedException MissingActionException
  956. * @expectedExceptionMessage Action MyPluginController::not_here() could not be found.
  957. * @return void
  958. */
  959. public function testAutomaticPluginControllerMissingActionDispatch() {
  960. Router::reload();
  961. $Dispatcher = new TestDispatcher();
  962. $url = new CakeRequest('my_plugin/not_here/param:value/param2:value2');
  963. $response = $this->getMock('CakeResponse');
  964. $Dispatcher->dispatch($url, $response, array('return' => 1));
  965. }
  966. /**
  967. * testAutomaticPluginControllerMissingActionDispatch method
  968. *
  969. * @expectedException MissingActionException
  970. * @expectedExceptionMessage Action MyPluginController::param:value() could not be found.
  971. * @return void
  972. */
  973. public function testAutomaticPluginControllerIndexMissingAction() {
  974. Router::reload();
  975. $Dispatcher = new TestDispatcher();
  976. $url = new CakeRequest('my_plugin/param:value/param2:value2');
  977. $response = $this->getMock('CakeResponse');
  978. $Dispatcher->dispatch($url, $response, array('return' => 1));
  979. }
  980. /**
  981. * Test dispatching into the TestPlugin in the test_app
  982. *
  983. * @return void
  984. */
  985. public function testTestPluginDispatch() {
  986. $Dispatcher = new TestDispatcher();
  987. App::build(array(
  988. 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
  989. ), App::RESET);
  990. CakePlugin::load(array('TestPlugin', 'TestPluginTwo'));
  991. Router::reload();
  992. Router::parse('/');
  993. $url = new CakeRequest('/test_plugin/tests/index');
  994. $response = $this->getMock('CakeResponse');
  995. $Dispatcher->dispatch($url, $response, array('return' => 1));
  996. $this->assertTrue(class_exists('TestsController'));
  997. $this->assertTrue(class_exists('TestPluginAppController'));
  998. $this->assertTrue(class_exists('PluginsComponent'));
  999. $this->assertEquals('tests', $Dispatcher->controller->params['controller']);
  1000. $this->assertEquals('test_plugin', $Dispatcher->controller->params['plugin']);
  1001. $this->assertEquals('index', $Dispatcher->controller->params['action']);
  1002. App::build();
  1003. }
  1004. /**
  1005. * Tests that it is possible to attach filter classes to the dispatch cycle
  1006. *
  1007. * @return void
  1008. */
  1009. public function testDispatcherFilterSubscriber() {
  1010. App::build(array(
  1011. 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS),
  1012. 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
  1013. ), App::RESET);
  1014. CakePlugin::load('TestPlugin');
  1015. Configure::write('Dispatcher.filters', array(
  1016. array('callable' => 'TestPlugin.TestDispatcherFilter')
  1017. ));
  1018. $dispatcher = new TestDispatcher();
  1019. $request = new CakeRequest('/');
  1020. $request->params['altered'] = false;
  1021. $response = $this->getMock('CakeResponse', array('send'));
  1022. $dispatcher->dispatch($request, $response);
  1023. $this->assertTrue($request->params['altered']);
  1024. $this->assertEquals(304, $response->statusCode());
  1025. Configure::write('Dispatcher.filters', array(
  1026. 'TestPlugin.Test2DispatcherFilter',
  1027. 'TestPlugin.TestDispatcherFilter'
  1028. ));
  1029. $dispatcher = new TestDispatcher();
  1030. $request = new CakeRequest('/');
  1031. $request->params['altered'] = false;
  1032. $response = $this->getMock('CakeResponse', array('send'));
  1033. $dispatcher->dispatch($request, $response);
  1034. $this->assertFalse($request->params['altered']);
  1035. $this->assertEquals(500, $response->statusCode());
  1036. $this->assertNull($dispatcher->controller);
  1037. }
  1038. /**
  1039. * Tests that attaching an inexistent class as filter will throw an exception
  1040. *
  1041. * @expectedException MissingDispatcherFilterException
  1042. * @return void
  1043. */
  1044. public function testDispatcherFilterSuscriberMissing() {
  1045. App::build(array(
  1046. 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
  1047. ), App::RESET);
  1048. CakePlugin::load('TestPlugin');
  1049. Configure::write('Dispatcher.filters', array(
  1050. array('callable' => 'TestPlugin.NotAFilter')
  1051. ));
  1052. $dispatcher = new TestDispatcher();
  1053. $request = new CakeRequest('/');
  1054. $response = $this->getMock('CakeResponse', array('send'));
  1055. $dispatcher->dispatch($request, $response);
  1056. }
  1057. /**
  1058. * Tests it is possible to attach single callables as filters
  1059. *
  1060. * @return void
  1061. */
  1062. public function testDispatcherFilterCallable() {
  1063. App::build(array(
  1064. 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS)
  1065. ), App::RESET);
  1066. $dispatcher = new TestDispatcher();
  1067. Configure::write('Dispatcher.filters', array(
  1068. array('callable' => array($dispatcher, 'filterTest'), 'on' => 'before')
  1069. ));
  1070. $request = new CakeRequest('/');
  1071. $response = $this->getMock('CakeResponse', array('send'));
  1072. $dispatcher->dispatch($request, $response);
  1073. $this->assertEquals('Dispatcher.beforeDispatch', $request->params['eventName']);
  1074. $dispatcher = new TestDispatcher();
  1075. Configure::write('Dispatcher.filters', array(
  1076. array('callable' => array($dispatcher, 'filterTest'), 'on' => 'after')
  1077. ));
  1078. $request = new CakeRequest('/');
  1079. $response = $this->getMock('CakeResponse', array('send'));
  1080. $dispatcher->dispatch($request, $response);
  1081. $this->assertEquals('Dispatcher.afterDispatch', $request->params['eventName']);
  1082. // Test that it is possible to skip the route connection process
  1083. $dispatcher = new TestDispatcher();
  1084. Configure::write('Dispatcher.filters', array(
  1085. array('callable' => array($dispatcher, 'filterTest2'), 'on' => 'before', 'priority' => 1)
  1086. ));
  1087. $request = new CakeRequest('/');
  1088. $response = $this->getMock('CakeResponse', array('send'));
  1089. $dispatcher->dispatch($request, $response);
  1090. $this->assertEmpty($dispatcher->controller);
  1091. $expected = array('controller' => null, 'action' => null, 'plugin' => null, 'named' => array(), 'pass' => array());
  1092. $this->assertEquals($expected, $request->params);
  1093. $dispatcher = new TestDispatcher();
  1094. Configure::write('Dispatcher.filters', array(
  1095. array('callable' => array($dispatcher, 'filterTest2'), 'on' => 'before', 'priority' => 1)
  1096. ));
  1097. $request = new CakeRequest('/');
  1098. $request->params['return'] = true;
  1099. $response = $this->getMock('CakeResponse', array('send'));
  1100. $response->body('this is a body');
  1101. $result = $dispatcher->dispatch($request, $response);
  1102. $this->assertEquals('this is a body', $result);
  1103. $request = new CakeRequest('/');
  1104. $response = $this->getMock('CakeResponse', array('send'));
  1105. $response->expects($this->once())->method('send');
  1106. $response->body('this is a body');
  1107. $result = $dispatcher->dispatch($request, $response);
  1108. $this->assertNull($result);
  1109. }
  1110. /**
  1111. * testChangingParamsFromBeforeFilter method
  1112. *
  1113. * @return void
  1114. */
  1115. public function testChangingParamsFromBeforeFilter() {
  1116. $Dispatcher = new TestDispatcher();
  1117. $response = $this->getMock('CakeResponse');
  1118. $url = new CakeRequest('some_posts/index/param:value/param2:value2');
  1119. try {
  1120. $Dispatcher->dispatch($url, $response, array('return' => 1));
  1121. $this->fail('No exception.');
  1122. } catch (MissingActionException $e) {
  1123. $this->assertEquals('Action SomePostsController::view() could not be found.', $e->getMessage());
  1124. }
  1125. $url = new CakeRequest('some_posts/something_else/param:value/param2:value2');
  1126. $Dispatcher->dispatch($url, $response, array('return' => 1));
  1127. $expected = 'SomePosts';
  1128. $this->assertEquals($expected, $Dispatcher->controller->name);
  1129. $expected = 'change';
  1130. $this->assertEquals($expected, $Dispatcher->controller->action);
  1131. $expected = array('changed');
  1132. $this->assertSame($expected, $Dispatcher->controller->params['pass']);
  1133. }
  1134. /**
  1135. * testStaticAssets method
  1136. *
  1137. * @return void
  1138. */
  1139. public function testAssets() {
  1140. Router::reload();
  1141. App::build(array(
  1142. 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS),
  1143. 'Vendor' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS),
  1144. 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS)
  1145. ));
  1146. CakePlugin::load(array('TestPlugin', 'TestPluginTwo'));
  1147. Configure::write('Dispatcher.filters', array('AssetDispatcher'));
  1148. $Dispatcher = new TestDispatcher();
  1149. $response = $this->getMock('CakeResponse', array('_sendHeader'));
  1150. try {
  1151. $Dispatcher->dispatch(new CakeRequest('theme/test_theme/../webroot/css/test_asset.css'), $response);
  1152. $this->fail('No exception');
  1153. } catch (MissingControllerException $e) {
  1154. $this->assertEquals('Controller class ThemeController could not be found.', $e->getMessage());
  1155. }
  1156. try {
  1157. $Dispatcher->dispatch(new CakeRequest('theme/test_theme/pdfs'), $response);
  1158. $this->fail('No exception');
  1159. } catch (MissingControllerException $e) {
  1160. $this->assertEquals('Controller class ThemeController could not be found.', $e->getMessage());
  1161. }
  1162. }
  1163. /**
  1164. * Data provider for asset filter
  1165. *
  1166. * - theme assets.
  1167. * - plugin assets.
  1168. * - plugin assets in sub directories.
  1169. * - unknown plugin assets.
  1170. *
  1171. * @return array
  1172. */
  1173. public static function assetProvider() {
  1174. return array(
  1175. array(
  1176. 'theme/test_theme/flash/theme_test.swf',
  1177. 'View/Themed/TestTheme/webroot/flash/theme_test.swf'
  1178. ),
  1179. array(
  1180. 'theme/test_theme/pdfs/theme_test.pdf',
  1181. 'View/Themed/TestTheme/webroot/pdfs/theme_test.pdf'
  1182. ),
  1183. array(
  1184. 'theme/test_theme/img/test.jpg',
  1185. 'View/Themed/TestTheme/webroot/img/test.jpg'
  1186. ),
  1187. array(
  1188. 'theme/test_theme/css/test_asset.css',
  1189. 'View/Themed/TestTheme/webroot/css/test_asset.css'
  1190. ),
  1191. array(
  1192. 'theme/test_theme/js/theme.js',
  1193. 'View/Themed/TestTheme/webroot/js/theme.js'
  1194. ),
  1195. array(
  1196. 'theme/test_theme/js/one/theme_one.js',
  1197. 'View/Themed/TestTheme/webroot/js/one/theme_one.js'
  1198. ),
  1199. array(
  1200. 'theme/test_theme/space%20image.text',
  1201. 'View/Themed/TestTheme/webroot/space image.text'
  1202. ),
  1203. array(
  1204. 'test_plugin/root.js',
  1205. 'Plugin/TestPlugin/webroot/root.js'
  1206. ),
  1207. array(
  1208. 'test_plugin/flash/plugin_test.swf',
  1209. 'Plugin/TestPlugin/webroot/flash/plugin_test.swf'
  1210. ),
  1211. array(
  1212. 'test_plugin/pdfs/plugin_test.pdf',
  1213. 'Plugin/TestPlugin/webroot/pdfs/plugin_test.pdf'
  1214. ),
  1215. array(
  1216. 'test_plugin/js/test_plugin/test.js',
  1217. 'Plugin/TestPlugin/webroot/js/test_plugin/test.js'
  1218. ),
  1219. array(
  1220. 'test_plugin/css/test_plugin_asset.css',
  1221. 'Plugin/TestPlugin/webroot/css/test_plugin_asset.css'
  1222. ),
  1223. array(
  1224. 'test_plugin/img/cake.icon.gif',
  1225. 'Plugin/TestPlugin/webroot/img/cake.icon.gif'
  1226. ),
  1227. array(
  1228. 'plugin_js/js/plugin_js.js',
  1229. 'Plugin/PluginJs/webroot/js/plugin_js.js'
  1230. ),
  1231. array(
  1232. 'plugin_js/js/one/plugin_one.js',
  1233. 'Plugin/PluginJs/webroot/js/one/plugin_one.js'
  1234. ),
  1235. array(
  1236. 'test_plugin/css/unknown.extension',
  1237. 'Plugin/TestPlugin/webroot/css/unknown.extension'
  1238. ),
  1239. array(
  1240. 'test_plugin/css/theme_one.htc',
  1241. 'Plugin/TestPlugin/webroot/css/theme_one.htc'
  1242. ),
  1243. );
  1244. }
  1245. /**
  1246. * Test assets
  1247. *
  1248. * @dataProvider assetProvider
  1249. * @outputBuffering enabled
  1250. * @return void
  1251. */
  1252. public function testAsset($url, $file) {
  1253. Router::reload();
  1254. App::build(array(
  1255. 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS),
  1256. 'Vendor' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS),
  1257. 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS)
  1258. ));
  1259. CakePlugin::load(array('TestPlugin', 'PluginJs'));
  1260. Configure::write('Dispatcher.filters', array('AssetDispatcher'));
  1261. $Dispatcher = new TestDispatcher();
  1262. $response = $this->getMock('CakeResponse', array('_sendHeader'));
  1263. $Dispatcher->dispatch(new CakeRequest($url), $response);
  1264. $result = ob_get_clean();
  1265. $path = CAKE . 'Test' . DS . 'test_app' . DS . str_replace('/', DS, $file);
  1266. $file = file_get_contents($path);
  1267. $this->assertEquals($file, $result);
  1268. $expected = filesize($path);
  1269. $headers = $response->header();
  1270. $this->assertEquals($expected, $headers['Content-Length']);
  1271. }
  1272. /**
  1273. * test that missing asset processors trigger a 404 with no response body.
  1274. *
  1275. * @return void
  1276. */
  1277. public function testMissingAssetProcessor404() {
  1278. $response = $this->getMock('CakeResponse', array('send'));
  1279. $Dispatcher = new TestDispatcher();
  1280. Configure::write('Asset.filter', array(
  1281. 'js' => '',
  1282. 'css' => null
  1283. ));
  1284. Configure::write('Dispatcher.filters', array('AssetDispatcher'));
  1285. $request = new CakeRequest('ccss/cake.generic.css');
  1286. $Dispatcher->dispatch($request, $response);
  1287. $this->assertEquals('404', $response->statusCode());
  1288. }
  1289. /**
  1290. * Data provider for cached actions.
  1291. *
  1292. * - Test simple views
  1293. * - Test views with nocache tags
  1294. * - Test requests with named + passed params.
  1295. * - Test requests with query string params
  1296. * - Test themed views.
  1297. *
  1298. * @return array
  1299. */
  1300. public static function cacheActionProvider() {
  1301. return array(
  1302. array('/'),
  1303. array('test_cached_pages/index'),
  1304. array('TestCachedPages/index'),
  1305. array('test_cached_pages/test_nocache_tags'),
  1306. array('TestCachedPages/test_nocache_tags'),
  1307. array('test_cached_pages/view/param/param'),
  1308. array('test_cached_pages/view/foo:bar/value:goo'),
  1309. array('test_cached_pages/view?q=cakephp'),
  1310. array('test_cached_pages/themed'),
  1311. );
  1312. }
  1313. /**
  1314. * testFullPageCachingDispatch method
  1315. *
  1316. * @dataProvider cacheActionProvider
  1317. * @return void
  1318. */
  1319. public function testFullPageCachingDispatch($url) {
  1320. Configure::write('Cache.disable', false);
  1321. Configure::write('Cache.check', true);
  1322. Configure::write('debug', 2);
  1323. Router::reload();
  1324. Router::connect('/', array('controller' => 'test_cached_pages', 'action' => 'index'));
  1325. Router::connect('/:controller/:action/*');
  1326. App::build(array(
  1327. 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS),
  1328. ), App::RESET);
  1329. $dispatcher = new TestDispatcher();
  1330. $request = new CakeRequest($url);
  1331. $response = $this->getMock('CakeResponse', array('send'));
  1332. $dispatcher->dispatch($request, $response);
  1333. $out = $response->body();
  1334. Configure::write('Dispatcher.filters', array('CacheDispatcher'));
  1335. $request = new CakeRequest($url);
  1336. $response = $this->getMock('CakeResponse', array('send'));
  1337. $dispatcher = new TestDispatcher();
  1338. $dispatcher->dispatch($request, $response);
  1339. $cached = $response->body();
  1340. $cached = preg_replace('/<!--+[^<>]+-->/', '', $cached);
  1341. $this->assertTextEquals($out, $cached);
  1342. $filename = $this->_cachePath($request->here());
  1343. unlink($filename);
  1344. }
  1345. /**
  1346. * testHttpMethodOverrides method
  1347. *
  1348. * @return void
  1349. */
  1350. public function testHttpMethodOverrides() {
  1351. Router::reload();
  1352. Router::mapResources('Posts');
  1353. $_SERVER['REQUEST_METHOD'] = 'POST';
  1354. $dispatcher = new Dispatcher();
  1355. $request = new CakeRequest('/posts');
  1356. $event = new CakeEvent('DispatcherTest', $dispatcher, array('request' => $request));
  1357. $dispatcher->parseParams($event);
  1358. $expected = array('pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'add', '[method]' => 'POST');
  1359. foreach ($expected as $key => $value) {
  1360. $this->assertEquals($value, $request[$key], 'Value mismatch for ' . $key . ' %s');
  1361. }
  1362. $_SERVER['REQUEST_METHOD'] = 'GET';
  1363. $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT';
  1364. $request = new CakeRequest('/posts/5');
  1365. $event = new CakeEvent('DispatcherTest', $dispatcher, array('request' => $request));
  1366. $dispatcher->parseParams($event);
  1367. $expected = array(
  1368. 'pass' => array('5'),
  1369. 'named' => array(),
  1370. 'id' => '5',
  1371. 'plugin' => null,
  1372. 'controller' => 'posts',
  1373. 'action' => 'edit',
  1374. '[method]' => 'PUT'
  1375. );
  1376. foreach ($expected as $key => $value) {
  1377. $this->assertEquals($value, $request[$key], 'Value mismatch for ' . $key . ' %s');
  1378. }
  1379. unset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
  1380. $_SERVER['REQUEST_METHOD'] = 'GET';
  1381. $request = new CakeRequest('/posts/5');
  1382. $event = new CakeEvent('DispatcherTest', $dispatcher, array('request' => $request));
  1383. $dispatcher->parseParams($event);
  1384. $expected = array('pass' => array('5'), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'view', '[method]' => 'GET');
  1385. foreach ($expected as $key => $value) {
  1386. $this->assertEquals($value, $request[$key], 'Value mismatch for ' . $key . ' %s');
  1387. }
  1388. $_POST['_method'] = 'PUT';
  1389. $request = new CakeRequest('/posts/5');
  1390. $event = new CakeEvent('DispatcherTest', $dispatcher, array('request' => $request));
  1391. $dispatcher->parseParams($event);
  1392. $expected = array('pass' => array('5'), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'edit', '[method]' => 'PUT');
  1393. foreach ($expected as $key => $value) {
  1394. $this->assertEquals($value, $request[$key], 'Value mismatch for ' . $key . ' %s');
  1395. }
  1396. $_POST['_method'] = 'POST';
  1397. $_POST['data'] = array('Post' => array('title' => 'New Post'));
  1398. $_POST['extra'] = 'data';
  1399. $_SERVER = array();
  1400. $request = new CakeRequest('/posts');
  1401. $event = new CakeEvent('DispatcherTest', $dispatcher, array('request' => $request));
  1402. $dispatcher->parseParams($event);
  1403. $expected = array(
  1404. 'pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'add',
  1405. '[method]' => 'POST', 'data' => array('extra' => 'data', 'Post' => array('title' => 'New Post')),
  1406. );
  1407. foreach ($expected as $key => $value) {
  1408. $this->assertEquals($value, $request[$key], 'Value mismatch for ' . $key . ' %s');
  1409. }
  1410. unset($_POST['_method']);
  1411. }
  1412. /**
  1413. * cachePath method
  1414. *
  1415. * @param string $here
  1416. * @return string
  1417. */
  1418. protected function _cachePath($here) {
  1419. $path = $here;
  1420. if ($here == '/') {
  1421. $path = 'home';
  1422. }
  1423. $path = strtolower(Inflector::slug($path));
  1424. $filename = CACHE . 'views' . DS . $path . '.php';
  1425. if (!file_exists($filename)) {
  1426. $filename = CACHE . 'views' . DS . $path . '_index.php';
  1427. }
  1428. return $filename;
  1429. }
  1430. }