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(array('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] : 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/', '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/', '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/-', '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//', '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/', '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///', '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/-', '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//', '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//', '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/-', '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' => '/', 'route' => '/', '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' => '/', 'route' => '/', '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' => '/', 'route' => '/', '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'), ), ), array( 'with host info', array( 'pattern' => 'post//', 'route' => 'post/index', 'defaults' => array('page' => 1), 'host' => 'http://.example.com', ), array( array('post/index', array('page' => 1, 'tag' => 'a'), false), array('post/index', array('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 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( 'with dot', // https://github.com/yiisoft/yii/issues/2945 array( 'pattern' => 'posts.html', 'route' => 'post/index', ), array( array('posts.html', 'post/index'), array('postsahtml', false), ), ), array( 'creation only', array( 'pattern' => 'posts', 'route' => 'post/index', 'mode' => UrlRule::CREATION_ONLY, ), array( array('posts', false), ), ), array( 'with param', array( 'pattern' => 'post/', '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/', '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/-', '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//', '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/', '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///', '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/1/a/no', 'post/index', array('page' => '1', 'tag' => 'a', 'sort' => 'no')), 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/-', '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//', '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//', '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/-', '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' => '/', 'route' => '/', 'defaults' => array(), ), array( array('post/index', 'post/index'), array('module/post/index', false), ), ), array( 'route has parameters with regex', array( 'pattern' => '/', 'route' => '/', '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' => '/', 'route' => '/', '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('posts', false), array('a', false), ), ), array( 'with host info', array( 'pattern' => 'post/', 'route' => 'post/index', 'host' => 'http://.example.com', ), array( array('post/1', 'post/index', array('page' => '1', 'lang' => 'en')), array('post/a', false), array('post/1/a', false), ), ), ); } }