DispatcherTest.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2012, 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\Response;
  11. use lithium\net\http\Router;
  12. use lithium\action\Dispatcher;
  13. use lithium\tests\mocks\action\MockDispatcher;
  14. use lithium\util\Inflector;
  15. class DispatcherTest extends \lithium\test\Unit {
  16. protected $_routes = array();
  17. public function setUp() {
  18. $this->_routes = Router::get();
  19. Router::reset();
  20. }
  21. public function tearDown() {
  22. Router::reset();
  23. foreach ($this->_routes as $route) {
  24. Router::connect($route);
  25. }
  26. }
  27. public function testRun() {
  28. Router::connect('/', array('controller' => 'test', 'action' => 'test'));
  29. MockDispatcher::run(new Request(array('url' => '/')));
  30. $result = end(MockDispatcher::$dispatched);
  31. $expected = array('controller' => 'Test', 'action' => 'test');
  32. $this->assertEqual($expected, $result->params);
  33. }
  34. public function testRunWithNoRouting() {
  35. $this->expectException('/Could not route request/');
  36. MockDispatcher::run(new Request(array('url' => '/')));
  37. }
  38. /**
  39. * Tests that POST requests to the / URL work as expected.
  40. *
  41. * This test belongs to the issue that POST requests (like submitting forms) to the /
  42. * URL don't work as expected, because they immediately get redirected to the same URL but
  43. * as GET requests (with no data attached to it). It veryfies that the Lithium dispatcher
  44. * works as expected and returns the correct controller/action combination.
  45. *
  46. * @return void
  47. */
  48. public function testRunWithPostRoot() {
  49. Router::connect('/', array('controller' => 'test', 'action' => 'test'));
  50. $request = new Request(array('url' => '/', 'env' => array(
  51. 'REQUEST_METHOD' => 'POST'
  52. )));
  53. MockDispatcher::run($request);
  54. $expected = array('controller' => 'Test', 'action' => 'test');
  55. $result = end(MockDispatcher::$dispatched);
  56. $this->assertEqual($expected, $result->params);
  57. }
  58. public function testApplyRulesControllerCasing() {
  59. $params = array('controller' => 'test', 'action' => 'test');
  60. $expected = array('controller' => 'Test', 'action' => 'test');
  61. $this->assertEqual($expected, Dispatcher::applyRules($params));
  62. $params = array('controller' => 'Test', 'action' => 'test');
  63. $this->assertEqual($params, Dispatcher::applyRules($params));
  64. $params = array('controller' => 'test_one', 'action' => 'test');
  65. $expected = array('controller' => 'TestOne', 'action' => 'test');
  66. $this->assertEqual($expected, Dispatcher::applyRules($params));
  67. }
  68. public function testApplyRulesWithNamespacedController() {
  69. $params = array('controller' => 'li3_test\\Test', 'action' => 'test');
  70. $expected = array('controller' => 'li3_test\\Test', 'action' => 'test');
  71. $this->assertEqual($expected, Dispatcher::applyRules($params));
  72. }
  73. public function testApplyRulesDotNamespacing() {
  74. $params = array('controller' => 'li3_test.test', 'action' => 'test');
  75. $expected = array(
  76. 'library' => 'li3_test', 'controller' => 'li3_test.Test', 'action' => 'test'
  77. );
  78. $this->assertEqual($expected, Dispatcher::applyRules($params));
  79. }
  80. public function testApplyRulesLibraryKeyNamespacing() {
  81. $params = array('library' => 'li3_test', 'controller' => 'test', 'action' => 'test');
  82. $expected = array(
  83. 'library' => 'li3_test', 'controller' => 'li3_test.Test', 'action' => 'test'
  84. );
  85. $this->assertEqual($expected, Dispatcher::applyRules($params));
  86. }
  87. public function testApplyRulesNamespacingCollision() {
  88. $params = array('library' => 'li3_one', 'controller' => 'li3_two.test', 'action' => 'test');
  89. $expected = array(
  90. 'library' => 'li3_one', 'controller' => 'li3_two.Test', 'action' => 'test'
  91. );
  92. $this->assertEqual($expected, Dispatcher::applyRules($params));
  93. $params = array('library' => 'li3_one', 'controller' => 'li3_two\Test', 'action' => 'test');
  94. $expected = array(
  95. 'library' => 'li3_one', 'controller' => 'li3_two\Test', 'action' => 'test'
  96. );
  97. $this->assertEqual($expected, Dispatcher::applyRules($params));
  98. }
  99. public function testConfigManipulation() {
  100. $config = MockDispatcher::config();
  101. $expected = array('rules' => array());
  102. $this->assertEqual($expected, $config);
  103. MockDispatcher::config(array('rules' => array(
  104. 'admin' => array('action' => 'admin_{:action}')
  105. )));
  106. Router::connect('/', array('controller' => 'test', 'action' => 'test', 'admin' => true));
  107. MockDispatcher::run(new Request(array('url' => '/')));
  108. $result = end(MockDispatcher::$dispatched);
  109. $expected = array('action' => 'admin_test', 'controller' => 'Test', 'admin' => true);
  110. $this->assertEqual($expected, $result->params);
  111. MockDispatcher::config(array('rules' => array(
  112. 'action' => array('action' => function($params) {
  113. return Inflector::camelize(strtolower($params['action']), false);
  114. })
  115. )));
  116. MockDispatcher::$dispatched = array();
  117. Router::reset();
  118. Router::connect('/', array('controller' => 'test', 'action' => 'TeST-camelize'));
  119. MockDispatcher::run(new Request(array('url' => '/')));
  120. $result = end(MockDispatcher::$dispatched);
  121. $expected = array('action' => 'testCamelize', 'controller' => 'Test');
  122. $this->assertEqual($expected, $result->params);
  123. MockDispatcher::config(array('rules' => function($params) {
  124. if (isset($params['admin'])) {
  125. return array('special' => array('action' => 'special_{:action}'));
  126. }
  127. return array();
  128. }));
  129. MockDispatcher::$dispatched = array();
  130. Router::reset();
  131. Router::connect('/', array('controller' => 'test', 'action' => 'test', 'admin' => true));
  132. Router::connect('/special', array(
  133. 'controller' => 'test', 'action' => 'test',
  134. 'admin' => true, 'special' => true
  135. ));
  136. MockDispatcher::run(new Request(array('url' => '/')));
  137. $result = end(MockDispatcher::$dispatched);
  138. $expected = array('action' => 'test', 'controller' => 'Test', 'admin' => true);
  139. $this->assertEqual($expected, $result->params);
  140. MockDispatcher::run(new Request(array('url' => '/special')));
  141. $result = end(MockDispatcher::$dispatched);
  142. $expected = array(
  143. 'action' => 'special_test', 'controller' => 'Test',
  144. 'admin' => true, 'special' => true
  145. );
  146. $this->assertEqual($expected, $result->params);
  147. }
  148. public function testControllerLookupFail() {
  149. Dispatcher::config(array('classes' => array('router' => __CLASS__)));
  150. $this->expectException("/Controller `SomeNonExistentController` not found/");
  151. Dispatcher::run(new Request(array('url' => '/')));
  152. }
  153. public function testPluginControllerLookupFail() {
  154. Dispatcher::config(array('classes' => array('router' => __CLASS__)));
  155. $this->expectException("/Controller `some_invalid_plugin.Controller` not found/");
  156. Dispatcher::run(new Request(array('url' => '/plugin')));
  157. }
  158. public function testCall() {
  159. $result = MockDispatcher::run(new Request(array('url' => '/call')));
  160. $this->assertEqual('Working', $result->body);
  161. }
  162. public function testAutoHandler() {
  163. $result = MockDispatcher::run(new Request(array('url' => '/auto')));
  164. $this->assertEqual(array('Location: /redirect'), $result->headers());
  165. }
  166. public static function process($request) {
  167. if ($request->url === '/auto') {
  168. return new Response(array('location' => '/redirect'));
  169. }
  170. $params = array(
  171. '' => array('controller' => 'some_non_existent_controller', 'action' => 'index'),
  172. '/plugin' => array(
  173. 'controller' => 'some_invalid_plugin.controller', 'action' => 'index'
  174. ),
  175. '/call' => array('action' => 'index', 'controller' => function($request) {
  176. return new Response(array('body' => 'Working'));
  177. })
  178. );
  179. if (isset($params[$request->url])) {
  180. $request->params = $params[$request->url];
  181. }
  182. return $request;
  183. }
  184. }
  185. ?>