PageRenderTime 25ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/lithium/tests/cases/action/ControllerTest.php

https://bitbucket.org/thesyncim/admin-biarq
PHP | 356 lines | 229 code | 68 blank | 59 comment | 0 complexity | ef90122477e63ba90f5b7847857f7c72 MD5 | raw file
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2011, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\tests\cases\action;
  9. use lithium\action\Request;
  10. use lithium\action\Controller;
  11. use lithium\tests\mocks\action\MockPostsController;
  12. use lithium\tests\mocks\action\MockControllerRequest;
  13. class ControllerTest extends \lithium\test\Unit {
  14. /**
  15. * Tests that controllers can be instantiated with custom request objects.
  16. *
  17. * @return void
  18. */
  19. public function testConstructionWithCustomRequest() {
  20. $request = new MockControllerRequest();
  21. $postsController = new MockPostsController(compact('request'));
  22. $result = get_class($postsController->request);
  23. $this->assertEqual($result, 'lithium\tests\mocks\action\MockControllerRequest');
  24. }
  25. /**
  26. * Tests the use of `Controller::__invoke()` for dispatching requests to action methods. Also
  27. * tests that using PHP's callable syntax yields the same result as calling `__invoke()`
  28. * explicitly.
  29. *
  30. * @return void
  31. */
  32. public function testMethodInvocation() {
  33. $postsController = new MockPostsController();
  34. $result = $postsController->__invoke(null, array('action' => 'index', 'args' => array()));
  35. $this->assertTrue(is_a($result, 'lithium\action\Response'));
  36. $this->assertEqual('List of posts', $result->body());
  37. $this->assertEqual(array('Content-type' => 'text/plain; charset=UTF-8'), $result->headers);
  38. $result2 = $postsController(null, array('action' => 'index', 'args' => array()));
  39. $this->assertEqual($result2, $result);
  40. $postsController = new MockPostsController();
  41. $this->expectException('/Unhandled media type/');
  42. $result = $postsController(null, array('action' => 'index', 'args' => array(true)));
  43. $this->assertTrue(is_a($result, 'lithium\action\Response'));
  44. $this->assertEqual($result->body, '');
  45. $headers = array('Content-type' => 'text/html; charset=UTF-8');
  46. $this->assertEqual($result->headers, $headers);
  47. $result = $postsController->access('_render');
  48. $this->assertEqual($result['data'], array('foo' => 'bar'));
  49. $postsController = new MockPostsController();
  50. $result = $postsController(null, array('action' => 'view', 'args' => array('2')));
  51. $this->assertTrue(is_a($result, 'lithium\action\Response'));
  52. $this->assertEqual($result->body, "Array\n(\n [0] => This is a post\n)\n");
  53. $headers = array('status' => 200, 'Content-type' => 'text/plain; charset=UTF-8');
  54. $this->assertEqual($result->headers(), $headers);
  55. $result = $postsController->access('_render');
  56. $this->assertEqual($result['data'], array('This is a post'));
  57. }
  58. /**
  59. * Tests that calls to `Controller::redirect()` correctly write redirect headers to the
  60. * response object.
  61. *
  62. * @return void
  63. */
  64. public function testRedirectResponse() {
  65. $postsController = new MockPostsController();
  66. $result = $postsController(null, array('action' => 'delete'));
  67. $this->assertEqual($result->body(), '');
  68. $headers = array('Location' => '/posts');
  69. $this->assertEqual($result->headers, $headers);
  70. $postsController = new MockPostsController();
  71. $result = $postsController(null, array('action' => 'delete', 'args' => array('5')));
  72. $this->assertEqual($result->body(), 'Deleted 5');
  73. $this->assertFalse($postsController->stopped);
  74. $postsController = new MockPostsController(array('classes' => array(
  75. 'response' => 'lithium\tests\mocks\action\MockControllerResponse'
  76. )));
  77. $this->assertFalse($postsController->stopped);
  78. $postsController->__invoke(null, array('action' => 'send'));
  79. $this->assertTrue($postsController->stopped);
  80. $result = $postsController->access('_render');
  81. $this->assertTrue($result['hasRendered']);
  82. $this->assertEqual($postsController->response->body(), null);
  83. $this->assertEqual(
  84. $postsController->response->headers,
  85. array('Location' => '/posts')
  86. );
  87. }
  88. /**
  89. * Tests calling `Controller::render()` with parameters to render an alternate template from
  90. * the default.
  91. *
  92. * @return void
  93. */
  94. public function testRenderWithAlternateTemplate() {
  95. $postsController = new MockPostsController(array('classes' => array(
  96. 'media' => 'lithium\tests\mocks\action\MockMediaClass'
  97. )));
  98. $result = $postsController(null, array('action' => 'view2'));
  99. $this->assertEqual('view', $result->options['template']);
  100. $this->assertEqual('default', $result->options['layout']);
  101. $result = $postsController(null, array('action' => 'view3'));
  102. $this->assertEqual('view', $result->options['template']);
  103. $this->assertFalse($result->options['layout']);
  104. }
  105. /**
  106. * Tests that requests where the controller class is specified manually continue to route to
  107. * the correct template path.
  108. *
  109. * @return void
  110. */
  111. public function testRenderWithNamespacedController() {
  112. $request = new Request();
  113. $request->params['controller'] = 'lithium\tests\mocks\action\MockPostsController';
  114. $controller = new MockPostsController(compact('request') + array('classes' => array(
  115. 'media' => 'lithium\tests\mocks\action\MockMediaClass'
  116. )));
  117. $controller->render();
  118. $this->assertEqual('mock_posts', $controller->response->options['controller']);
  119. }
  120. /**
  121. * Verifies that data array is passed on to controller's response.
  122. *
  123. * @return void
  124. */
  125. public function testRenderWithDataArray() {
  126. $request = new Request();
  127. $request->params['controller'] = 'lithium\tests\mocks\action\MockPostsController';
  128. $controller = new MockPostsController(compact('request') + array('classes' => array(
  129. 'media' => 'lithium\tests\mocks\action\MockMediaClass'
  130. )));
  131. $controller->set(array('set' => 'data'));
  132. $controller->render(array('data' => array('render' => 'data')));
  133. $expected = array(
  134. 'set' => 'data',
  135. 'render' => 'data'
  136. );
  137. $this->assertEqual($expected, $controller->response->data);
  138. }
  139. /**
  140. * Verifies that protected methods (i.e. prefixed with '_'), and methods declared in the
  141. * Controller base class cannot be accessed.
  142. *
  143. * @return void
  144. */
  145. public function testProtectedMethodAccessAttempt() {
  146. $postsController = new MockPostsController();
  147. $this->expectException('/^Attempted to invoke a private method/');
  148. $result = $postsController->__invoke(null, array('action' => 'redirect'));
  149. $this->assertEqual($result->body, null);
  150. $this->assertEqual($result->headers(), array());
  151. $postsController = new MockPostsController();
  152. $this->expectException('/^Private/');
  153. $result = $postsController->invoke('_safe');
  154. $this->assertEqual($result->body, null);
  155. $this->assertEqual($result->headers(), array());
  156. }
  157. public function testResponseStatus() {
  158. $postsController = new MockPostsController(array('classes' => array(
  159. 'response' => 'lithium\tests\mocks\action\MockControllerResponse'
  160. )));
  161. $this->assertFalse($postsController->stopped);
  162. $postsController(null, array('action' => 'not_found'));
  163. $result = $postsController->access('_render');
  164. $this->assertTrue($result['hasRendered']);
  165. $expected = array('code' => 404, 'message' => 'Not Found');
  166. $result = $postsController->response->status;
  167. $this->assertEqual($expected, $result);
  168. $result = json_decode($postsController->response->body(), true);
  169. $this->assertEqual($expected, $result);
  170. }
  171. public function testResponseTypeBasedOnRequestType() {
  172. $request = new MockControllerRequest();
  173. $request->params['type'] = 'json';
  174. $postsController = new MockPostsController(array(
  175. 'request' => $request,
  176. 'classes' => array(
  177. 'response' => 'lithium\tests\mocks\action\MockControllerResponse'
  178. )
  179. ));
  180. $this->assertFalse($postsController->stopped);
  181. $postsController($request, array('action' => 'type'));
  182. $expected = array(
  183. 'type' => 'json', 'data' => array('data' => 'test'), 'auto' => true,
  184. 'layout' => 'default', 'template' => 'type', 'hasRendered' => true, 'negotiate' => false
  185. );
  186. $result = $postsController->access('_render');
  187. $this->assertEqual($expected, $result);
  188. $result = $postsController->response->headers('Content-type');
  189. $this->assertEqual('application/json; charset=UTF-8', $result);
  190. $result = json_decode($postsController->response->body(), true);
  191. $this->assertEqual(array('data' => 'test'), $result);
  192. }
  193. public function testResponseTypeBasedOnRequestParamsType() {
  194. $request = new MockControllerRequest();
  195. $request->params['type'] = 'json';
  196. $postsController = new MockPostsController(array(
  197. 'request' => $request,
  198. 'classes' => array(
  199. 'response' => 'lithium\tests\mocks\action\MockControllerResponse'
  200. )
  201. ));
  202. $this->assertFalse($postsController->stopped);
  203. $postsController->__invoke($request, array('action' => 'type'));
  204. $expected = array(
  205. 'type' => 'json', 'data' => array('data' => 'test'), 'auto' => true,
  206. 'layout' => 'default', 'template' => 'type', 'hasRendered' => true, 'negotiate' => false
  207. );
  208. $result = $postsController->access('_render');
  209. $this->assertEqual($expected, $result);
  210. $result = $postsController->response->headers('Content-type');
  211. $this->assertEqual('application/json; charset=UTF-8', $result);
  212. $expected = array('data' => 'test');
  213. $result = json_decode($postsController->response->body(), true);
  214. $this->assertEqual($expected, $result);
  215. }
  216. /**
  217. * Tests that `$_render['template']` can be manually set in a controller action and will not be
  218. * overwritten.
  219. *
  220. * @return void
  221. */
  222. public function testManuallySettingTemplate() {
  223. $postsController = new MockPostsController(array('classes' => array(
  224. 'media' => 'lithium\tests\mocks\action\MockMediaClass'
  225. )));
  226. $postsController(new Request(), array('action' => 'changeTemplate'));
  227. $result = $postsController->access('_render');
  228. $this->assertEqual('foo', $result['template']);
  229. }
  230. public function testSetData() {
  231. $postController = new MockPostsController();
  232. $setData = array('foo' => 'bar');
  233. $postController->set($setData);
  234. $_render = $postController->access('_render');
  235. $data = $_render['data'];
  236. $expected = $setData;
  237. $this->assertEqual($expected, $data);
  238. $setData = array('foo' => 'baz');
  239. $postController->set($setData);
  240. $_render = $postController->access('_render');
  241. $data = $_render['data'];
  242. $expected = $setData;
  243. $this->assertEqual($expected, $data);
  244. }
  245. public function testResponseTypeBasedOnRequestHeaderType() {
  246. $request = new MockControllerRequest(array(
  247. 'env' => array('HTTP_ACCEPT' => 'application/json,*/*')
  248. ));
  249. $postsController = new MockPostsController(array(
  250. 'request' => $request,
  251. 'classes' => array('response' => 'lithium\tests\mocks\action\MockControllerResponse'),
  252. 'render' => array('negotiate' => true)
  253. ));
  254. $this->assertFalse($postsController->stopped);
  255. $postsController($request, array('action' => 'type'));
  256. $expected = array(
  257. 'type' => 'json', 'data' => array('data' => 'test'), 'auto' => true,
  258. 'layout' => 'default', 'template' => 'type', 'hasRendered' => true, 'negotiate' => true
  259. );
  260. $result = $postsController->access('_render');
  261. $this->assertEqual($expected, $result);
  262. $result = $postsController->response->headers('Content-type');
  263. $this->assertEqual('application/json; charset=UTF-8', $result);
  264. $result = json_decode($postsController->response->body(), true);
  265. $this->assertEqual(array('data' => 'test'), $result);
  266. }
  267. /**
  268. * Tests that requests which are dispotched with the controller route parameter specified as
  269. * a fully-qualified class name are able to locate their templates correctly.
  270. *
  271. * @return void
  272. */
  273. public function testDispatchingWithExplicitControllerName() {
  274. $request = new Request(array('url' => '/'));
  275. $request->params = array(
  276. 'controller' => 'lithium\tests\mocks\action\MockPostsController',
  277. 'action' => 'index'
  278. );
  279. $postsController = new MockPostsController(compact('request'));
  280. $postsController->__invoke($request, $request->params);
  281. }
  282. public function testNonExistentFunction() {
  283. $postsController = new MockPostsController();
  284. $this->expectException("Action `foo` not found.");
  285. $postsController(new Request(), array('action' => 'foo'));
  286. }
  287. }
  288. ?>