PageRenderTime 56ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/kohana/RouteTest.php

https://github.com/Gyllsdorff/core
PHP | 416 lines | 196 code | 56 blank | 164 comment | 0 complexity | 4bf8e81e9296459b8c027220eec799b3 MD5 | raw file
  1. <?php defined('SYSPATH') OR die('Kohana bootstrap needs to be included before tests run');
  2. /**
  3. * Description of RouteTest
  4. *
  5. * @group kohana
  6. *
  7. * @package Unittest
  8. * @author Kohana Team
  9. * @author BRMatt <matthew@sigswitch.com>
  10. * @copyright (c) 2008-2010 Kohana Team
  11. * @license http://kohanaframework.org/license
  12. */
  13. class Kohana_RouteTest extends Kohana_Unittest_TestCase
  14. {
  15. /**
  16. * Remove all caches
  17. */
  18. public function setUp()
  19. {
  20. parent::setUp();
  21. $this->cleanCacheDir();
  22. }
  23. /**
  24. * Removes cache files created during tests
  25. */
  26. public function tearDown()
  27. {
  28. parent::tearDown();
  29. $this->cleanCacheDir();
  30. }
  31. /**
  32. * If Route::get() is asked for a route that does not exist then
  33. * it should throw a Kohana_Exception
  34. *
  35. * Note use of @expectedException
  36. *
  37. * @test
  38. * @covers Route::get
  39. * @expectedException Kohana_Exception
  40. */
  41. public function test_get_throws_exception_if_route_dnx()
  42. {
  43. Route::get('HAHAHAHAHAHAHAHAHA');
  44. }
  45. /**
  46. * Route::all() should return all routes defined via Route::set()
  47. * and not through new Route()
  48. *
  49. * @test
  50. * @covers Route::all
  51. */
  52. public function test_all_returns_all_defined_routes()
  53. {
  54. $defined_routes = self::readAttribute('Route', '_routes');
  55. $this->assertSame($defined_routes, Route::all());
  56. }
  57. /**
  58. * Route::name() should fetch the name of a passed route
  59. * If route is not found then it should return FALSE
  60. *
  61. * @TODO: This test needs to segregate the Route::$_routes singleton
  62. * @test
  63. * @covers Route::name
  64. */
  65. public function test_name_returns_routes_name_or_false_if_dnx()
  66. {
  67. $route = Route::set('flamingo_people', 'flamingo/dance');
  68. $this->assertSame('flamingo_people', Route::name($route));
  69. $route = new Route('dance/dance');
  70. $this->assertFalse(Route::name($route));
  71. }
  72. /**
  73. * If Route::cache() was able to restore routes from the cache then
  74. * it should return TRUE and load the cached routes
  75. *
  76. * @test
  77. * @covers Route::cache
  78. */
  79. public function test_cache_stores_route_objects()
  80. {
  81. $routes = Route::all();
  82. // First we create the cache
  83. Route::cache(TRUE);
  84. // Now lets modify the "current" routes
  85. Route::set('nonsensical_route', 'flabbadaga/ding_dong');
  86. // Then try and load said cache
  87. $this->assertTrue(Route::cache());
  88. // And if all went ok the nonsensical route should be gone...
  89. $this->assertEquals($routes, Route::all());
  90. }
  91. /**
  92. * Route::cache() should return FALSE if cached routes could not be found
  93. *
  94. * The cache is cleared before and after each test in setUp tearDown
  95. * by cleanCacheDir()
  96. *
  97. * @test
  98. * @covers Route::cache
  99. */
  100. public function test_cache_returns_false_if_cache_dnx()
  101. {
  102. $this->assertSame(FALSE, Route::cache(), 'Route cache was not empty');
  103. }
  104. /**
  105. * If the constructor is passed a NULL uri then it should assume it's
  106. * being loaded from the cache & therefore shouldn't override the cached attributes
  107. *
  108. * @test
  109. * @covers Route::__construct
  110. */
  111. public function test_constructor_returns_if_uri_is_null()
  112. {
  113. // We use a mock object to make sure that the route wasn't recompiled
  114. $route = $this->getMock('Route', array('_compile'), array(), '', FALSE);
  115. $route
  116. ->expects($this->never())
  117. ->method('_compile');
  118. $route->__construct(NULL,NULL);
  119. $this->assertAttributeSame('', '_uri', $route);
  120. $this->assertAttributeSame(array(), '_regex', $route);
  121. $this->assertAttributeSame(array('action' => 'index'), '_defaults', $route);
  122. $this->assertAttributeSame(NULL, '_route_regex', $route);
  123. }
  124. /**
  125. * The constructor should only use custom regex if passed a non-empty array
  126. *
  127. * Technically we can't "test" this as the default regex is an empty array, this
  128. * is purely for improving test coverage
  129. *
  130. * @test
  131. * @covers Route::__construct
  132. */
  133. public function test_constructor_only_changes_custom_regex_if_passed()
  134. {
  135. $route = new Route('<controller>/<action>', array());
  136. $this->assertAttributeSame(array(), '_regex', $route);
  137. $route = new Route('<controller>/<action>', NULL);
  138. $this->assertAttributeSame(array(), '_regex', $route);
  139. }
  140. /**
  141. * When we pass custom regex to the route's constructor it should it
  142. * in leu of the default
  143. *
  144. * @test
  145. * @covers Route::__construct
  146. * @covers Route::_compile
  147. */
  148. public function test_route_uses_custom_regex_passed_to_constructor()
  149. {
  150. $regex = array('id' => '[0-9]{1,2}');
  151. $route = new Route('<controller>(/<action>(/<id>))', $regex);
  152. $this->assertAttributeSame($regex, '_regex', $route);
  153. $this->assertAttributeContains(
  154. $regex['id'],
  155. '_route_regex',
  156. $route
  157. );
  158. }
  159. /**
  160. * Route::matches() should return false if the route doesn't match against a uri
  161. *
  162. * @test
  163. * @covers Route::matches
  164. */
  165. public function test_matches_returns_false_on_failure()
  166. {
  167. $route = new Route('projects/(<project_id>/(<controller>(/<action>(/<id>))))');
  168. $this->assertSame(FALSE, $route->matches('apple/pie'));
  169. }
  170. /**
  171. * Route::matches() should return an array of parameters when a match is made
  172. * An parameters that are not matched should not be present in the array of matches
  173. *
  174. * @test
  175. * @covers Route::matches
  176. */
  177. public function test_matches_returns_array_of_parameters_on_successful_match()
  178. {
  179. $route = new Route('(<controller>(/<action>(/<id>)))');
  180. $matches = $route->matches('welcome/index');
  181. $this->assertType('array', $matches);
  182. $this->assertArrayHasKey('controller', $matches);
  183. $this->assertArrayHasKey('action', $matches);
  184. $this->assertArrayNotHasKey('id', $matches);
  185. $this->assertSame(2, count($matches));
  186. $this->assertSame('welcome', $matches['controller']);
  187. $this->assertSame('index', $matches['action']);
  188. }
  189. /**
  190. * Defaults specified with defaults() should be used if their values aren't
  191. * present in the uri
  192. *
  193. * @test
  194. * @covers Route::matches
  195. */
  196. public function test_defaults_are_used_if_params_arent_specified()
  197. {
  198. $route = new Route('(<controller>(/<action>(/<id>)))');
  199. $route->defaults(array('controller' => 'welcome', 'action' => 'index'));
  200. $matches = $route->matches('');
  201. $this->assertType('array', $matches);
  202. $this->assertArrayHasKey('controller', $matches);
  203. $this->assertArrayHasKey('action', $matches);
  204. $this->assertArrayNotHasKey('id', $matches);
  205. $this->assertSame(2, count($matches));
  206. $this->assertSame('welcome', $matches['controller']);
  207. $this->assertSame('index', $matches['action']);
  208. $this->assertSame('unit/test/1', $route->uri(array(
  209. 'controller' => 'unit',
  210. 'action' => 'test',
  211. 'id' => '1'
  212. )));
  213. $this->assertSame('welcome/index', $route->uri());
  214. }
  215. /**
  216. * This tests that routes with required parameters will not match uris without them present
  217. *
  218. * @test
  219. * @covers Route::matches
  220. */
  221. public function test_required_parameters_are_needed()
  222. {
  223. $route = new Route('admin(/<controller>(/<action>(/<id>)))');
  224. $this->assertFalse($route->matches(''));
  225. $matches = $route->matches('admin');
  226. $this->assertType('array', $matches);
  227. $matches = $route->matches('admin/users/add');
  228. $this->assertType('array', $matches);
  229. $this->assertSame(2, count($matches));
  230. $this->assertArrayHasKey('controller', $matches);
  231. $this->assertArrayHasKey('action', $matches);
  232. }
  233. /**
  234. * This tests the reverse routing returns the uri specified in the route
  235. * if it's a static route
  236. *
  237. * A static route is a route without any parameters
  238. *
  239. * @test
  240. * @covers Route::uri
  241. */
  242. public function test_reverse_routing_returns_routes_uri_if_route_is_static()
  243. {
  244. $route = new Route('info/about_us');
  245. $this->assertSame('info/about_us', $route->uri(array('some' => 'random', 'params' => 'to confuse')));
  246. }
  247. /**
  248. * When Route::uri is working on a uri that requires certain parameters to be present
  249. * (i.e. <controller> in '<controller(/<action)') then it should throw an exception
  250. * if the param was not provided
  251. *
  252. * @test
  253. * @covers Route::uri
  254. */
  255. public function test_uri_throws_exception_if_required_params_are_missing()
  256. {
  257. $route = new Route('<controller>(/<action)');
  258. try
  259. {
  260. $route->uri(array('action' => 'awesome-action'));
  261. $this->fail('Route::uri should throw exception if required param is not provided');
  262. }
  263. catch(Exception $e)
  264. {
  265. $this->assertType('Kohana_Exception', $e);
  266. // Check that the error in question is about the controller param
  267. $this->assertContains('controller', $e->getMessage());
  268. }
  269. }
  270. /**
  271. * The logic for replacing required segments is separate (but similar) to that for
  272. * replacing optional segments.
  273. *
  274. * This test asserts that Route::uri will replace required segments with provided
  275. * params
  276. *
  277. * @test
  278. * @covers Route::uri
  279. */
  280. public function test_uri_fills_required_uri_segments_from_params()
  281. {
  282. $route = new Route('<controller>/<action>(/<id>)');
  283. $this->assertSame(
  284. 'users/edit',
  285. $route->uri(array(
  286. 'controller' => 'users',
  287. 'action' => 'edit',
  288. ))
  289. );
  290. $this->assertSame(
  291. 'users/edit/god',
  292. $route->uri(array(
  293. 'controller' => 'users',
  294. 'action' => 'edit',
  295. 'id' => 'god',
  296. ))
  297. );
  298. }
  299. /**
  300. * Provides test data for test_composing_url_from_route()
  301. * @return array
  302. */
  303. public function provider_composing_url_from_route()
  304. {
  305. return array(
  306. array('/welcome'),
  307. array('/news/view/42', array('controller' => 'news', 'action' => 'view', 'id' => 42)),
  308. array('http://kohanaframework.org/news', array('controller' => 'news'), true)
  309. );
  310. }
  311. /**
  312. * Tests Route::url()
  313. *
  314. * Checks the url composing from specific route via Route::url() shortcut
  315. *
  316. * @test
  317. * @dataProvider provider_composing_url_from_route
  318. * @param string $expected
  319. * @param array $params
  320. * @param boolean $protocol
  321. */
  322. public function test_composing_url_from_route($expected, $params = NULL, $protocol = NULL)
  323. {
  324. Route::set('foobar', '(<controller>(/<action>(/<id>)))')
  325. ->defaults(array(
  326. 'controller' => 'welcome',
  327. )
  328. );
  329. $this->setEnvironment(array(
  330. '_SERVER' => array('HTTP_HOST' => 'kohanaframework.org'),
  331. 'Kohana::$base_url' => '/',
  332. 'Request::$protocol' => 'http',
  333. 'Kohana::$index_file' => '',
  334. ));
  335. $this->assertSame($expected, Route::url('foobar', $params, $protocol));
  336. }
  337. /**
  338. * Tests Route::_compile()
  339. *
  340. * Makes sure that compile will use custom regex if specified
  341. *
  342. * @test
  343. * @covers Route::_compile
  344. */
  345. public function test_compile_uses_custom_regex_if_specificed()
  346. {
  347. $route = new Route(
  348. '<controller>(/<action>(/<id>))',
  349. array(
  350. 'controller' => '[a-z]+',
  351. 'id' => '\d+',
  352. )
  353. );
  354. $this->assertAttributeSame(
  355. '#^(?P<controller>[a-z]+)(?:/(?P<action>[^/.,;?\n]++)(?:/(?P<id>\d+))?)?$#uD',
  356. '_route_regex',
  357. $route
  358. );
  359. }
  360. }