You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							615 lines
						
					
					
						
							17 KiB
						
					
					
				
			
		
		
	
	
							615 lines
						
					
					
						
							17 KiB
						
					
					
				| <?php | |
|  | |
| namespace yiiunit\framework\web; | |
|  | |
| use yii\web\UrlManager; | |
| use yii\web\UrlRule; | |
| use yii\web\Request; | |
|  | |
| class UrlRuleTest extends \yiiunit\TestCase | |
| { | |
| 	public function testCreateUrl() | |
| 	{ | |
| 		$manager = new UrlManager(array('cache' => null)); | |
| 		$suites = $this->getTestsForCreateUrl(); | |
| 		foreach ($suites as $i => $suite) { | |
| 			list ($name, $config, $tests) = $suite; | |
| 			$rule = new UrlRule($config); | |
| 			foreach ($tests as $j => $test) { | |
| 				list ($route, $params, $expected) = $test; | |
| 				$url = $rule->createUrl($manager, $route, $params); | |
| 				$this->assertEquals($expected, $url, "Test#$i-$j: $name"); | |
| 			} | |
| 		} | |
| 	} | |
|  | |
| 	public function testParseRequest() | |
| 	{ | |
| 		$manager = new UrlManager(array('cache' => null)); | |
| 		$request = new Request; | |
| 		$suites = $this->getTestsForParseRequest(); | |
| 		foreach ($suites as $i => $suite) { | |
| 			list ($name, $config, $tests) = $suite; | |
| 			$rule = new UrlRule($config); | |
| 			foreach ($tests as $j => $test) { | |
| 				$request->pathInfo = $test[0]; | |
| 				$route = $test[1]; | |
| 				$params = isset($test[2]) ? $test[2] : array(); | |
| 				$result = $rule->parseRequest($manager, $request); | |
| 				if ($route === false) { | |
| 					$this->assertFalse($result, "Test#$i-$j: $name"); | |
| 				} else { | |
| 					$this->assertEquals(array($route, $params), $result, "Test#$i-$j: $name"); | |
| 				} | |
| 			} | |
| 		} | |
| 	} | |
|  | |
| 	protected function getTestsForCreateUrl() | |
| 	{ | |
| 		// structure of each test | |
| 		//   message for the test | |
| 		//   config for the URL rule | |
| 		//   list of inputs and outputs | |
| 		//     route | |
| 		//     params | |
| 		//     expected output | |
| 		return array( | |
| 			array( | |
| 				'empty pattern', | |
| 				array( | |
| 					'pattern' => '', | |
| 					'route' => 'post/index', | |
| 				), | |
| 				array( | |
| 					array('post/index', array(), ''), | |
| 					array('comment/index', array(), false), | |
| 					array('post/index', array('page' => 1), '?page=1'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'without param', | |
| 				array( | |
| 					'pattern' => 'posts', | |
| 					'route' => 'post/index', | |
| 				), | |
| 				array( | |
| 					array('post/index', array(), 'posts'), | |
| 					array('comment/index', array(), false), | |
| 					array('post/index', array('page' => 1), 'posts?page=1'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'parsing only', | |
| 				array( | |
| 					'pattern' => 'posts', | |
| 					'route' => 'post/index', | |
| 					'mode' => UrlRule::PARSING_ONLY, | |
| 				), | |
| 				array( | |
| 					array('post/index', array(), false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'with param', | |
| 				array( | |
| 					'pattern' => 'post/<page>', | |
| 					'route' => 'post/index', | |
| 				), | |
| 				array( | |
| 					array('post/index', array(), false), | |
| 					array('comment/index', array(), false), | |
| 					array('post/index', array('page' => 1), 'post/1'), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a'), 'post/1?tag=a'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'with param requirement', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>', | |
| 					'route' => 'post/index', | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => 'abc'), false), | |
| 					array('post/index', array('page' => 1), 'post/1'), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a'), 'post/1?tag=a'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'with multiple params', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>-<tag>', | |
| 					'route' => 'post/index', | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => '1abc'), false), | |
| 					array('post/index', array('page' => 1), false), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a'), 'post/1-a'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'with optional param', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>/<tag>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1), | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => 1), false), | |
| 					array('post/index', array('page' => '1abc', 'tag' => 'a'), false), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a'), 'post/a'), | |
| 					array('post/index', array('page' => 2, 'tag' => 'a'), 'post/2/a'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'with optional param not in pattern', | |
| 				array( | |
| 					'pattern' => 'post/<tag>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1), | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => 1), false), | |
| 					array('post/index', array('page' => '1abc', 'tag' => 'a'), false), | |
| 					array('post/index', array('page' => 2, 'tag' => 'a'), false), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a'), 'post/a'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'multiple optional params', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>/<tag>/<sort:yes|no>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1, 'sort' => 'yes'), | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => 1), false), | |
| 					array('post/index', array('page' => '1abc', 'tag' => 'a'), false), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a', 'sort' => 'YES'), false), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a', 'sort' => 'yes'), 'post/a'), | |
| 					array('post/index', array('page' => 2, 'tag' => 'a', 'sort' => 'yes'), 'post/2/a'), | |
| 					array('post/index', array('page' => 2, 'tag' => 'a', 'sort' => 'no'), 'post/2/a/no'), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a', 'sort' => 'no'), 'post/a/no'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'optional param and required param separated by dashes', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>-<tag>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1), | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => 1), false), | |
| 					array('post/index', array('page' => '1abc', 'tag' => 'a'), false), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a'), 'post/-a'), | |
| 					array('post/index', array('page' => 2, 'tag' => 'a'), 'post/2-a'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'optional param at the end', | |
| 				array( | |
| 					'pattern' => 'post/<tag>/<page:\d+>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1), | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => 1), false), | |
| 					array('post/index', array('page' => '1abc', 'tag' => 'a'), false), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a'), 'post/a'), | |
| 					array('post/index', array('page' => 2, 'tag' => 'a'), 'post/a/2'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'consecutive optional params', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>/<tag>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1, 'tag' => 'a'), | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => 1), false), | |
| 					array('post/index', array('page' => '1abc', 'tag' => 'a'), false), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a'), 'post'), | |
| 					array('post/index', array('page' => 2, 'tag' => 'a'), 'post/2'), | |
| 					array('post/index', array('page' => 1, 'tag' => 'b'), 'post/b'), | |
| 					array('post/index', array('page' => 2, 'tag' => 'b'), 'post/2/b'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'consecutive optional params separated by dash', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>-<tag>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1, 'tag' => 'a'), | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => 1), false), | |
| 					array('post/index', array('page' => '1abc', 'tag' => 'a'), false), | |
| 					array('post/index', array('page' => 1, 'tag' => 'a'), 'post/-'), | |
| 					array('post/index', array('page' => 1, 'tag' => 'b'), 'post/-b'), | |
| 					array('post/index', array('page' => 2, 'tag' => 'a'), 'post/2-'), | |
| 					array('post/index', array('page' => 2, 'tag' => 'b'), 'post/2-b'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'route has parameters', | |
| 				array( | |
| 					'pattern' => '<controller>/<action>', | |
| 					'route' => '<controller>/<action>', | |
| 					'defaults' => array(), | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => 1), 'post/index?page=1'), | |
| 					array('module/post/index', array(), false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'route has parameters with regex', | |
| 				array( | |
| 					'pattern' => '<controller:post|comment>/<action>', | |
| 					'route' => '<controller>/<action>', | |
| 					'defaults' => array(), | |
| 				), | |
| 				array( | |
| 					array('post/index', array('page' => 1), 'post/index?page=1'), | |
| 					array('comment/index', array('page' => 1), 'comment/index?page=1'), | |
| 					array('test/index', array('page' => 1), false), | |
| 					array('post', array(), false), | |
| 					array('module/post/index', array(), false), | |
| 					array('post/index', array('controller' => 'comment'), 'post/index?controller=comment'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'route has default parameter', | |
| 				array( | |
| 					'pattern' => '<controller:post|comment>/<action>', | |
| 					'route' => '<controller>/<action>', | |
| 					'defaults' => array('action' => 'index'), | |
| 				), | |
| 				array( | |
| 					array('post/view', array('page' => 1), 'post/view?page=1'), | |
| 					array('comment/view', array('page' => 1), 'comment/view?page=1'), | |
| 					array('test/view', array('page' => 1), false), | |
| 					array('test/index', array('page' => 1), false), | |
| 					array('post/index', array('page' => 1), 'post?page=1'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'empty pattern with suffix', | |
| 				array( | |
| 					'pattern' => '', | |
| 					'route' => 'post/index', | |
| 					'suffix' => '.html', | |
| 				), | |
| 				array( | |
| 					array('post/index', array(), ''), | |
| 					array('comment/index', array(), false), | |
| 					array('post/index', array('page' => 1), '?page=1'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'regular pattern with suffix', | |
| 				array( | |
| 					'pattern' => 'posts', | |
| 					'route' => 'post/index', | |
| 					'suffix' => '.html', | |
| 				), | |
| 				array( | |
| 					array('post/index', array(), 'posts.html'), | |
| 					array('comment/index', array(), false), | |
| 					array('post/index', array('page' => 1), 'posts.html?page=1'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'empty pattern with slash suffix', | |
| 				array( | |
| 					'pattern' => '', | |
| 					'route' => 'post/index', | |
| 					'suffix' => '/', | |
| 				), | |
| 				array( | |
| 					array('post/index', array(), ''), | |
| 					array('comment/index', array(), false), | |
| 					array('post/index', array('page' => 1), '?page=1'), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'regular pattern with slash suffix', | |
| 				array( | |
| 					'pattern' => 'posts', | |
| 					'route' => 'post/index', | |
| 					'suffix' => '/', | |
| 				), | |
| 				array( | |
| 					array('post/index', array(), 'posts/'), | |
| 					array('comment/index', array(), false), | |
| 					array('post/index', array('page' => 1), 'posts/?page=1'), | |
| 				), | |
| 			), | |
| 		); | |
| 	} | |
|  | |
| 	protected function getTestsForParseRequest() | |
| 	{ | |
| 		// structure of each test | |
| 		//   message for the test | |
| 		//   config for the URL rule | |
| 		//   list of inputs and outputs | |
| 		//     pathInfo | |
| 		//     expected route, or false if the rule doesn't apply | |
| 		//     expected params, or not set if empty | |
| 		return array( | |
| 			array( | |
| 				'empty pattern', | |
| 				array( | |
| 					'pattern' => '', | |
| 					'route' => 'post/index', | |
| 				), | |
| 				array( | |
| 					array('', 'post/index'), | |
| 					array('a', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'without param', | |
| 				array( | |
| 					'pattern' => 'posts', | |
| 					'route' => 'post/index', | |
| 				), | |
| 				array( | |
| 					array('posts', 'post/index'), | |
| 					array('a', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'creation only', | |
| 				array( | |
| 					'pattern' => 'posts', | |
| 					'route' => 'post/index', | |
| 					'mode' => UrlRule::CREATION_ONLY, | |
| 				), | |
| 				array( | |
| 					array('posts', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'with param', | |
| 				array( | |
| 					'pattern' => 'post/<page>', | |
| 					'route' => 'post/index', | |
| 				), | |
| 				array( | |
| 					array('post/1', 'post/index', array('page' => '1')), | |
| 					array('post/a', 'post/index', array('page' => 'a')), | |
| 					array('post', false), | |
| 					array('posts', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'with param requirement', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>', | |
| 					'route' => 'post/index', | |
| 				), | |
| 				array( | |
| 					array('post/1', 'post/index', array('page' => '1')), | |
| 					array('post/a', false), | |
| 					array('post/1/a', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'with multiple params', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>-<tag>', | |
| 					'route' => 'post/index', | |
| 				), | |
| 				array( | |
| 					array('post/1-a', 'post/index', array('page' => '1', 'tag' => 'a')), | |
| 					array('post/a', false), | |
| 					array('post/1', false), | |
| 					array('post/1/a', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'with optional param', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>/<tag>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1), | |
| 				), | |
| 				array( | |
| 					array('post/1/a', 'post/index', array('page' => '1', 'tag' => 'a')), | |
| 					array('post/2/a', 'post/index', array('page' => '2', 'tag' => 'a')), | |
| 					array('post/a', 'post/index', array('page' => '1', 'tag' => 'a')), | |
| 					array('post/1', 'post/index', array('page' => '1', 'tag' => '1')), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'with optional param not in pattern', | |
| 				array( | |
| 					'pattern' => 'post/<tag>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1), | |
| 				), | |
| 				array( | |
| 					array('post/a', 'post/index', array('page' => '1', 'tag' => 'a')), | |
| 					array('post/1', 'post/index', array('page' => '1', 'tag' => '1')), | |
| 					array('post', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'multiple optional params', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>/<tag>/<sort:yes|no>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1, 'sort' => 'yes'), | |
| 				), | |
| 				array( | |
| 					array('post/1/a/yes', 'post/index', array('page' => '1', 'tag' => 'a', 'sort' => 'yes')), | |
| 					array('post/2/a/no', 'post/index', array('page' => '2', 'tag' => 'a', 'sort' => 'no')), | |
| 					array('post/2/a', 'post/index', array('page' => '2', 'tag' => 'a', 'sort' => 'yes')), | |
| 					array('post/a/no', 'post/index', array('page' => '1', 'tag' => 'a', 'sort' => 'no')), | |
| 					array('post/a', 'post/index', array('page' => '1', 'tag' => 'a', 'sort' => 'yes')), | |
| 					array('post', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'optional param and required param separated by dashes', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>-<tag>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1), | |
| 				), | |
| 				array( | |
| 					array('post/1-a', 'post/index', array('page' => '1', 'tag' => 'a')), | |
| 					array('post/2-a', 'post/index', array('page' => '2', 'tag' => 'a')), | |
| 					array('post/-a', 'post/index', array('page' => '1', 'tag' => 'a')), | |
| 					array('post/a', false), | |
| 					array('post-a', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'optional param at the end', | |
| 				array( | |
| 					'pattern' => 'post/<tag>/<page:\d+>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1), | |
| 				), | |
| 				array( | |
| 					array('post/a/1', 'post/index', array('page' => '1', 'tag' => 'a')), | |
| 					array('post/a/2', 'post/index', array('page' => '2', 'tag' => 'a')), | |
| 					array('post/a', 'post/index', array('page' => '1', 'tag' => 'a')), | |
| 					array('post/2', 'post/index', array('page' => '1', 'tag' => '2')), | |
| 					array('post', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'consecutive optional params', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>/<tag>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1, 'tag' => 'a'), | |
| 				), | |
| 				array( | |
| 					array('post/2/b', 'post/index', array('page' => '2', 'tag' => 'b')), | |
| 					array('post/2', 'post/index', array('page' => '2', 'tag' => 'a')), | |
| 					array('post', 'post/index', array('page' => '1', 'tag' => 'a')), | |
| 					array('post/b', 'post/index', array('page' => '1', 'tag' => 'b')), | |
| 					array('post//b', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'consecutive optional params separated by dash', | |
| 				array( | |
| 					'pattern' => 'post/<page:\d+>-<tag>', | |
| 					'route' => 'post/index', | |
| 					'defaults' => array('page' => 1, 'tag' => 'a'), | |
| 				), | |
| 				array( | |
| 					array('post/2-b', 'post/index', array('page' => '2', 'tag' => 'b')), | |
| 					array('post/2-', 'post/index', array('page' => '2', 'tag' => 'a')), | |
| 					array('post/-b', 'post/index', array('page' => '1', 'tag' => 'b')), | |
| 					array('post/-', 'post/index', array('page' => '1', 'tag' => 'a')), | |
| 					array('post', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'route has parameters', | |
| 				array( | |
| 					'pattern' => '<controller>/<action>', | |
| 					'route' => '<controller>/<action>', | |
| 					'defaults' => array(), | |
| 				), | |
| 				array( | |
| 					array('post/index', 'post/index'), | |
| 					array('module/post/index', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'route has parameters with regex', | |
| 				array( | |
| 					'pattern' => '<controller:post|comment>/<action>', | |
| 					'route' => '<controller>/<action>', | |
| 					'defaults' => array(), | |
| 				), | |
| 				array( | |
| 					array('post/index', 'post/index'), | |
| 					array('comment/index', 'comment/index'), | |
| 					array('test/index', false), | |
| 					array('post', false), | |
| 					array('module/post/index', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'route has default parameter', | |
| 				array( | |
| 					'pattern' => '<controller:post|comment>/<action>', | |
| 					'route' => '<controller>/<action>', | |
| 					'defaults' => array('action' => 'index'), | |
| 				), | |
| 				array( | |
| 					array('post/view', 'post/view'), | |
| 					array('comment/view', 'comment/view'), | |
| 					array('test/view', false), | |
| 					array('post', 'post/index'), | |
| 					array('posts', false), | |
| 					array('test', false), | |
| 					array('index', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'empty pattern with suffix', | |
| 				array( | |
| 					'pattern' => '', | |
| 					'route' => 'post/index', | |
| 					'suffix' => '.html', | |
| 				), | |
| 				array( | |
| 					array('', 'post/index'), | |
| 					array('.html', false), | |
| 					array('a.html', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'regular pattern with suffix', | |
| 				array( | |
| 					'pattern' => 'posts', | |
| 					'route' => 'post/index', | |
| 					'suffix' => '.html', | |
| 				), | |
| 				array( | |
| 					array('posts.html', 'post/index'), | |
| 					array('posts', false), | |
| 					array('posts.HTML', false), | |
| 					array('a.html', false), | |
| 					array('a', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'empty pattern with slash suffix', | |
| 				array( | |
| 					'pattern' => '', | |
| 					'route' => 'post/index', | |
| 					'suffix' => '/', | |
| 				), | |
| 				array( | |
| 					array('', 'post/index'), | |
| 					array('a', false), | |
| 				), | |
| 			), | |
| 			array( | |
| 				'regular pattern with slash suffix', | |
| 				array( | |
| 					'pattern' => 'posts', | |
| 					'route' => 'post/index', | |
| 					'suffix' => '/', | |
| 				), | |
| 				array( | |
| 					array('posts', 'post/index'), | |
| 					array('a', false), | |
| 				), | |
| 			), | |
| 		); | |
| 	} | |
| }
 | |
| 
 |