1073 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			1073 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace Phroute\Phroute\Dispatcher;
 | |
| 
 | |
| use Phroute\Phroute\RouteCollector;
 | |
| use Phroute\Phroute\RouteParser;
 | |
| use Phroute\Phroute\Dispatcher;
 | |
| use Phroute\Phroute\Route;
 | |
| 
 | |
| class Test {
 | |
|     
 | |
|     public function route()
 | |
|     {
 | |
|         return 'testRoute';
 | |
|     }
 | |
|     
 | |
|     public function anyIndex()
 | |
|     {
 | |
|         return 'testRouteAnyIndex';
 | |
|     }
 | |
|     
 | |
|     public function anyTest()
 | |
|     {
 | |
|         return 'testRouteAnyTest';
 | |
|     }
 | |
|     
 | |
|     public function getTest()
 | |
|     {
 | |
|         return 'testRouteGetTest';
 | |
|     }
 | |
|     
 | |
|     public function postTest()
 | |
|     {
 | |
|         return 'testRoutePostTest';
 | |
|     }
 | |
|     
 | |
|     public function putTest()
 | |
|     {
 | |
|         return 'testRoutePutTest';
 | |
|     }
 | |
| 
 | |
|     public function patchTest()
 | |
|     {
 | |
|         return 'testRoutePatchTest';
 | |
|     }
 | |
| 
 | |
|     public function deleteTest()
 | |
|     {
 | |
|         return 'testRouteDeleteTest';
 | |
|     }
 | |
|     
 | |
|     public function headTest()
 | |
|     {
 | |
|         return 'testRouteHeadTest';
 | |
|     }
 | |
|     
 | |
|     public function optionsTest()
 | |
|     {
 | |
|         return 'testRouteOptionsTest';
 | |
|     }
 | |
| 
 | |
|     public function getCamelCaseHyphenated()
 | |
|     {
 | |
|         return 'hyphenated';
 | |
|     }
 | |
| 
 | |
|     public function getParameter($param)
 | |
|     {
 | |
|         return $param;
 | |
|     }
 | |
| 
 | |
|     public function getParameterHyphenated($param)
 | |
|     {
 | |
|         return $param;
 | |
|     }
 | |
| 
 | |
|     public function getParameterOptional($param = 'default')
 | |
|     {
 | |
|         return $param;
 | |
|     }
 | |
| 
 | |
|     public function getParameterRequired($param)
 | |
|     {
 | |
|         return $param;
 | |
|     }
 | |
| 
 | |
|     public function getParameterOptionalRequired($param, $param2 = 'default')
 | |
|     {
 | |
|         return $param . $param2;
 | |
|     }
 | |
| }
 | |
| 
 | |
| class DispatcherTest extends \PHPUnit_Framework_TestCase {
 | |
| 
 | |
|     /**
 | |
|      * Set appropriate options for the specific Dispatcher class we're testing
 | |
|      */
 | |
|     private function router()
 | |
|     {
 | |
|         return new RouteCollector(new RouteParser);
 | |
|     }
 | |
| 
 | |
|     private function dispatch($router, $method, $uri)
 | |
|     {
 | |
|         return (new Dispatcher($router->getData()))->dispatch($method, $uri);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @dataProvider provideFoundDispatchCases
 | |
|      */
 | |
|     public function testFoundDispatches($method, $uri, $callback, $expected)
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         $callback($r);
 | |
|         $response = $this->dispatch($r, $method, $uri);
 | |
|         $this->assertEquals($expected, $response);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @dataProvider provideNotFoundDispatchCases
 | |
|      * @expectedException \Phroute\Phroute\Exception\HttpRouteNotFoundException
 | |
|      * @expectedExceptionMessage does not exist
 | |
|      */
 | |
|     public function testNotFoundDispatches($method, $uri, $callback)
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         $callback($r);
 | |
|         $this->dispatch($r, $method, $uri);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @dataProvider provideMethodNotAllowedDispatchCases
 | |
|      */
 | |
|     public function testMethodNotAllowedDispatches($method, $uri, $callback, $allowed)
 | |
|     {
 | |
|         $this->setExpectedException('\Phroute\Phroute\Exception\HttpMethodNotAllowedException',"Allow: " . implode(', ', $allowed));
 | |
| 
 | |
|         $r = $this->router();
 | |
|         $callback($r);
 | |
|         $this->dispatch($r, $method, $uri);
 | |
|     }
 | |
|     
 | |
|     public function testStringObjectIsDispatched()
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         
 | |
|         $r->addRoute('GET', '/foo', array(__NAMESPACE__.'\\Test','route'));
 | |
|         
 | |
|         $response = $this->dispatch($r, 'GET', '/foo');
 | |
|                 
 | |
|         $this->assertEquals('testRoute',$response);
 | |
|     }
 | |
|     
 | |
|     public function testNamedRoutes()
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         
 | |
|         $r->addRoute('GET', array('/foo', 'name'), array(__NAMESPACE__.'\\Test','route'));
 | |
|                 
 | |
|         $this->assertEquals('foo',$r->route('name'));
 | |
|         
 | |
|         $r->addRoute('GET', array('/foo/{name}/{something:i}', 'name2'), array(__NAMESPACE__.'\\Test','route'));
 | |
|                 
 | |
|         $this->assertEquals('foo/joe/something',$r->route('name2', ['joe', 'something']));
 | |
| 
 | |
| 
 | |
|         $this->assertTrue($r->hasRoute('name2'));
 | |
|         $this->assertFalse($r->hasRoute('unknown-name'));
 | |
|     }
 | |
| 
 | |
|     public function testOptionalReverseRoute()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->any( array('products/store/{store:i}?', 'products'), array(__NAMESPACE__.'\\Test','route'));
 | |
| 
 | |
|         $this->assertEquals('products/store', $r->route('products'));
 | |
|         $this->assertEquals('products/store/1', $r->route('products', array(1)));
 | |
|     }
 | |
| 
 | |
|     public function testReverseRouteWithDashes()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->any( array('product-catalogue/store/{store:i}?', 'products'), array(__NAMESPACE__.'\\Test','route'));
 | |
| 
 | |
|         $this->assertEquals('product-catalogue/store', $r->route('products'));
 | |
|         $this->assertEquals('product-catalogue/store/1', $r->route('products', array(1)));
 | |
|     }
 | |
| 
 | |
|     public function testGroupsReverseRoutes()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->group([], function($r) {
 | |
|             $r->any(['products/store/{store:i}?', 'products'], array(__NAMESPACE__.'\\Test','route'));
 | |
|         });
 | |
| 
 | |
|         $this->assertEquals('products/store', $r->route('products'));
 | |
|         $this->assertEquals('products/store/1', $r->route('products', array(1)));
 | |
|     }
 | |
| 
 | |
|     public function testPrefixGroupsReverseRoutes()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->group(['prefix' => 'product-catalogue/store'], function($r) {
 | |
|             $r->any(['items/{store:i}?', 'products'], array(__NAMESPACE__.'\\Test','route'));
 | |
|         });
 | |
| 
 | |
|         $this->assertEquals('product-catalogue/store/items', $r->route('products'));
 | |
|         $this->assertEquals('product-catalogue/store/items/1', $r->route('products', array(1)));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @expectedException \Phroute\Phroute\Exception\BadRouteException
 | |
|      * @expectedExceptionMessage Expecting route variable 'store'
 | |
|      */
 | |
|     public function testMissingParameterReverseRoute()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->any( array('products/store/{store:i}', 'products'), array(__NAMESPACE__.'\\Test','route'));
 | |
| 
 | |
|         $this->assertEquals('products/store', $r->route('products'));
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @expectedException \Phroute\Phroute\Exception\BadRouteException
 | |
|      * @expectedExceptionMessage Cannot use the same placeholder 'test' twice
 | |
|      */
 | |
|     public function testDuplicateVariableNameError()
 | |
|     {
 | |
|         $this->router()->addRoute('GET', '/foo/{test}/{test:\d+}', function() {
 | |
|             
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @expectedException \Phroute\Phroute\Exception\BadRouteException
 | |
|      * @expectedExceptionMessage Cannot register two routes matching 'user/([^/]+)' for method 'GET'
 | |
|      */
 | |
|     public function testDuplicateVariableRoute()
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         $r->addRoute('GET', '/user/{id}', function() {
 | |
|             
 | |
|         }); // oops, forgot \d+ restriction ;)
 | |
|         $r->addRoute('GET', '/user/{name}', function() {
 | |
|             
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @expectedException \Phroute\Phroute\Exception\BadRouteException
 | |
|      * @expectedExceptionMessage Cannot register two routes matching 'user' for method 'GET'
 | |
|      */
 | |
|     public function testDuplicateStaticRoute()
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         $r->addRoute('GET', '/user', function() {
 | |
|             
 | |
|         });
 | |
|         $r->addRoute('GET', '/user', function() {
 | |
|             
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @expectedException \Phroute\Phroute\Exception\BadRouteException
 | |
|      * @expectedExceptionMessage Static route 'user/nikic' is shadowed by previously defined variable route 'user/([^/]+)' for method 'GET'
 | |
|      */
 | |
|     public function testShadowedStaticRoute()
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         $r->addRoute('GET', '/user/{name}', function() {
 | |
|             
 | |
|         });
 | |
|         $r->addRoute('GET', '/user/nikic', function() {
 | |
|             
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     public function testBeforeFilters()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $dispatchedFilter = false;
 | |
|         
 | |
|         $r->filter('test', function() use(&$dispatchedFilter){
 | |
|             $dispatchedFilter = true;
 | |
|         });
 | |
| 
 | |
|         $r->addRoute('GET', '/user', function() {
 | |
|             return 'dispatched';
 | |
|         }, array('before' => 'test'));
 | |
| 
 | |
|         $this->assertEquals('dispatched', $this->dispatch($r, 'GET', '/user'));
 | |
|         
 | |
|         $this->assertTrue($dispatchedFilter);
 | |
|     }
 | |
|     
 | |
|     public function testBeforeFiltersStringClass()
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         
 | |
|         $r->filter('test', array(__NAMESPACE__ . '\Test','route'));
 | |
| 
 | |
|         $r->addRoute('GET', '/user', function() {}, array('before' => 'test'));
 | |
| 
 | |
|         $this->assertEquals('testRoute', $this->dispatch($r, 'GET', '/user'));
 | |
|     }
 | |
| 
 | |
|     public function testBeforeFilterCancels()
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         
 | |
|         $r->filter('test', function(){            
 | |
|             return 'cancel';
 | |
|         });
 | |
| 
 | |
|         $r->addRoute('GET', '/user', function() {
 | |
|             return 'dispatched';
 | |
|         }, array('before' => 'test'));
 | |
| 
 | |
|         $this->assertEquals('cancel', $this->dispatch($r, 'GET', '/user'));
 | |
|     }
 | |
|     
 | |
|     
 | |
|     public function testAfterFilters()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $dispatchedFilter = false;
 | |
|         
 | |
|         $r->filter('test', function($response) use(&$dispatchedFilter){
 | |
|             $dispatchedFilter = true;
 | |
|             
 | |
|             return $response . ' filtered';
 | |
|         });
 | |
| 
 | |
|         $r->addRoute('GET', '/user', function() {
 | |
|             return 'test';
 | |
|         }, array('after' => 'test'));
 | |
| 
 | |
|         $response = $this->dispatch($r, 'GET', '/user');
 | |
|         
 | |
|         $this->assertTrue($dispatchedFilter);
 | |
|         
 | |
|         $this->assertEquals('test filtered', $response);
 | |
|     }
 | |
|     
 | |
|     public function testFilterGroups()
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         
 | |
|         $dispatchedFilter = 0;
 | |
|         $dispatchedFilter2 = 0;
 | |
|         
 | |
|         $r->filter('test', function() use(&$dispatchedFilter){
 | |
|             $dispatchedFilter++;
 | |
|         });
 | |
|         
 | |
|         $r->filter('test2', function() use(&$dispatchedFilter2){
 | |
|             $dispatchedFilter2++;
 | |
|         });
 | |
|         
 | |
|         $r->group(array('before' => 'test'), function($router){
 | |
|             $router->addRoute('GET', '/user', function() {
 | |
|             
 | |
|             });
 | |
|             $router->group(array('before' => 'test2'), function($router){
 | |
|                 $router->addRoute('GET', '/user2', function() {
 | |
| 
 | |
|                 });
 | |
|             });
 | |
|         });
 | |
|         
 | |
|         $this->dispatch($r, 'GET', '/user');
 | |
|         
 | |
|         $this->assertEquals(1, $dispatchedFilter);
 | |
|         
 | |
|         $this->dispatch($r, 'GET', '/user2');
 | |
|         
 | |
|         $this->assertEquals(2, $dispatchedFilter);
 | |
|         $this->assertEquals(1, $dispatchedFilter2);
 | |
|         
 | |
|     }
 | |
| 
 | |
|     public function testMultiplePrefixedGroups()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->group(['prefix' => '/user'], function($router){
 | |
|             $router->addRoute('GET', '/', function() {
 | |
| 
 | |
|             });
 | |
|             $router->group(['prefix' => '/foo'], function($router){
 | |
|                 $router->addRoute('GET', '/{id}', function() {
 | |
| 
 | |
|                 });
 | |
|             });
 | |
|         });
 | |
| 
 | |
|         $this->dispatch($r, 'GET', '/user');
 | |
| 
 | |
|         $this->dispatch($r, 'GET', '/user/foo/2');
 | |
| 
 | |
|     }
 | |
| 
 | |
|     public function testVariablePrefix()
 | |
|     {
 | |
|         $r = $this->router();
 | |
|         $r->group(['prefix' => '/demo/{variable}'], function($router){
 | |
|             $router->addRoute('GET', '/something', function($var){
 | |
|                return $var;
 | |
|             });
 | |
| 
 | |
|             $router->addRoute('GET', '/something-else', function($var){
 | |
|                 return $var;
 | |
|             });
 | |
|         });
 | |
| 
 | |
|         $response = $this->dispatch($r, 'GET', '/demo/2/something');
 | |
| 
 | |
|         $this->assertEquals('2', $response);
 | |
| 
 | |
|         $response = $this->dispatch($r, 'GET', '/demo/4/something-else');
 | |
| 
 | |
|         $this->assertEquals('4', $response);
 | |
|     }
 | |
| 
 | |
|     public function testValidMethods()
 | |
|     {
 | |
|         $this->assertEquals(array(
 | |
|             Route::ANY,
 | |
|             Route::GET,
 | |
|             Route::POST,
 | |
|             Route::PUT,
 | |
|             Route::PATCH,
 | |
|             Route::DELETE,
 | |
|             Route::HEAD,
 | |
|             Route::OPTIONS,
 | |
|         ), $this->router()->getValidMethods());
 | |
|     }
 | |
| 
 | |
|     public function testAnyRespondsToDeletePutAndGet()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->any('/user', function(){
 | |
|             return 'yes';
 | |
|         });
 | |
| 
 | |
|         $this->assertEquals('yes', $this->dispatch($r, Route::GET, 'user'));
 | |
|         $this->assertEquals('yes', $this->dispatch($r, Route::DELETE, 'user'));
 | |
|         $this->assertEquals('yes', $this->dispatch($r, Route::PUT, 'user'));
 | |
|         $this->assertEquals('yes', $this->dispatch($r, Route::PATCH, 'user'));
 | |
|         $this->assertEquals('yes', $this->dispatch($r, Route::POST, 'user'));
 | |
|         $this->assertEquals('yes', $this->dispatch($r, Route::OPTIONS, 'user'));
 | |
|         $this->assertEquals('yes', $this->dispatch($r, 'MADE_UP_NON_STANDARD_METHOD', 'user'));
 | |
|     }
 | |
|     
 | |
|     public function testRestfulControllerMethods()
 | |
|     {
 | |
| 
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->controller('/user', __NAMESPACE__ . '\\Test');
 | |
| 
 | |
|         $data = $r->getData();
 | |
| 
 | |
|         $this->assertEquals($r->getValidMethods(), array_keys($data->getStaticRoutes()['user/test']));
 | |
| 
 | |
|         $this->assertEquals(array(Route::ANY), array_keys($data->getStaticRoutes()['user']));
 | |
|         $this->assertEquals(array(Route::ANY), array_keys($data->getStaticRoutes()['user/index']));
 | |
| 
 | |
|         $this->assertEquals('testRouteAnyIndex', $this->dispatch($r, Route::GET, 'user'));
 | |
|         $this->assertEquals('testRouteAnyIndex', $this->dispatch($r, Route::POST, 'user'));
 | |
|         $this->assertEquals('testRouteAnyIndex', $this->dispatch($r, Route::PUT, 'user'));
 | |
|         $this->assertEquals('testRouteAnyIndex', $this->dispatch($r, Route::PATCH, 'user'));
 | |
|         $this->assertEquals('testRouteAnyIndex', $this->dispatch($r, Route::DELETE, 'user'));
 | |
| 
 | |
|         $this->assertEquals('testRouteAnyIndex', $this->dispatch($r, Route::GET, 'user/index'));
 | |
|         $this->assertEquals('testRouteAnyIndex', $this->dispatch($r, Route::POST, 'user/index'));
 | |
|         $this->assertEquals('testRouteAnyIndex', $this->dispatch($r, Route::PUT, 'user/index'));
 | |
|         $this->assertEquals('testRouteAnyIndex', $this->dispatch($r, Route::PATCH, 'user/index'));
 | |
|         $this->assertEquals('testRouteAnyIndex', $this->dispatch($r, Route::DELETE, 'user/index'));
 | |
| 
 | |
|         $this->assertEquals('hyphenated', $this->dispatch($r, Route::GET, 'user/camel-case-hyphenated'));
 | |
| 
 | |
|         $this->assertEquals('joe', $this->dispatch($r, Route::GET, 'user/parameter/joe'));
 | |
|         $this->assertEquals('joe', $this->dispatch($r, Route::GET, 'user/parameter-hyphenated/joe'));
 | |
| 
 | |
|         $this->assertEquals('joe', $this->dispatch($r, Route::GET, 'user/parameter-optional/joe'));
 | |
|         $this->assertEquals('default', $this->dispatch($r, Route::GET, 'user/parameter-optional'));
 | |
|         $this->assertEquals('joedefault', $this->dispatch($r, Route::GET, 'user/parameter-optional-required/joe'));
 | |
|         $this->assertEquals('joegreen', $this->dispatch($r, Route::GET, 'user/parameter-optional-required/joe/green'));
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /**
 | |
|      * @expectedException \Phroute\Phroute\Exception\HttpRouteNotFoundException
 | |
|      * @expectedExceptionMessage does not exist
 | |
|      */
 | |
|     public function testRestfulOptionalRequiredControllerMethodThrows()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->controller('/user', __NAMESPACE__ . '\\Test');
 | |
| 
 | |
|         $this->dispatch($r, Route::GET, 'user/parameter-optional-required');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @expectedException \Phroute\Phroute\Exception\HttpRouteNotFoundException
 | |
|      * @expectedExceptionMessage does not exist
 | |
|      */
 | |
|     public function testRestfulRequiredControllerMethodThrows()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->controller('/user', __NAMESPACE__ . '\\Test');
 | |
| 
 | |
|         $this->dispatch($r, Route::GET, 'user/parameter-required');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @expectedException \Phroute\Phroute\Exception\HttpRouteNotFoundException
 | |
|      * @expectedExceptionMessage does not exist
 | |
|      */
 | |
|     public function testRestfulHyphenateControllerMethodThrows()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->controller('/user', __NAMESPACE__ . '\\Test');
 | |
| 
 | |
|         $this->dispatch($r, Route::GET, 'user/camelcasehyphenated');
 | |
|     }
 | |
| 
 | |
|     public function testHyphenatedRoutes()
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->get('/user-name', function(){
 | |
|             return 'test';
 | |
|         });
 | |
| 
 | |
|         $val = $this->dispatch($r, Route::GET, '/user-name');
 | |
| 
 | |
|         $this->assertEquals('test', $val);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * @dataProvider characterfulRoutes
 | |
|      */
 | |
|     public function testCharacterDynamicRoutes($route, $uri, $expected)
 | |
|     {
 | |
|         $r = $this->router();
 | |
| 
 | |
|         $r->get($route, function(){
 | |
|             return implode(' ', func_get_args());
 | |
|         });
 | |
| 
 | |
|         $val = $this->dispatch($r, Route::GET, $uri);
 | |
| 
 | |
|         $this->assertEquals($expected, $val);
 | |
|     }
 | |
| 
 | |
|     public function characterfulRoutes()
 | |
|     {
 | |
|         return array(
 | |
|             // route / dispatch URI / expected
 | |
|             array('/user-name/{name}', '/user-name/joe', 'joe'),
 | |
|             array('/user_name/{name}', '/user_name/joe', 'joe'),
 | |
|             array('/user+++name/{name}', '/user+++name/joe', 'joe'),
 | |
|             array('/user.name/{name_with_undersc0r3s_n_nums}', '/user.name/joe', 'joe'),
 | |
|             array('/us;er:nam;e/{name}', '/us;er:nam;e/joe', 'joe'),
 | |
|             array('/us%25r:na%20;e/{name}', '/us%25r:na%20;e/joe', 'joe'),
 | |
| 
 | |
|             // Regex characters to check for proper escaping
 | |
|             array('/sta++++tic1', '/sta++++tic1', ''),
 | |
| 
 | |
|             array('/static1/{name}/static2/{country}', '/static1/joe/static2/uk', 'joe uk'),
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     public function testRestfulMethods()
 | |
|     {
 | |
|         
 | |
|         $r = $this->router();
 | |
|         
 | |
|         $methods = $r->getValidMethods();
 | |
|         
 | |
|         foreach($methods as $method)
 | |
|         {
 | |
|             $r->$method('/user','callback');
 | |
|         }
 | |
|         
 | |
|         $data = $r->getData();
 | |
|         
 | |
|         $this->assertEquals($methods, array_keys($data->getStaticRoutes()['user']));
 | |
|     }
 | |
|     
 | |
|     public function provideFoundDispatchCases()
 | |
|     {
 | |
|         $cases = [];
 | |
|         
 | |
|          // 0 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/', function() {
 | |
|                 return true;
 | |
|             });
 | |
|         };
 | |
|         
 | |
|         $cases[] = ['GET', '', $callback, true];
 | |
| 
 | |
|         $cases[] = ['GET', '/', $callback, true];
 | |
|         
 | |
|         
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '', function() {
 | |
|                 return true;
 | |
|             });
 | |
|         };
 | |
|         
 | |
|         $cases[] = ['GET', '', $callback, true];
 | |
| 
 | |
|         $cases[] = ['GET', '/', $callback, true];
 | |
| 
 | |
|         // 0 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/resource/123/456', function() {
 | |
|                 return true;
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', '/resource/123/456', $callback, true];
 | |
|         
 | |
|         
 | |
|         
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', 'resource/123/456', function() {
 | |
|                 return true;
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', 'resource/123/456', $callback, true];
 | |
|         
 | |
|         
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', 'resource/123/456', function() {
 | |
|                 return true;
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', '/resource/123/456', $callback, true];
 | |
| 
 | |
|         // 1 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/handler0', function() {
 | |
|                 
 | |
|             });
 | |
|             $r->addRoute('GET', '/handler1', function() {
 | |
|                 
 | |
|             });
 | |
|             $r->addRoute('GET', '/handler2', function() {
 | |
|                 return true;
 | |
|             });
 | |
|         };
 | |
|         $cases[] = ['GET', '/handler2', $callback, true];
 | |
| 
 | |
|         // 2 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', function($name, $id) {
 | |
|                 return [$name, $id];
 | |
|             });
 | |
|             $r->addRoute('GET', '/user/{id:[0-9]+}', function($id) {
 | |
|                 return $id;
 | |
|             });
 | |
|             $r->addRoute('GET', '/user/{name}', function($name) {
 | |
|                 return $name;
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', '/user/rdlowrey', $callback, 'rdlowrey'];
 | |
| 
 | |
| 
 | |
|         // 3 -------------------------------------------------------------------------------------->
 | |
|         // reuse $callback from #2
 | |
| 
 | |
|         $cases[] = ['GET', '/user/12345', $callback, '12345'];
 | |
| 
 | |
|         // 4 -------------------------------------------------------------------------------------->
 | |
|         // reuse $callback from #3
 | |
| 
 | |
|         $cases[] = ['GET', '/user/NaN', $callback, 'NaN'];
 | |
| 
 | |
|         // 5 -------------------------------------------------------------------------------------->
 | |
|         // reuse $callback from #4
 | |
|         $cases[] = ['GET', '/user/rdlowrey/12345', $callback, ['rdlowrey', '12345']];
 | |
| 
 | |
|         // 6 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function( $r) {
 | |
|             $r->addRoute('GET', '/user/{id:[0-9]+}', function() {
 | |
|                 
 | |
|             });
 | |
|             $r->addRoute('GET', '/user/12345/extension', function() {
 | |
|                 
 | |
|             });
 | |
|             $r->addRoute('GET', '/user/{id:[0-9]+}.{extension}', function($id, $extension) {
 | |
|                 return [$id, $extension];
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', '/user/12345.svg', $callback, ['12345', 'svg']];
 | |
| 
 | |
|         // 7 ----- Test GET method fallback on HEAD route miss ------------------------------------>
 | |
| 
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/user/{name}', function($name) {
 | |
|                 return $name;
 | |
|             });
 | |
|             $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', function($name, $id) {
 | |
|                 return [$name, $id];
 | |
|             });
 | |
|             $r->addRoute('GET', '/static0', function() {
 | |
|                 return 'static0';
 | |
|             });
 | |
|             $r->addRoute('GET', '/static1', function() {
 | |
|                 
 | |
|             });
 | |
|             $r->addRoute('HEAD', '/static1', function() {
 | |
|                 return 'static1head';
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['HEAD', '/user/rdlowrey', $callback, 'rdlowrey'];
 | |
| 
 | |
|         // 8 ----- Test GET method fallback on HEAD route miss ------------------------------------>
 | |
|         // reuse $callback from #7
 | |
|         $cases[] = ['HEAD', '/user/rdlowrey/1234', $callback, ['rdlowrey', '1234']];
 | |
| 
 | |
|         // 9 ----- Test GET method fallback on HEAD route miss ------------------------------------>
 | |
|         // reuse $callback from #8
 | |
| 
 | |
|         $cases[] = ['HEAD', '/static0', $callback, 'static0'];
 | |
| 
 | |
|         // 10 ---- Test existing HEAD route used if available (no fallback) ----------------------->
 | |
|         // reuse $callback from #9
 | |
| 
 | |
|         $cases[] = ['HEAD', '/static1', $callback, 'static1head'];
 | |
| 
 | |
|         // x -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         
 | |
|         // 11 -------------------------------------------------------------------------------------->
 | |
|         // Test optional parameter
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/user/{name}/{id:[0-9]+}?', function($name, $id = null) {
 | |
|                 return [$name, $id];
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', '/user/rdlowrey', $callback, array('rdlowrey', null)];
 | |
|         
 | |
|         // 12
 | |
|         $cases[] = ['GET', '/user/rdlowrey/23', $callback, array('rdlowrey', '23')];
 | |
|         
 | |
|         // 13 -------------------------------------------------------------------------------------->
 | |
|         // Test multiple optional parameters
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/user/{name}/{id:[0-9]+}?/{other}?', function($name, $id = null, $other = null) {
 | |
|                 return [$name, $id, $other];
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', '/user/rdlowrey', $callback, array('rdlowrey', null, null)];
 | |
|         
 | |
|         // 14
 | |
|         $cases[] = ['GET', '/user/rdlowrey/23', $callback, array('rdlowrey', '23', null)];
 | |
|         
 | |
|         //15
 | |
|         $cases[] = ['GET', '/user/rdlowrey/23/blah', $callback, array('rdlowrey', '23', 'blah')];
 | |
|         
 | |
| 
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/user/random_{name}', function($name) {
 | |
|                 return $name;
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         //16
 | |
|         $cases[] = ['GET', '/user/random_rdlowrey', $callback, 'rdlowrey'];
 | |
|         
 | |
|         
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/user/random_{name}?', function($name = null) {
 | |
|                 return $name;
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         //17
 | |
|         $cases[] = ['GET', '/user/random_rdlowrey', $callback, 'rdlowrey'];
 | |
|          //18
 | |
|         $cases[] = ['GET', '/user/random_', $callback, null];
 | |
|         
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '{name}?', function($name = null) {
 | |
|                 return $name;
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         //19
 | |
|         $cases[] = ['GET', 'rdlowrey', $callback, 'rdlowrey'];
 | |
|          //20
 | |
|         $cases[] = ['GET', '/', $callback, null];
 | |
|         
 | |
|         // 11 -------------------------------------------------------------------------------------->
 | |
|         // Test shortcuts parameter
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/user/{id:i}', function($id) {
 | |
|                 return $id;
 | |
|             });
 | |
|             $r->addRoute('GET', '/user1/{idname:a}', function($idname) {
 | |
|                 return array($idname);
 | |
|             });
 | |
|             $r->addRoute('GET', '/user2/{hexcode:h}', function($hexcode) {
 | |
|                 return array($hexcode);
 | |
|             });
 | |
|             $r->addRoute('GET', '/user3/{id:i}/{hexcode:h}?', function($id, $hexcode = null) {
 | |
|                 return array($id, $hexcode);
 | |
|             });
 | |
|             $r->addRoute('GET', '/user4/{slug:c}', function($slug) {
 | |
|                 return array($slug);
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', '/user/21', $callback, '21'];
 | |
|         $cases[] = ['GET', '/user1/abcdezzASd123', $callback, array('abcdezzASd123')];
 | |
|         $cases[] = ['GET', '/user2/abcde123', $callback, array('abcde123')];
 | |
|         $cases[] = ['GET', '/user3/21/abcde123', $callback, array('21','abcde123')];
 | |
|         $cases[] = ['GET', '/user3/21', $callback, array('21', null)];
 | |
|         $cases[] = ['GET', '/user4/test_something-123', $callback, array('test_something-123')];
 | |
|         
 | |
|         
 | |
|         // 11 -------------------------------------------------------------------------------------->
 | |
|         // Test shortcuts parameter
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/user/{id}?/{id2}?/{id3}?', function() {
 | |
|                 return 'first';
 | |
|             });
 | |
|             $r->addRoute('GET', '/user2/{id}?', function() {
 | |
|                 return 'second';
 | |
|             });
 | |
|             $r->addRoute('GET', '/user3/{id}?', function() {
 | |
|                 return 'third';
 | |
|             });
 | |
|             $r->addRoute('GET', '/user4/{id}?/{id2}?/{id3}?', function() {
 | |
|                 return 'fourth';
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', '/user/21', $callback, 'first'];
 | |
|         $cases[] = ['GET', '/user2/abcdezzASd123', $callback, 'second'];
 | |
|         $cases[] = ['GET', '/user2/abcde123', $callback, 'second'];
 | |
|         $cases[] = ['GET', '/user/21/abcde123', $callback, 'first'];
 | |
|         $cases[] = ['GET', '/user2/21', $callback, 'second'];
 | |
|         $cases[] = ['GET', '/user3/abcdezzASd123', $callback, 'third'];
 | |
|         $cases[] = ['GET', '/user3/abcde123', $callback, 'third'];
 | |
|         $cases[] = ['GET', '/user3/21', $callback, 'third'];
 | |
|         $cases[] = ['GET', '/user4/abcdezzASd123', $callback, 'fourth'];
 | |
|         $cases[] = ['GET', '/user4/abcde123', $callback, 'fourth'];
 | |
|         $cases[] = ['GET', '/user4/21', $callback, 'fourth'];
 | |
|         
 | |
|         // 11 -------------------------------------------------------------------------------------->
 | |
|         // Test shortcuts parameter
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', 'ext/{asset}.json', function($asset) {
 | |
|                 return $asset . ' jsonencoded';
 | |
|             });
 | |
|             $r->addRoute('GET', 'ext/{asset}', function($asset) {
 | |
|                 return $asset;
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', 'ext/asset', $callback, 'asset'];
 | |
|         $cases[] = ['GET', 'ext/asset.json', $callback, 'asset jsonencoded'];
 | |
| 
 | |
|         // 12 -------------------------------------------------------------------------------------->
 | |
|         // Test \d{3,4} style quantifiers
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', 'server/{ip:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}}/{name}/{newname}?', function($ip, $name, $newname = null) {
 | |
|                 return trim("$ip $name $newname");
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', 'server/10.10.10.10/server1', $callback, '10.10.10.10 server1'];
 | |
|         $cases[] = ['GET', 'server/0.0.0.0/server2', $callback, '0.0.0.0 server2'];
 | |
|         $cases[] = ['GET', 'server/123.2.23.111/server3/server4', $callback, '123.2.23.111 server3 server4'];
 | |
| 
 | |
|         // 13 -------------------------------------------------------------------------------------->
 | |
|         // Test \d{3,4} style quantifiers
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', 'date/{year:\d{4}}/{month:\d+}?', function($year, $month) {
 | |
|                 return trim("$year $month");
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', 'date/1990/05', $callback, '1990 05'];
 | |
| 
 | |
|         // 14 -------------------------------------------------------------------------------------->
 | |
|         // Test \d{3,4} style quantifiers
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', 'date/{year:\d{4}}/{month:\d{2}}', function($year, $month) {
 | |
|                 return trim("$year $month");
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', 'date/2010/06', $callback, '2010 06'];
 | |
| 
 | |
|         return $cases;
 | |
|     }
 | |
| 
 | |
|     public function provideNotFoundDispatchCases()
 | |
|     {
 | |
|         $cases = [];
 | |
| 
 | |
|         // 0 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function( $r) {
 | |
|             $r->addRoute('GET', '/resource/123/456', 'handler0');
 | |
|         };
 | |
| 
 | |
|         $method = 'GET';
 | |
|         $uri = '/not-found';
 | |
| 
 | |
|         $cases[] = [$method, $uri, $callback];
 | |
| 
 | |
|         // 1 -------------------------------------------------------------------------------------->
 | |
|         // reuse callback from #0
 | |
|         $method = 'POST';
 | |
|         $uri = '/not-found';
 | |
| 
 | |
|         $cases[] = [$method, $uri, $callback];
 | |
| 
 | |
|         // 2 -------------------------------------------------------------------------------------->
 | |
|         // reuse callback from #1
 | |
|         $method = 'PUT';
 | |
|         $uri = '/not-found';
 | |
| 
 | |
|         $cases[] = [$method, $uri, $callback];
 | |
| 
 | |
|         // 3 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function( $r) {
 | |
|             $r->addRoute('GET', '/handler0', 'handler0');
 | |
|             $r->addRoute('GET', '/handler1', 'handler1');
 | |
|             $r->addRoute('GET', '/handler2', 'handler2');
 | |
|         };
 | |
| 
 | |
|         $method = 'GET';
 | |
|         $uri = '/not-found';
 | |
| 
 | |
|         $cases[] = [$method, $uri, $callback];
 | |
| 
 | |
|         // 4 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function( $r) {
 | |
|             $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
 | |
|             $r->addRoute('GET', '/user/{id:[0-9]+}', 'handler1');
 | |
|             $r->addRoute('GET', '/user/{name}', 'handler2');
 | |
|         };
 | |
| 
 | |
|         $method = 'GET';
 | |
|         $uri = '/not-found';
 | |
| 
 | |
|         $cases[] = [$method, $uri, $callback];
 | |
| 
 | |
|         // 5 -------------------------------------------------------------------------------------->
 | |
|         // reuse callback from #4
 | |
|         $method = 'GET';
 | |
|         $uri = '/user/rdlowrey/12345/not-found';
 | |
| 
 | |
|         $cases[] = [$method, $uri, $callback];
 | |
| 
 | |
|         // x -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', '/user/random_{name}?', function($name = null) {
 | |
|                 return $name;
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         //17
 | |
|         $cases[] = ['GET', 'rdlowrey', $callback];
 | |
|         
 | |
|         //19
 | |
|         $cases[] = ['GET', '/user/rdlowrey', $callback, null];
 | |
| 
 | |
| 
 | |
|         // 20 -------------------------------------------------------------------------------------->
 | |
|         // Test \d{3,4} style quantifiers
 | |
|         $callback = function($r) {
 | |
|             $r->addRoute('GET', 'server/{ip:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}}', function($year) {
 | |
|                 return trim("$year");
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         $cases[] = ['GET', 'server/1044.10.10.10', $callback, null];
 | |
|         $cases[] = ['GET', 'server/0.0.0', $callback, null];
 | |
|         $cases[] = ['GET', 'server/.2.23.111', $callback, null];
 | |
|         
 | |
|         return $cases;
 | |
|     }
 | |
| 
 | |
|     public function provideMethodNotAllowedDispatchCases()
 | |
|     {
 | |
|         $cases = [];
 | |
| 
 | |
|         // 0 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function( $r) {
 | |
|             $r->addRoute('GET', '/resource/123/456', 'handler0');
 | |
|         };
 | |
| 
 | |
|         $method = 'POST';
 | |
|         $uri = '/resource/123/456';
 | |
|         $allowedMethods = ['GET'];
 | |
| 
 | |
|         $cases[] = [$method, $uri, $callback, $allowedMethods];
 | |
| 
 | |
|         // 1 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function( $r) {
 | |
|             $r->addRoute('GET', '/resource/123/456', 'handler0');
 | |
|             $r->addRoute('POST', '/resource/123/456', 'handler1');
 | |
|             $r->addRoute('PUT', '/resource/123/456', 'handler2');
 | |
|         };
 | |
| 
 | |
|         $method = 'DELETE';
 | |
|         $uri = '/resource/123/456';
 | |
|         $allowedMethods = ['GET', 'POST', 'PUT'];
 | |
| 
 | |
|         $cases[] = [$method, $uri, $callback, $allowedMethods];
 | |
| 
 | |
|         // 2 -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         $callback = function( $r) {
 | |
|             $r->addRoute('GET', '/user/{name}/{id:[0-9]+}', 'handler0');
 | |
|             $r->addRoute('POST', '/user/{name}/{id:[0-9]+}', 'handler1');
 | |
|             $r->addRoute('PUT', '/user/{name}/{id:[0-9]+}', 'handler2');
 | |
|             $r->addRoute('PATCH', '/user/{name}/{id:[0-9]+}', 'handler3');
 | |
|         };
 | |
| 
 | |
|         $method = 'DELETE';
 | |
|         $uri = '/user/rdlowrey/42';
 | |
|         $allowedMethods = ['GET', 'POST', 'PUT', 'PATCH'];
 | |
| 
 | |
|         $cases[] = [$method, $uri, $callback, $allowedMethods];
 | |
| 
 | |
|         // x -------------------------------------------------------------------------------------->
 | |
| 
 | |
|         return $cases;
 | |
|     }
 | |
| 
 | |
| }
 |