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.
		
		
		
		
		
			
		
			
				
					
					
						
							658 lines
						
					
					
						
							16 KiB
						
					
					
				
			
		
		
	
	
							658 lines
						
					
					
						
							16 KiB
						
					
					
				<?php | 
						|
 | 
						|
namespace yiiunit\framework\web; | 
						|
 | 
						|
use yii\web\UrlManager; | 
						|
use yii\web\UrlRule; | 
						|
use yii\web\Request; | 
						|
use yiiunit\TestCase; | 
						|
 | 
						|
/** | 
						|
 * @group web | 
						|
 */ | 
						|
class UrlRuleTest extends TestCase | 
						|
{ | 
						|
	public function testCreateUrl() | 
						|
	{ | 
						|
		$manager = new UrlManager(['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(['cache' => null]); | 
						|
		$request = new Request(['hostInfo' => 'http://en.example.com']); | 
						|
		$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] : []; | 
						|
				$result = $rule->parseRequest($manager, $request); | 
						|
				if ($route === false) { | 
						|
					$this->assertFalse($result, "Test#$i-$j: $name"); | 
						|
				} else { | 
						|
					$this->assertEquals([$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 [ | 
						|
			[ | 
						|
				'empty pattern', | 
						|
				[ | 
						|
					'pattern' => '', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['post/index', [], ''], | 
						|
					['comment/index', [], false], | 
						|
					['post/index', ['page' => 1], '?page=1'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'without param', | 
						|
				[ | 
						|
					'pattern' => 'posts', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['post/index', [], 'posts'], | 
						|
					['comment/index', [], false], | 
						|
					['post/index', ['page' => 1], 'posts?page=1'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'parsing only', | 
						|
				[ | 
						|
					'pattern' => 'posts', | 
						|
					'route' => 'post/index', | 
						|
					'mode' => UrlRule::PARSING_ONLY, | 
						|
				], | 
						|
				[ | 
						|
					['post/index', [], false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with param', | 
						|
				[ | 
						|
					'pattern' => 'post/<page>', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['post/index', [], false], | 
						|
					['comment/index', [], false], | 
						|
					['post/index', ['page' => 1], 'post/1'], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a'], 'post/1?tag=a'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with param requirement', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 'abc'], false], | 
						|
					['post/index', ['page' => 1], 'post/1'], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a'], 'post/1?tag=a'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with multiple params', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>-<tag>', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => '1abc'], false], | 
						|
					['post/index', ['page' => 1], false], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a'], 'post/1-a'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with optional param', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>/<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 1], false], | 
						|
					['post/index', ['page' => '1abc', 'tag' => 'a'], false], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a'], 'post/a'], | 
						|
					['post/index', ['page' => 2, 'tag' => 'a'], 'post/2/a'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with optional param not in pattern', | 
						|
				[ | 
						|
					'pattern' => 'post/<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 1], false], | 
						|
					['post/index', ['page' => '1abc', 'tag' => 'a'], false], | 
						|
					['post/index', ['page' => 2, 'tag' => 'a'], false], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a'], 'post/a'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'multiple optional params', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>/<tag>/<sort:yes|no>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1, 'sort' => 'yes'], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 1], false], | 
						|
					['post/index', ['page' => '1abc', 'tag' => 'a'], false], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a', 'sort' => 'YES'], false], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a', 'sort' => 'yes'], 'post/a'], | 
						|
					['post/index', ['page' => 2, 'tag' => 'a', 'sort' => 'yes'], 'post/2/a'], | 
						|
					['post/index', ['page' => 2, 'tag' => 'a', 'sort' => 'no'], 'post/2/a/no'], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a', 'sort' => 'no'], 'post/a/no'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'optional param and required param separated by dashes', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>-<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 1], false], | 
						|
					['post/index', ['page' => '1abc', 'tag' => 'a'], false], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a'], 'post/-a'], | 
						|
					['post/index', ['page' => 2, 'tag' => 'a'], 'post/2-a'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'optional param at the end', | 
						|
				[ | 
						|
					'pattern' => 'post/<tag>/<page:\d+>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 1], false], | 
						|
					['post/index', ['page' => '1abc', 'tag' => 'a'], false], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a'], 'post/a'], | 
						|
					['post/index', ['page' => 2, 'tag' => 'a'], 'post/a/2'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'consecutive optional params', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>/<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1, 'tag' => 'a'], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 1], false], | 
						|
					['post/index', ['page' => '1abc', 'tag' => 'a'], false], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a'], 'post'], | 
						|
					['post/index', ['page' => 2, 'tag' => 'a'], 'post/2'], | 
						|
					['post/index', ['page' => 1, 'tag' => 'b'], 'post/b'], | 
						|
					['post/index', ['page' => 2, 'tag' => 'b'], 'post/2/b'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'consecutive optional params separated by dash', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>-<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1, 'tag' => 'a'], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 1], false], | 
						|
					['post/index', ['page' => '1abc', 'tag' => 'a'], false], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a'], 'post/-'], | 
						|
					['post/index', ['page' => 1, 'tag' => 'b'], 'post/-b'], | 
						|
					['post/index', ['page' => 2, 'tag' => 'a'], 'post/2-'], | 
						|
					['post/index', ['page' => 2, 'tag' => 'b'], 'post/2-b'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'route has parameters', | 
						|
				[ | 
						|
					'pattern' => '<controller>/<action>', | 
						|
					'route' => '<controller>/<action>', | 
						|
					'defaults' => [], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 1], 'post/index?page=1'], | 
						|
					['module/post/index', [], false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'route has parameters with regex', | 
						|
				[ | 
						|
					'pattern' => '<controller:post|comment>/<action>', | 
						|
					'route' => '<controller>/<action>', | 
						|
					'defaults' => [], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 1], 'post/index?page=1'], | 
						|
					['comment/index', ['page' => 1], 'comment/index?page=1'], | 
						|
					['test/index', ['page' => 1], false], | 
						|
					['post', [], false], | 
						|
					['module/post/index', [], false], | 
						|
					['post/index', ['controller' => 'comment'], 'post/index?controller=comment'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'route has default parameter', | 
						|
				[ | 
						|
					'pattern' => '<controller:post|comment>/<action>', | 
						|
					'route' => '<controller>/<action>', | 
						|
					'defaults' => ['action' => 'index'], | 
						|
				], | 
						|
				[ | 
						|
					['post/view', ['page' => 1], 'post/view?page=1'], | 
						|
					['comment/view', ['page' => 1], 'comment/view?page=1'], | 
						|
					['test/view', ['page' => 1], false], | 
						|
					['test/index', ['page' => 1], false], | 
						|
					['post/index', ['page' => 1], 'post?page=1'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'empty pattern with suffix', | 
						|
				[ | 
						|
					'pattern' => '', | 
						|
					'route' => 'post/index', | 
						|
					'suffix' => '.html', | 
						|
				], | 
						|
				[ | 
						|
					['post/index', [], ''], | 
						|
					['comment/index', [], false], | 
						|
					['post/index', ['page' => 1], '?page=1'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'regular pattern with suffix', | 
						|
				[ | 
						|
					'pattern' => 'posts', | 
						|
					'route' => 'post/index', | 
						|
					'suffix' => '.html', | 
						|
				], | 
						|
				[ | 
						|
					['post/index', [], 'posts.html'], | 
						|
					['comment/index', [], false], | 
						|
					['post/index', ['page' => 1], 'posts.html?page=1'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'empty pattern with slash suffix', | 
						|
				[ | 
						|
					'pattern' => '', | 
						|
					'route' => 'post/index', | 
						|
					'suffix' => '/', | 
						|
				], | 
						|
				[ | 
						|
					['post/index', [], ''], | 
						|
					['comment/index', [], false], | 
						|
					['post/index', ['page' => 1], '?page=1'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'regular pattern with slash suffix', | 
						|
				[ | 
						|
					'pattern' => 'posts', | 
						|
					'route' => 'post/index', | 
						|
					'suffix' => '/', | 
						|
				], | 
						|
				[ | 
						|
					['post/index', [], 'posts/'], | 
						|
					['comment/index', [], false], | 
						|
					['post/index', ['page' => 1], 'posts/?page=1'], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with host info', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>/<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1], | 
						|
					'host' => 'http://<lang:en|fr>.example.com', | 
						|
				], | 
						|
				[ | 
						|
					['post/index', ['page' => 1, 'tag' => 'a'], false], | 
						|
					['post/index', ['page' => 1, 'tag' => 'a', 'lang' => 'en'], 'http://en.example.com/post/a'], | 
						|
				], | 
						|
			], | 
						|
		]; | 
						|
	} | 
						|
 | 
						|
	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 [ | 
						|
			[ | 
						|
				'empty pattern', | 
						|
				[ | 
						|
					'pattern' => '', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['', 'post/index'], | 
						|
					['a', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'without param', | 
						|
				[ | 
						|
					'pattern' => 'posts', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['posts', 'post/index'], | 
						|
					['a', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with dot', // https://github.com/yiisoft/yii/issues/2945 | 
						|
				[ | 
						|
					'pattern' => 'posts.html', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['posts.html', 'post/index'], | 
						|
					['postsahtml', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'creation only', | 
						|
				[ | 
						|
					'pattern' => 'posts', | 
						|
					'route' => 'post/index', | 
						|
					'mode' => UrlRule::CREATION_ONLY, | 
						|
				], | 
						|
				[ | 
						|
					['posts', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with param', | 
						|
				[ | 
						|
					'pattern' => 'post/<page>', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['post/1', 'post/index', ['page' => '1']], | 
						|
					['post/a', 'post/index', ['page' => 'a']], | 
						|
					['post', false], | 
						|
					['posts', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with param requirement', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['post/1', 'post/index', ['page' => '1']], | 
						|
					['post/a', false], | 
						|
					['post/1/a', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with multiple params', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>-<tag>', | 
						|
					'route' => 'post/index', | 
						|
				], | 
						|
				[ | 
						|
					['post/1-a', 'post/index', ['page' => '1', 'tag' => 'a']], | 
						|
					['post/a', false], | 
						|
					['post/1', false], | 
						|
					['post/1/a', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with optional param', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>/<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1], | 
						|
				], | 
						|
				[ | 
						|
					['post/1/a', 'post/index', ['page' => '1', 'tag' => 'a']], | 
						|
					['post/2/a', 'post/index', ['page' => '2', 'tag' => 'a']], | 
						|
					['post/a', 'post/index', ['page' => '1', 'tag' => 'a']], | 
						|
					['post/1', 'post/index', ['page' => '1', 'tag' => '1']], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with optional param not in pattern', | 
						|
				[ | 
						|
					'pattern' => 'post/<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1], | 
						|
				], | 
						|
				[ | 
						|
					['post/a', 'post/index', ['page' => '1', 'tag' => 'a']], | 
						|
					['post/1', 'post/index', ['page' => '1', 'tag' => '1']], | 
						|
					['post', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'multiple optional params', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>/<tag>/<sort:yes|no>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1, 'sort' => 'yes'], | 
						|
				], | 
						|
				[ | 
						|
					['post/1/a/yes', 'post/index', ['page' => '1', 'tag' => 'a', 'sort' => 'yes']], | 
						|
					['post/1/a/no', 'post/index', ['page' => '1', 'tag' => 'a', 'sort' => 'no']], | 
						|
					['post/2/a/no', 'post/index', ['page' => '2', 'tag' => 'a', 'sort' => 'no']], | 
						|
					['post/2/a', 'post/index', ['page' => '2', 'tag' => 'a', 'sort' => 'yes']], | 
						|
					['post/a/no', 'post/index', ['page' => '1', 'tag' => 'a', 'sort' => 'no']], | 
						|
					['post/a', 'post/index', ['page' => '1', 'tag' => 'a', 'sort' => 'yes']], | 
						|
					['post', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'optional param and required param separated by dashes', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>-<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1], | 
						|
				], | 
						|
				[ | 
						|
					['post/1-a', 'post/index', ['page' => '1', 'tag' => 'a']], | 
						|
					['post/2-a', 'post/index', ['page' => '2', 'tag' => 'a']], | 
						|
					['post/-a', 'post/index', ['page' => '1', 'tag' => 'a']], | 
						|
					['post/a', false], | 
						|
					['post-a', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'optional param at the end', | 
						|
				[ | 
						|
					'pattern' => 'post/<tag>/<page:\d+>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1], | 
						|
				], | 
						|
				[ | 
						|
					['post/a/1', 'post/index', ['page' => '1', 'tag' => 'a']], | 
						|
					['post/a/2', 'post/index', ['page' => '2', 'tag' => 'a']], | 
						|
					['post/a', 'post/index', ['page' => '1', 'tag' => 'a']], | 
						|
					['post/2', 'post/index', ['page' => '1', 'tag' => '2']], | 
						|
					['post', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'consecutive optional params', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>/<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1, 'tag' => 'a'], | 
						|
				], | 
						|
				[ | 
						|
					['post/2/b', 'post/index', ['page' => '2', 'tag' => 'b']], | 
						|
					['post/2', 'post/index', ['page' => '2', 'tag' => 'a']], | 
						|
					['post', 'post/index', ['page' => '1', 'tag' => 'a']], | 
						|
					['post/b', 'post/index', ['page' => '1', 'tag' => 'b']], | 
						|
					['post//b', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'consecutive optional params separated by dash', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>-<tag>', | 
						|
					'route' => 'post/index', | 
						|
					'defaults' => ['page' => 1, 'tag' => 'a'], | 
						|
				], | 
						|
				[ | 
						|
					['post/2-b', 'post/index', ['page' => '2', 'tag' => 'b']], | 
						|
					['post/2-', 'post/index', ['page' => '2', 'tag' => 'a']], | 
						|
					['post/-b', 'post/index', ['page' => '1', 'tag' => 'b']], | 
						|
					['post/-', 'post/index', ['page' => '1', 'tag' => 'a']], | 
						|
					['post', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'route has parameters', | 
						|
				[ | 
						|
					'pattern' => '<controller>/<action>', | 
						|
					'route' => '<controller>/<action>', | 
						|
					'defaults' => [], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', 'post/index'], | 
						|
					['module/post/index', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'route has parameters with regex', | 
						|
				[ | 
						|
					'pattern' => '<controller:post|comment>/<action>', | 
						|
					'route' => '<controller>/<action>', | 
						|
					'defaults' => [], | 
						|
				], | 
						|
				[ | 
						|
					['post/index', 'post/index'], | 
						|
					['comment/index', 'comment/index'], | 
						|
					['test/index', false], | 
						|
					['post', false], | 
						|
					['module/post/index', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'route has default parameter', | 
						|
				[ | 
						|
					'pattern' => '<controller:post|comment>/<action>', | 
						|
					'route' => '<controller>/<action>', | 
						|
					'defaults' => ['action' => 'index'], | 
						|
				], | 
						|
				[ | 
						|
					['post/view', 'post/view'], | 
						|
					['comment/view', 'comment/view'], | 
						|
					['test/view', false], | 
						|
					['post', 'post/index'], | 
						|
					['posts', false], | 
						|
					['test', false], | 
						|
					['index', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'empty pattern with suffix', | 
						|
				[ | 
						|
					'pattern' => '', | 
						|
					'route' => 'post/index', | 
						|
					'suffix' => '.html', | 
						|
				], | 
						|
				[ | 
						|
					['', 'post/index'], | 
						|
					['.html', false], | 
						|
					['a.html', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'regular pattern with suffix', | 
						|
				[ | 
						|
					'pattern' => 'posts', | 
						|
					'route' => 'post/index', | 
						|
					'suffix' => '.html', | 
						|
				], | 
						|
				[ | 
						|
					['posts.html', 'post/index'], | 
						|
					['posts', false], | 
						|
					['posts.HTML', false], | 
						|
					['a.html', false], | 
						|
					['a', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'empty pattern with slash suffix', | 
						|
				[ | 
						|
					'pattern' => '', | 
						|
					'route' => 'post/index', | 
						|
					'suffix' => '/', | 
						|
				], | 
						|
				[ | 
						|
					['', 'post/index'], | 
						|
					['a', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'regular pattern with slash suffix', | 
						|
				[ | 
						|
					'pattern' => 'posts', | 
						|
					'route' => 'post/index', | 
						|
					'suffix' => '/', | 
						|
				], | 
						|
				[ | 
						|
					['posts/', 'post/index'], | 
						|
					['posts', false], | 
						|
					['a', false], | 
						|
				], | 
						|
			], | 
						|
			[ | 
						|
				'with host info', | 
						|
				[ | 
						|
					'pattern' => 'post/<page:\d+>', | 
						|
					'route' => 'post/index', | 
						|
					'host' => 'http://<lang:en|fr>.example.com', | 
						|
				], | 
						|
				[ | 
						|
					['post/1', 'post/index', ['page' => '1', 'lang' => 'en']], | 
						|
					['post/a', false], | 
						|
					['post/1/a', false], | 
						|
				], | 
						|
			], | 
						|
		]; | 
						|
	} | 
						|
}
 | 
						|
 |