/tests/kohana/RouteTest.php
PHP | 447 lines | 217 code | 62 blank | 168 comment | 2 complexity | c8adde84705b14a58ac961d731b8288f MD5 | raw file
- <?php defined('SYSPATH') OR die('Kohana bootstrap needs to be included before tests run');
- /**
- * Description of RouteTest
- *
- * @group kohana
- *
- * @package Unittest
- * @author Kohana Team
- * @author BRMatt <matthew@sigswitch.com>
- * @copyright (c) 2008-2009 Kohana Team
- * @license http://kohanaphp.com/license
- */
- class Kohana_RouteTest extends Kohana_Unittest_TestCase
- {
- /**
- * Remove all caches
- */
- public function setUp()
- {
- parent::setUp();
- $this->clean_cache_dir();
- }
- /**
- * Removes cache files created during tests
- */
- public function tearDown()
- {
- parent::tearDown();
- $this->clean_cache_dir();
- }
- /**
- * Removes all kohana related cache files in the cache directory
- */
- public function clean_cache_dir()
- {
- $cache_dir = opendir(Kohana::$cache_dir);
- while($dir = readdir($cache_dir))
- {
- // Cache files are split into directories based on first two characters of hash
- if($dir[0] !== '.' AND strlen($dir) === 2)
- {
- $cache = opendir(Kohana::$cache_dir.'/'.$dir);
- while($file = readdir($cache))
- {
- if($file[0] !== '.')
- {
- unlink(Kohana::$cache_dir.'/'.$dir.'/'.$file);
- }
- }
- closedir($cache);
- rmdir(Kohana::$cache_dir.'/'.$dir);
- }
- }
- closedir($cache_dir);
- }
- /**
- * If Route::get() is asked for a route that does not exist then
- * it should throw a Kohana_Exception
- *
- * Note use of @expectedException
- *
- * @test
- * @covers Route::get
- * @expectedException Kohana_Exception
- */
- public function test_get_throws_exception_if_route_dnx()
- {
- Route::get('HAHAHAHAHAHAHAHAHA');
- }
- /**
- * Route::all() should return all routes defined via Route::set()
- * and not through new Route()
- *
- * @test
- * @covers Route::all
- */
- public function test_all_returns_all_defined_routes()
- {
- $defined_routes = self::readAttribute('Route', '_routes');
- $this->assertSame($defined_routes, Route::all());
- }
- /**
- * Route::name() should fetch the name of a passed route
- * If route is not found then it should return FALSE
- *
- * @TODO: This test needs to segregate the Route::$_routes singleton
- * @test
- * @covers Route::name
- */
- public function test_name_returns_routes_name_or_false_if_dnx()
- {
- $route = Route::set('flamingo_people', 'flamingo/dance');
-
- $this->assertSame('flamingo_people', Route::name($route));
- $route = new Route('dance/dance');
- $this->assertFalse(Route::name($route));
- }
- /**
- * If Route::cache() was able to restore routes from the cache then
- * it should return TRUE and load the cached routes
- *
- * @test
- * @covers Route::cache
- */
- public function test_cache_stores_route_objects()
- {
- $routes = Route::all();
- // First we create the cache
- Route::cache(TRUE);
- // Now lets modify the "current" routes
- Route::set('nonsensical_route', 'flabbadaga/ding_dong');
- // Then try and load said cache
- $this->assertTrue(Route::cache());
- // And if all went ok the nonsensical route should be gone...
- $this->assertEquals($routes, Route::all());
- }
- /**
- * Route::cache() should return FALSE if cached routes could not be found
- *
- * The cache is cleared before and after each test in setUp tearDown
- * by clean_cache_dir()
- *
- * @test
- * @covers Route::cache
- */
- public function test_cache_returns_false_if_cache_dnx()
- {
- $this->assertSame(FALSE, Route::cache(), 'Route cache was not empty');
- }
- /**
- * If the constructor is passed a NULL uri then it should assume it's
- * being loaded from the cache & therefore shouldn't override the cached attributes
- *
- * @test
- * @covers Route::__construct
- */
- public function test_constructor_returns_if_uri_is_null()
- {
- // We use a mock object to make sure that the route wasn't recompiled
- $route = $this->getMock('Route', array('_compile'), array(), '', FALSE);
- $route
- ->expects($this->never())
- ->method('_compile');
- $route->__construct(NULL,NULL);
- $this->assertAttributeSame('', '_uri', $route);
- $this->assertAttributeSame(array(), '_regex', $route);
- $this->assertAttributeSame(array('action' => 'index'), '_defaults', $route);
- $this->assertAttributeSame(NULL, '_route_regex', $route);
- }
- /**
- * The constructor should only use custom regex if passed a non-empty array
- *
- * Technically we can't "test" this as the default regex is an empty array, this
- * is purely for improving test coverage
- *
- * @test
- * @covers Route::__construct
- */
- public function test_constructor_only_changes_custom_regex_if_passed()
- {
- $route = new Route('<controller>/<action>', array());
- $this->assertAttributeSame(array(), '_regex', $route);
- $route = new Route('<controller>/<action>', NULL);
- $this->assertAttributeSame(array(), '_regex', $route);
- }
- /**
- * When we pass custom regex to the route's constructor it should it
- * in leu of the default
- *
- * @test
- * @covers Route::__construct
- * @covers Route::_compile
- */
- public function test_route_uses_custom_regex_passed_to_constructor()
- {
- $regex = array('id' => '[0-9]{1,2}');
- $route = new Route('<controller>(/<action>(/<id>))', $regex);
- $this->assertAttributeSame($regex, '_regex', $route);
- $this->assertAttributeContains(
- $regex['id'],
- '_route_regex',
- $route
- );
- }
- /**
- * Route::matches() should return false if the route doesn't match against a uri
- *
- * @test
- * @covers Route::matches
- */
- public function test_matches_returns_false_on_failure()
- {
- $route = new Route('projects/(<project_id>/(<controller>(/<action>(/<id>))))');
- $this->assertSame(FALSE, $route->matches('apple/pie'));
- }
- /**
- * Route::matches() should return an array of parameters when a match is made
- * An parameters that are not matched should not be present in the array of matches
- *
- * @test
- * @covers Route::matches
- */
- public function test_matches_returns_array_of_parameters_on_successful_match()
- {
- $route = new Route('(<controller>(/<action>(/<id>)))');
- $matches = $route->matches('welcome/index');
- $this->assertType('array', $matches);
- $this->assertArrayHasKey('controller', $matches);
- $this->assertArrayHasKey('action', $matches);
- $this->assertArrayNotHasKey('id', $matches);
- $this->assertSame(2, count($matches));
- $this->assertSame('welcome', $matches['controller']);
- $this->assertSame('index', $matches['action']);
- }
- /**
- * Defaults specified with defaults() should be used if their values aren't
- * present in the uri
- *
- * @test
- * @covers Route::matches
- */
- public function test_defaults_are_used_if_params_arent_specified()
- {
- $route = new Route('(<controller>(/<action>(/<id>)))');
- $route->defaults(array('controller' => 'welcome', 'action' => 'index'));
- $matches = $route->matches('');
- $this->assertType('array', $matches);
- $this->assertArrayHasKey('controller', $matches);
- $this->assertArrayHasKey('action', $matches);
- $this->assertArrayNotHasKey('id', $matches);
- $this->assertSame(2, count($matches));
- $this->assertSame('welcome', $matches['controller']);
- $this->assertSame('index', $matches['action']);
- $this->assertSame('unit/test/1', $route->uri(array(
- 'controller' => 'unit',
- 'action' => 'test',
- 'id' => '1'
- )));
- $this->assertSame('welcome/index', $route->uri());
- }
- /**
- * This tests that routes with required parameters will not match uris without them present
- *
- * @test
- * @covers Route::matches
- */
- public function test_required_parameters_are_needed()
- {
- $route = new Route('admin(/<controller>(/<action>(/<id>)))');
- $this->assertFalse($route->matches(''));
- $matches = $route->matches('admin');
- $this->assertType('array', $matches);
- $matches = $route->matches('admin/users/add');
- $this->assertType('array', $matches);
- $this->assertSame(2, count($matches));
- $this->assertArrayHasKey('controller', $matches);
- $this->assertArrayHasKey('action', $matches);
- }
- /**
- * This tests the reverse routing returns the uri specified in the route
- * if it's a static route
- *
- * A static route is a route without any parameters
- *
- * @test
- * @covers Route::uri
- */
- public function test_reverse_routing_returns_routes_uri_if_route_is_static()
- {
- $route = new Route('info/about_us');
- $this->assertSame('info/about_us', $route->uri(array('some' => 'random', 'params' => 'to confuse')));
- }
- /**
- * When Route::uri is working on a uri that requires certain parameters to be present
- * (i.e. <controller> in '<controller(/<action)') then it should throw an exception
- * if the param was not provided
- *
- * @test
- * @covers Route::uri
- */
- public function test_uri_throws_exception_if_required_params_are_missing()
- {
- $route = new Route('<controller>(/<action)');
- try
- {
- $route->uri(array('action' => 'awesome-action'));
- $this->fail('Route::uri should throw exception if required param is not provided');
- }
- catch(Exception $e)
- {
- $this->assertType('Kohana_Exception', $e);
- // Check that the error in question is about the controller param
- $this->assertContains('controller', $e->getMessage());
- }
- }
- /**
- * The logic for replacing required segments is separate (but similar) to that for
- * replacing optional segments.
- *
- * This test asserts that Route::uri will replace required segments with provided
- * params
- *
- * @test
- * @covers Route::uri
- */
- public function test_uri_fills_required_uri_segments_from_params()
- {
- $route = new Route('<controller>/<action>(/<id>)');
- $this->assertSame(
- 'users/edit',
- $route->uri(array(
- 'controller' => 'users',
- 'action' => 'edit',
- ))
- );
- $this->assertSame(
- 'users/edit/god',
- $route->uri(array(
- 'controller' => 'users',
- 'action' => 'edit',
- 'id' => 'god',
- ))
- );
- }
- /**
- * Provides test data for test_composing_url_from_route()
- * @return array
- */
- public function provider_composing_url_from_route()
- {
- return array(
- array('/welcome'),
- array('/news/view/42', array('controller' => 'news', 'action' => 'view', 'id' => 42)),
- array('http://kohanaframework.org/news', array('controller' => 'news'), true)
- );
- }
- /**
- * Tests Route::url()
- *
- * Checks the url composing from specific route via Route::url() shortcut
- *
- * @test
- * @dataProvider provider_composing_url_from_route
- * @param string $expected
- * @param array $params
- * @param boolean $protocol
- */
- public function test_composing_url_from_route($expected, $params = NULL, $protocol = NULL)
- {
- Route::set('foobar', '(<controller>(/<action>(/<id>)))')
- ->defaults(array(
- 'controller' => 'welcome',
- )
- );
- $this->setEnvironment(array(
- '_SERVER' => array('HTTP_HOST' => 'kohanaframework.org'),
- 'Kohana::$base_url' => '/',
- 'Request::$protocol' => 'http',
- 'Kohana::$index_file' => '',
- ));
- $this->assertSame($expected, Route::url('foobar', $params, $protocol));
- }
- /**
- * Tests Route::_compile()
- *
- * Makes sure that compile will use custom regex if specified
- *
- * @test
- * @covers Route::_compile
- */
- public function test_compile_uses_custom_regex_if_specificed()
- {
- $route = new Route(
- '<controller>(/<action>(/<id>))',
- array(
- 'controller' => '[a-z]+',
- 'id' => '\d+',
- )
- );
- $this->assertAttributeSame(
- '#^(?P<controller>[a-z]+)(?:/(?P<action>[^/.,;?\n]++)(?:/(?P<id>\d+))?)?$#uD',
- '_route_regex',
- $route
- );
- }
- }