ControllerTest.php 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
  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. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP Project
  12. * @since 1.2.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Controller;
  16. use Cake\Controller\Component;
  17. use Cake\Controller\Controller;
  18. use Cake\Core\Configure;
  19. use Cake\Core\Plugin;
  20. use Cake\Event\Event;
  21. use Cake\Http\Response;
  22. use Cake\Http\ServerRequest;
  23. use Cake\ORM\TableRegistry;
  24. use Cake\Routing\Router;
  25. use Cake\TestSuite\TestCase;
  26. use TestApp\Controller\Admin\PostsController;
  27. use TestPlugin\Controller\TestPluginController;
  28. /**
  29. * AppController class
  30. */
  31. class ControllerTestAppController extends Controller
  32. {
  33. /**
  34. * helpers property
  35. *
  36. * @var array
  37. */
  38. public $helpers = ['Html'];
  39. /**
  40. * modelClass property
  41. *
  42. * @var string
  43. */
  44. public $modelClass = 'Posts';
  45. /**
  46. * components property
  47. *
  48. * @var array
  49. */
  50. public $components = ['Cookie'];
  51. }
  52. /**
  53. * TestController class
  54. */
  55. class TestController extends ControllerTestAppController
  56. {
  57. /**
  58. * Theme property
  59. *
  60. * @var string
  61. */
  62. public $theme = 'Foo';
  63. /**
  64. * helpers property
  65. *
  66. * @var array
  67. */
  68. public $helpers = ['Html'];
  69. /**
  70. * components property
  71. *
  72. * @var array
  73. */
  74. public $components = ['Security'];
  75. /**
  76. * modelClass property
  77. *
  78. * @var string
  79. */
  80. public $modelClass = 'Comments';
  81. /**
  82. * beforeFilter handler
  83. *
  84. * @param \Cake\Event\Event $event
  85. * @return void
  86. */
  87. public function beforeFilter(Event $event)
  88. {
  89. }
  90. /**
  91. * index method
  92. *
  93. * @param mixed $testId
  94. * @param mixed $testTwoId
  95. * @return void
  96. */
  97. public function index($testId, $testTwoId)
  98. {
  99. $this->request->data = [
  100. 'testId' => $testId,
  101. 'test2Id' => $testTwoId
  102. ];
  103. }
  104. /**
  105. * view method
  106. *
  107. * @param mixed $testId
  108. * @param mixed $testTwoId
  109. * @return void
  110. */
  111. public function view($testId, $testTwoId)
  112. {
  113. $this->request->data = [
  114. 'testId' => $testId,
  115. 'test2Id' => $testTwoId
  116. ];
  117. }
  118. public function returner()
  119. {
  120. return 'I am from the controller.';
  121. }
  122. //@codingStandardsIgnoreStart
  123. protected function protected_m()
  124. {
  125. }
  126. private function private_m()
  127. {
  128. }
  129. public function _hidden()
  130. {
  131. }
  132. //@codingStandardsIgnoreEnd
  133. public function admin_add()
  134. {
  135. }
  136. }
  137. /**
  138. * TestComponent class
  139. */
  140. class TestComponent extends Component
  141. {
  142. /**
  143. * beforeRedirect method
  144. *
  145. * @return void
  146. */
  147. public function beforeRedirect()
  148. {
  149. }
  150. /**
  151. * initialize method
  152. *
  153. * @param array $config
  154. * @return void
  155. */
  156. public function initialize(array $config)
  157. {
  158. }
  159. /**
  160. * startup method
  161. *
  162. * @param Event $event
  163. * @return void
  164. */
  165. public function startup(Event $event)
  166. {
  167. }
  168. /**
  169. * shutdown method
  170. *
  171. * @param Event $event
  172. * @return void
  173. */
  174. public function shutdown(Event $event)
  175. {
  176. }
  177. /**
  178. * beforeRender callback
  179. *
  180. * @param Event $event
  181. * @return void
  182. */
  183. public function beforeRender(Event $event)
  184. {
  185. $controller = $event->getSubject();
  186. if ($this->viewclass) {
  187. $controller->viewClass = $this->viewclass;
  188. }
  189. }
  190. }
  191. /**
  192. * AnotherTestController class
  193. */
  194. class AnotherTestController extends ControllerTestAppController
  195. {
  196. }
  197. /**
  198. * ControllerTest class
  199. */
  200. class ControllerTest extends TestCase
  201. {
  202. /**
  203. * fixtures property
  204. *
  205. * @var array
  206. */
  207. public $fixtures = [
  208. 'core.comments',
  209. 'core.posts'
  210. ];
  211. /**
  212. * error level property
  213. *
  214. */
  215. private static $error_level;
  216. /**
  217. * reset environment.
  218. *
  219. * @return void
  220. */
  221. public function setUp()
  222. {
  223. parent::setUp();
  224. static::setAppNamespace();
  225. Router::reload();
  226. }
  227. /**
  228. * tearDown
  229. *
  230. * @return void
  231. */
  232. public function tearDown()
  233. {
  234. parent::tearDown();
  235. Plugin::unload();
  236. error_reporting(self::$error_level);
  237. }
  238. /**
  239. * setUpBeforeClass
  240. *
  241. * @return void
  242. */
  243. public static function setUpBeforeClass()
  244. {
  245. self::$error_level = error_reporting();
  246. }
  247. /**
  248. * tearDownAfterClass
  249. *
  250. * @return void
  251. */
  252. public static function tearDownAfterClass()
  253. {
  254. error_reporting(self::$error_level);
  255. }
  256. /**
  257. * test autoload modelClass
  258. *
  259. * @return void
  260. */
  261. public function testTableAutoload()
  262. {
  263. $request = new ServerRequest('controller_posts/index');
  264. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  265. $Controller = new Controller($request, $response);
  266. $Controller->modelClass = 'SiteArticles';
  267. $this->assertFalse($Controller->Articles);
  268. $this->assertInstanceOf(
  269. 'Cake\ORM\Table',
  270. $Controller->SiteArticles
  271. );
  272. unset($Controller->SiteArticles);
  273. $Controller->modelClass = 'Articles';
  274. $this->assertFalse($Controller->SiteArticles);
  275. $this->assertInstanceOf(
  276. 'TestApp\Model\Table\ArticlesTable',
  277. $Controller->Articles
  278. );
  279. }
  280. /**
  281. * testLoadModel method
  282. *
  283. * @return void
  284. */
  285. public function testLoadModel()
  286. {
  287. $request = new ServerRequest('controller_posts/index');
  288. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  289. $Controller = new Controller($request, $response);
  290. $this->assertFalse(isset($Controller->Articles));
  291. $result = $Controller->loadModel('Articles');
  292. $this->assertInstanceOf(
  293. 'TestApp\Model\Table\ArticlesTable',
  294. $result
  295. );
  296. $this->assertInstanceOf(
  297. 'TestApp\Model\Table\ArticlesTable',
  298. $Controller->Articles
  299. );
  300. }
  301. /**
  302. * testLoadModel method from a plugin controller
  303. *
  304. * @return void
  305. */
  306. public function testLoadModelInPlugins()
  307. {
  308. Plugin::load('TestPlugin');
  309. $Controller = new TestPluginController();
  310. $Controller->plugin = 'TestPlugin';
  311. $this->assertFalse(isset($Controller->TestPluginComments));
  312. $result = $Controller->loadModel('TestPlugin.TestPluginComments');
  313. $this->assertInstanceOf(
  314. 'TestPlugin\Model\Table\TestPluginCommentsTable',
  315. $result
  316. );
  317. $this->assertInstanceOf(
  318. 'TestPlugin\Model\Table\TestPluginCommentsTable',
  319. $Controller->TestPluginComments
  320. );
  321. }
  322. /**
  323. * Test that the constructor sets modelClass properly.
  324. *
  325. * @return void
  326. */
  327. public function testConstructSetModelClass()
  328. {
  329. Plugin::load('TestPlugin');
  330. $request = new ServerRequest();
  331. $response = new Response();
  332. $controller = new \TestApp\Controller\PostsController($request, $response);
  333. $this->assertEquals('Posts', $controller->modelClass);
  334. $this->assertInstanceOf('Cake\ORM\Table', $controller->Posts);
  335. $controller = new \TestApp\Controller\Admin\PostsController($request, $response);
  336. $this->assertEquals('Posts', $controller->modelClass);
  337. $this->assertInstanceOf('Cake\ORM\Table', $controller->Posts);
  338. $request->params['plugin'] = 'TestPlugin';
  339. $controller = new \TestPlugin\Controller\Admin\CommentsController($request, $response);
  340. $this->assertEquals('TestPlugin.Comments', $controller->modelClass);
  341. $this->assertInstanceOf('TestPlugin\Model\Table\CommentsTable', $controller->Comments);
  342. }
  343. /**
  344. * testConstructClassesWithComponents method
  345. *
  346. * @return void
  347. */
  348. public function testConstructClassesWithComponents()
  349. {
  350. Plugin::load('TestPlugin');
  351. $Controller = new TestPluginController(new ServerRequest(), new Response());
  352. $Controller->loadComponent('TestPlugin.Other');
  353. $this->assertInstanceOf('TestPlugin\Controller\Component\OtherComponent', $Controller->Other);
  354. }
  355. /**
  356. * testRender method
  357. *
  358. * @return void
  359. */
  360. public function testRender()
  361. {
  362. Plugin::load('TestPlugin');
  363. $request = new ServerRequest('controller_posts/index');
  364. $request->params['action'] = 'index';
  365. $Controller = new Controller($request, new Response());
  366. $Controller->viewBuilder()->templatePath('Posts');
  367. $result = $Controller->render('index');
  368. $this->assertRegExp('/posts index/', (string)$result);
  369. $Controller->viewBuilder()->template('index');
  370. $result = $Controller->render();
  371. $this->assertRegExp('/posts index/', (string)$result);
  372. $result = $Controller->render('/Element/test_element');
  373. $this->assertRegExp('/this is the test element/', (string)$result);
  374. }
  375. /**
  376. * test view rendering changing response
  377. *
  378. * @return void
  379. */
  380. public function testRenderViewChangesResponse()
  381. {
  382. $request = new ServerRequest('controller_posts/index');
  383. $request->params['action'] = 'header';
  384. $controller = new Controller($request, new Response());
  385. $controller->viewBuilder()->templatePath('Posts');
  386. $result = $controller->render('header');
  387. $this->assertContains('header template', (string)$result);
  388. $this->assertTrue($controller->response->hasHeader('X-view-template'));
  389. $this->assertSame('yes', $controller->response->getHeaderLine('X-view-template'));
  390. }
  391. /**
  392. * test that a component beforeRender can change the controller view class.
  393. *
  394. * @return void
  395. */
  396. public function testBeforeRenderCallbackChangingViewClass()
  397. {
  398. $Controller = new Controller(new ServerRequest, new Response());
  399. $Controller->getEventManager()->on('Controller.beforeRender', function (Event $event) {
  400. $controller = $event->getSubject();
  401. $controller->viewClass = 'Json';
  402. });
  403. $Controller->set([
  404. 'test' => 'value',
  405. '_serialize' => ['test']
  406. ]);
  407. $debug = Configure::read('debug');
  408. Configure::write('debug', false);
  409. $result = $Controller->render('index');
  410. $this->assertEquals('{"test":"value"}', $result->body());
  411. Configure::write('debug', $debug);
  412. }
  413. /**
  414. * test that a component beforeRender can change the controller view class.
  415. *
  416. * @return void
  417. */
  418. public function testBeforeRenderEventCancelsRender()
  419. {
  420. $Controller = new Controller(new ServerRequest, new Response());
  421. $Controller->getEventManager()->on('Controller.beforeRender', function (Event $event) {
  422. return false;
  423. });
  424. $result = $Controller->render('index');
  425. $this->assertInstanceOf('Cake\Http\Response', $result);
  426. }
  427. /**
  428. * Generates status codes for redirect test.
  429. *
  430. * @return void
  431. */
  432. public static function statusCodeProvider()
  433. {
  434. return [
  435. [300, 'Multiple Choices'],
  436. [301, 'Moved Permanently'],
  437. [302, 'Found'],
  438. [303, 'See Other'],
  439. [304, 'Not Modified'],
  440. [305, 'Use Proxy'],
  441. [307, 'Temporary Redirect'],
  442. [403, 'Forbidden'],
  443. ];
  444. }
  445. /**
  446. * testRedirect method
  447. *
  448. * @dataProvider statusCodeProvider
  449. * @return void
  450. */
  451. public function testRedirectByCode($code, $msg)
  452. {
  453. $Controller = new Controller(null, new Response());
  454. $response = $Controller->redirect('http://cakephp.org', (int)$code);
  455. $this->assertSame($response, $Controller->response);
  456. $this->assertEquals($code, $response->statusCode());
  457. $this->assertEquals('http://cakephp.org', $response->header()['Location']);
  458. $this->assertFalse($Controller->autoRender);
  459. }
  460. /**
  461. * test that beforeRedirect callbacks can set the URL that is being redirected to.
  462. *
  463. * @return void
  464. */
  465. public function testRedirectBeforeRedirectModifyingUrl()
  466. {
  467. $Controller = new Controller(null, new Response());
  468. $Controller->getEventManager()->on('Controller.beforeRedirect', function (Event $event, $url, Response $response) {
  469. $response->location('https://book.cakephp.org');
  470. });
  471. $response = $Controller->redirect('http://cakephp.org', 301);
  472. $this->assertEquals('https://book.cakephp.org', $response->header()['Location']);
  473. $this->assertEquals(301, $response->statusCode());
  474. }
  475. /**
  476. * test that beforeRedirect callback returning null doesn't affect things.
  477. *
  478. * @return void
  479. */
  480. public function testRedirectBeforeRedirectModifyingStatusCode()
  481. {
  482. $Response = $this->getMockBuilder('Cake\Http\Response')
  483. ->setMethods(['stop'])
  484. ->getMock();
  485. $Controller = new Controller(null, $Response);
  486. $Controller->getEventManager()->on('Controller.beforeRedirect', function (Event $event, $url, Response $response) {
  487. $response->statusCode(302);
  488. });
  489. $response = $Controller->redirect('http://cakephp.org', 301);
  490. $this->assertEquals('http://cakephp.org', $response->header()['Location']);
  491. $this->assertEquals(302, $response->statusCode());
  492. }
  493. public function testRedirectBeforeRedirectListenerReturnResponse()
  494. {
  495. $Response = $this->getMockBuilder('Cake\Http\Response')
  496. ->setMethods(['stop', 'header', 'statusCode'])
  497. ->getMock();
  498. $Controller = new Controller(null, $Response);
  499. $newResponse = new Response;
  500. $Controller->getEventManager()->on('Controller.beforeRedirect', function (Event $event, $url, Response $response) use ($newResponse) {
  501. return $newResponse;
  502. });
  503. $result = $Controller->redirect('http://cakephp.org');
  504. $this->assertSame($newResponse, $result);
  505. $this->assertSame($newResponse, $Controller->response);
  506. }
  507. /**
  508. * testMergeVars method
  509. *
  510. * @return void
  511. */
  512. public function testMergeVars()
  513. {
  514. $request = new ServerRequest();
  515. $TestController = new TestController($request);
  516. $expected = [
  517. 'Html' => null,
  518. ];
  519. $this->assertEquals($expected, $TestController->helpers);
  520. $expected = [
  521. 'Security' => null,
  522. 'Cookie' => null,
  523. ];
  524. $this->assertEquals($expected, $TestController->components);
  525. $TestController = new AnotherTestController($request);
  526. $this->assertEquals(
  527. 'Posts',
  528. $TestController->modelClass,
  529. 'modelClass should not be overwritten when defined.'
  530. );
  531. }
  532. /**
  533. * testReferer method
  534. *
  535. * @return void
  536. */
  537. public function testReferer()
  538. {
  539. $request = $this->getMockBuilder('Cake\Http\ServerRequest')
  540. ->setMethods(['referer'])
  541. ->getMock();
  542. $request->expects($this->any())->method('referer')
  543. ->with(true)
  544. ->will($this->returnValue('/posts/index'));
  545. $Controller = new Controller($request);
  546. $result = $Controller->referer(null, true);
  547. $this->assertEquals('/posts/index', $result);
  548. $request = $this->getMockBuilder('Cake\Http\ServerRequest')
  549. ->setMethods(['referer'])
  550. ->getMock();
  551. $request->expects($this->any())->method('referer')
  552. ->with(true)
  553. ->will($this->returnValue('/posts/index'));
  554. $Controller = new Controller($request);
  555. $result = $Controller->referer(['controller' => 'posts', 'action' => 'index'], true);
  556. $this->assertEquals('/posts/index', $result);
  557. $request = $this->getMockBuilder('Cake\Http\ServerRequest')
  558. ->setMethods(['referer'])
  559. ->getMock();
  560. $request->expects($this->any())->method('referer')
  561. ->with(false)
  562. ->will($this->returnValue('http://localhost/posts/index'));
  563. $Controller = new Controller($request);
  564. $result = $Controller->referer();
  565. $this->assertEquals('http://localhost/posts/index', $result);
  566. $Controller = new Controller(null);
  567. $result = $Controller->referer();
  568. $this->assertEquals('/', $result);
  569. }
  570. /**
  571. * Test that the referer is not absolute if it is '/'.
  572. *
  573. * This avoids the base path being applied twice on string urls.
  574. *
  575. * @return void
  576. */
  577. public function testRefererSlash()
  578. {
  579. $request = $this->getMockBuilder('Cake\Http\ServerRequest')
  580. ->setMethods(['referer'])
  581. ->getMock();
  582. $request->base = '/base';
  583. Router::pushRequest($request);
  584. $request->expects($this->any())->method('referer')
  585. ->will($this->returnValue('/'));
  586. $controller = new Controller($request);
  587. $result = $controller->referer('/', true);
  588. $this->assertEquals('/', $result);
  589. $controller = new Controller($request);
  590. $result = $controller->referer('/some/path', true);
  591. $this->assertEquals('/some/path', $result);
  592. }
  593. /**
  594. * testSetAction method
  595. *
  596. * @return void
  597. */
  598. public function testSetAction()
  599. {
  600. $request = new ServerRequest('controller_posts/index');
  601. $TestController = new TestController($request);
  602. $TestController->setAction('view', 1, 2);
  603. $expected = ['testId' => 1, 'test2Id' => 2];
  604. $this->assertSame($expected, $TestController->request->data);
  605. $this->assertSame('view', $TestController->request->params['action']);
  606. }
  607. /**
  608. * Tests that the startup process calls the correct functions
  609. *
  610. * @return void
  611. */
  612. public function testStartupProcess()
  613. {
  614. $eventManager = $this->getMockBuilder('Cake\Event\EventManager')->getMock();
  615. $controller = new Controller(null, null, null, $eventManager);
  616. $eventManager->expects($this->at(0))->method('dispatch')
  617. ->with(
  618. $this->logicalAnd(
  619. $this->isInstanceOf('Cake\Event\Event'),
  620. $this->attributeEqualTo('_name', 'Controller.initialize'),
  621. $this->attributeEqualTo('_subject', $controller)
  622. )
  623. )
  624. ->will($this->returnValue($this->getMockBuilder('Cake\Event\Event')->disableOriginalConstructor()->getMock()));
  625. $eventManager->expects($this->at(1))->method('dispatch')
  626. ->with(
  627. $this->logicalAnd(
  628. $this->isInstanceOf('Cake\Event\Event'),
  629. $this->attributeEqualTo('_name', 'Controller.startup'),
  630. $this->attributeEqualTo('_subject', $controller)
  631. )
  632. )
  633. ->will($this->returnValue($this->getMockBuilder('Cake\Event\Event')->disableOriginalConstructor()->getMock()));
  634. $controller->startupProcess();
  635. }
  636. /**
  637. * Tests that the shutdown process calls the correct functions
  638. *
  639. * @return void
  640. */
  641. public function testShutdownProcess()
  642. {
  643. $eventManager = $this->getMockBuilder('Cake\Event\EventManager')->getMock();
  644. $controller = new Controller(null, null, null, $eventManager);
  645. $eventManager->expects($this->once())->method('dispatch')
  646. ->with(
  647. $this->logicalAnd(
  648. $this->isInstanceOf('Cake\Event\Event'),
  649. $this->attributeEqualTo('_name', 'Controller.shutdown'),
  650. $this->attributeEqualTo('_subject', $controller)
  651. )
  652. )
  653. ->will($this->returnValue($this->getMockBuilder('Cake\Event\Event')->disableOriginalConstructor()->getMock()));
  654. $controller->shutdownProcess();
  655. }
  656. /**
  657. * test using Controller::paginate()
  658. *
  659. * @return void
  660. */
  661. public function testPaginate()
  662. {
  663. $request = new ServerRequest('controller_posts/index');
  664. $request->params['pass'] = [];
  665. $response = $this->getMockBuilder('Cake\Http\Response')
  666. ->setMethods(['httpCodes'])
  667. ->getMock();
  668. $Controller = new Controller($request, $response);
  669. $Controller->request->query = [
  670. 'url' => [],
  671. 'posts' => [
  672. 'page' => 2,
  673. 'limit' => 2,
  674. ]
  675. ];
  676. $this->assertEquals([], $Controller->paginate);
  677. $this->assertNotContains('Paginator', $Controller->helpers);
  678. $this->assertArrayNotHasKey('Paginator', $Controller->helpers);
  679. $results = $Controller->paginate('Posts');
  680. $this->assertInstanceOf('Cake\Datasource\ResultSetInterface', $results);
  681. $this->assertCount(3, $results);
  682. $results = $Controller->paginate(TableRegistry::get('Posts'));
  683. $this->assertInstanceOf('Cake\Datasource\ResultSetInterface', $results);
  684. $this->assertCount(3, $results);
  685. $this->assertSame($Controller->request->params['paging']['Posts']['page'], 1);
  686. $this->assertSame($Controller->request->params['paging']['Posts']['pageCount'], 1);
  687. $this->assertSame($Controller->request->params['paging']['Posts']['prevPage'], false);
  688. $this->assertSame($Controller->request->params['paging']['Posts']['nextPage'], false);
  689. $this->assertNull($Controller->request->params['paging']['Posts']['scope']);
  690. $results = $Controller->paginate(TableRegistry::get('Posts'), ['scope' => 'posts']);
  691. $this->assertInstanceOf('Cake\Datasource\ResultSetInterface', $results);
  692. $this->assertCount(1, $results);
  693. $this->assertSame($Controller->request->params['paging']['Posts']['page'], 2);
  694. $this->assertSame($Controller->request->params['paging']['Posts']['pageCount'], 2);
  695. $this->assertSame($Controller->request->params['paging']['Posts']['prevPage'], true);
  696. $this->assertSame($Controller->request->params['paging']['Posts']['nextPage'], false);
  697. $this->assertSame($Controller->request->params['paging']['Posts']['scope'], 'posts');
  698. }
  699. /**
  700. * test that paginate uses modelClass property.
  701. *
  702. * @return void
  703. */
  704. public function testPaginateUsesModelClass()
  705. {
  706. $request = new ServerRequest('controller_posts/index');
  707. $request->params['pass'] = [];
  708. $response = $this->getMockBuilder('Cake\Http\Response')
  709. ->setMethods(['httpCodes'])
  710. ->getMock();
  711. $Controller = new Controller($request, $response);
  712. $Controller->request->query['url'] = [];
  713. $Controller->modelClass = 'Posts';
  714. $results = $Controller->paginate();
  715. $this->assertInstanceOf('Cake\Datasource\ResultSetInterface', $results);
  716. }
  717. /**
  718. * testMissingAction method
  719. *
  720. * @expectedException \Cake\Controller\Exception\MissingActionException
  721. * @expectedExceptionMessage Action TestController::missing() could not be found, or is not accessible.
  722. * @return void
  723. */
  724. public function testInvokeActionMissingAction()
  725. {
  726. $url = new ServerRequest('test/missing');
  727. $url->addParams(['controller' => 'Test', 'action' => 'missing']);
  728. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  729. $Controller = new TestController($url, $response);
  730. $Controller->invokeAction();
  731. }
  732. /**
  733. * test invoking private methods.
  734. *
  735. * @expectedException \Cake\Controller\Exception\MissingActionException
  736. * @expectedExceptionMessage Action TestController::private_m() could not be found, or is not accessible.
  737. * @return void
  738. */
  739. public function testInvokeActionPrivate()
  740. {
  741. $url = new ServerRequest('test/private_m/');
  742. $url->addParams(['controller' => 'Test', 'action' => 'private_m']);
  743. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  744. $Controller = new TestController($url, $response);
  745. $Controller->invokeAction();
  746. }
  747. /**
  748. * test invoking protected methods.
  749. *
  750. * @expectedException \Cake\Controller\Exception\MissingActionException
  751. * @expectedExceptionMessage Action TestController::protected_m() could not be found, or is not accessible.
  752. * @return void
  753. */
  754. public function testInvokeActionProtected()
  755. {
  756. $url = new ServerRequest('test/protected_m/');
  757. $url->addParams(['controller' => 'Test', 'action' => 'protected_m']);
  758. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  759. $Controller = new TestController($url, $response);
  760. $Controller->invokeAction();
  761. }
  762. /**
  763. * test invoking controller methods.
  764. *
  765. * @expectedException \Cake\Controller\Exception\MissingActionException
  766. * @expectedExceptionMessage Action TestController::redirect() could not be found, or is not accessible.
  767. * @return void
  768. */
  769. public function testInvokeActionBaseMethods()
  770. {
  771. $url = new ServerRequest('test/redirect/');
  772. $url->addParams(['controller' => 'Test', 'action' => 'redirect']);
  773. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  774. $Controller = new TestController($url, $response);
  775. $Controller->invokeAction();
  776. }
  777. /**
  778. * test invoking controller methods.
  779. *
  780. * @return void
  781. */
  782. public function testInvokeActionReturnValue()
  783. {
  784. $url = new ServerRequest('test/returner/');
  785. $url->addParams([
  786. 'controller' => 'Test',
  787. 'action' => 'returner',
  788. 'pass' => []
  789. ]);
  790. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  791. $Controller = new TestController($url, $response);
  792. $result = $Controller->invokeAction();
  793. $this->assertEquals('I am from the controller.', $result);
  794. }
  795. /**
  796. * test invoking controller methods with passed params
  797. *
  798. * @return void
  799. */
  800. public function testInvokeActionWithPassedParams()
  801. {
  802. $url = new ServerRequest('test/index/1/2');
  803. $url->addParams([
  804. 'controller' => 'Test',
  805. 'action' => 'index',
  806. 'pass' => ['param1' => '1', 'param2' => '2']
  807. ]);
  808. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  809. $Controller = new TestController($url, $response);
  810. $result = $Controller->invokeAction();
  811. $this->assertEquals(
  812. ['testId' => '1', 'test2Id' => '2'],
  813. $Controller->request->data
  814. );
  815. }
  816. /**
  817. * test that a classes namespace is used in the viewPath.
  818. *
  819. * @return void
  820. */
  821. public function testViewPathConventions()
  822. {
  823. $request = new ServerRequest('admin/posts');
  824. $request->addParams([
  825. 'prefix' => 'admin'
  826. ]);
  827. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  828. $Controller = new \TestApp\Controller\Admin\PostsController($request, $response);
  829. $Controller->getEventManager()->on('Controller.beforeRender', function (Event $e) {
  830. return $e->subject()->response;
  831. });
  832. $Controller->render();
  833. $this->assertEquals('Admin' . DS . 'Posts', $Controller->viewBuilder()->templatePath());
  834. $request->addParams([
  835. 'prefix' => 'admin/super'
  836. ]);
  837. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  838. $Controller = new \TestApp\Controller\Admin\PostsController($request, $response);
  839. $Controller->getEventManager()->on('Controller.beforeRender', function (Event $e) {
  840. return $e->subject()->response;
  841. });
  842. $Controller->render();
  843. $this->assertEquals('Admin' . DS . 'Super' . DS . 'Posts', $Controller->viewBuilder()->templatePath());
  844. $request = new ServerRequest('pages/home');
  845. $request->addParams([
  846. 'prefix' => false
  847. ]);
  848. $Controller = new \TestApp\Controller\PagesController($request, $response);
  849. $Controller->getEventManager()->on('Controller.beforeRender', function (Event $e) {
  850. return $e->subject()->response;
  851. });
  852. $Controller->render();
  853. $this->assertEquals('Pages', $Controller->viewBuilder()->templatePath());
  854. }
  855. /**
  856. * Test the components() method.
  857. *
  858. * @return void
  859. */
  860. public function testComponents()
  861. {
  862. $request = new ServerRequest('/');
  863. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  864. $controller = new TestController($request, $response);
  865. $this->assertInstanceOf('Cake\Controller\ComponentRegistry', $controller->components());
  866. $result = $controller->components();
  867. $this->assertSame($result, $controller->components());
  868. }
  869. /**
  870. * Test the components() method with the custom ObjectRegistry.
  871. *
  872. * @return void
  873. */
  874. public function testComponentsWithCustomRegistry()
  875. {
  876. $request = new ServerRequest('/');
  877. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  878. $componentRegistry = $this->getMockBuilder('Cake\Controller\ComponentRegistry')
  879. ->setMethods(['offsetGet'])
  880. ->getMock();
  881. $controller = new TestController($request, $response, null, null, $componentRegistry);
  882. $this->assertInstanceOf(get_class($componentRegistry), $controller->components());
  883. $result = $controller->components();
  884. $this->assertSame($result, $controller->components());
  885. }
  886. /**
  887. * Test adding a component
  888. *
  889. * @return void
  890. */
  891. public function testLoadComponent()
  892. {
  893. $request = new ServerRequest('/');
  894. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  895. $controller = new TestController($request, $response);
  896. $result = $controller->loadComponent('Paginator');
  897. $this->assertInstanceOf('Cake\Controller\Component\PaginatorComponent', $result);
  898. $this->assertSame($result, $controller->Paginator);
  899. $registry = $controller->components();
  900. $this->assertTrue(isset($registry->Paginator));
  901. }
  902. /**
  903. * Test adding a component that is a duplicate.
  904. *
  905. * @return void
  906. */
  907. public function testLoadComponentDuplicate()
  908. {
  909. $request = new ServerRequest('/');
  910. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  911. $controller = new TestController($request, $response);
  912. $this->assertNotEmpty($controller->loadComponent('Paginator'));
  913. $this->assertNotEmpty($controller->loadComponent('Paginator'));
  914. try {
  915. $controller->loadComponent('Paginator', ['bad' => 'settings']);
  916. $this->fail('No exception');
  917. } catch (\RuntimeException $e) {
  918. $this->assertContains('The "Paginator" alias has already been loaded', $e->getMessage());
  919. }
  920. }
  921. /**
  922. * Test the isAction method.
  923. *
  924. * @return void
  925. */
  926. public function testIsAction()
  927. {
  928. $request = new ServerRequest('/');
  929. $response = $this->getMockBuilder('Cake\Http\Response')->getMock();
  930. $controller = new TestController($request, $response);
  931. $this->assertFalse($controller->isAction('redirect'));
  932. $this->assertFalse($controller->isAction('beforeFilter'));
  933. $this->assertTrue($controller->isAction('index'));
  934. }
  935. /**
  936. * Test declared deprecated properties like $theme are properly passed to view.
  937. *
  938. * @return void
  939. */
  940. public function testDeclaredDeprecatedProperty()
  941. {
  942. $controller = new TestController(new ServerRequest(), new Response());
  943. $theme = $controller->theme;
  944. // @codingStandardsIgnoreStart
  945. $this->assertEquals($theme, @$controller->createView()->theme);
  946. // @codingStandardsIgnoreEnd
  947. }
  948. /**
  949. * Test that view variables are being set after the beforeRender event gets dispatched
  950. *
  951. * @return void
  952. */
  953. public function testBeforeRenderViewVariables()
  954. {
  955. $controller = new PostsController();
  956. $controller->getEventManager()->on('Controller.beforeRender', function (Event $event) {
  957. /* @var Controller $controller */
  958. $controller = $event->getSubject();
  959. $controller->set('testVariable', 'test');
  960. });
  961. $controller->render('index');
  962. $this->assertArrayHasKey('testVariable', $controller->View->viewVars);
  963. }
  964. /**
  965. * Tests deprecated view propertiyes work
  966. *
  967. * @param $property Deprecated property name
  968. * @param $getter Getter name
  969. * @param $setter Setter name
  970. * @param mixed $value Value to be set
  971. * @return void
  972. * @dataProvider deprecatedViewPropertyProvider
  973. */
  974. public function testDeprecatedViewProperty($property, $getter, $setter, $value)
  975. {
  976. $controller = new AnotherTestController();
  977. error_reporting(E_ALL ^ E_USER_DEPRECATED);
  978. $controller->$property = $value;
  979. $this->assertSame($value, $controller->$property);
  980. $this->assertSame($value, $controller->viewBuilder()->{$getter}());
  981. }
  982. /**
  983. * Tests deprecated view propertiyes message
  984. *
  985. * @param $property Deprecated property name
  986. * @param $getter Getter name
  987. * @param $setter Setter name
  988. * @param mixed $value Value to be set
  989. * @return void
  990. * @expectedException PHPUnit\Framework\Error\Deprecated
  991. * @expectedExceptionMessageRegExp /^Controller::\$\w+ is deprecated(.*)/
  992. * @dataProvider deprecatedViewPropertyProvider
  993. */
  994. public function testDeprecatedViewPropertySetterMessage($property, $getter, $setter, $value)
  995. {
  996. error_reporting(E_ALL);
  997. $controller = new AnotherTestController();
  998. $controller->$property = $value;
  999. }
  1000. /**
  1001. * Tests deprecated view propertiyes message
  1002. *
  1003. * @param $property Deprecated property name
  1004. * @param $getter Getter name
  1005. * @param $setter Setter name
  1006. * @param mixed $value Value to be set
  1007. * @return void
  1008. * @expectedException PHPUnit\Framework\Error\Deprecated
  1009. * @expectedExceptionMessageRegExp /^Controller::\$\w+ is deprecated(.*)/
  1010. * @dataProvider deprecatedViewPropertyProvider
  1011. */
  1012. public function testDeprecatedViewPropertyGetterMessage($property, $getter, $setter, $value)
  1013. {
  1014. error_reporting(E_ALL);
  1015. $controller = new AnotherTestController();
  1016. $controller->viewBuilder()->{$setter}($value);
  1017. $result = $controller->$property;
  1018. }
  1019. /**
  1020. * Data provider for testing deprecated view properties
  1021. *
  1022. * @return array
  1023. */
  1024. public function deprecatedViewPropertyProvider()
  1025. {
  1026. return [
  1027. ['layout', 'getLayout', 'setLayout', 'custom'],
  1028. ['view', 'getTemplate', 'setTemplate', 'view'],
  1029. ['theme', 'getTheme', 'setTheme', 'Modern'],
  1030. ['autoLayout', 'isAutoLayoutEnabled', 'enableAutoLayout', false],
  1031. ['viewPath', 'getTemplatePath', 'setTemplatePath', 'Templates'],
  1032. ['layoutPath', 'getLayoutPath', 'setLayoutPath', 'Layouts'],
  1033. ];
  1034. }
  1035. }