ControllerTest.php 35 KB

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