1<?php defined('SYSPATH') OR die('Kohana bootstrap needs to be included before tests run'); 2 3/** 4 * Description of RouteTest 5 * 6 * @group kohana 7 * @group kohana.core 8 * @group kohana.core.route 9 * 10 * @package Kohana 11 * @category Tests 12 * @author Kohana Team 13 * @author BRMatt <matthew@sigswitch.com> 14 * @copyright (c) 2008-2012 Kohana Team 15 * @license http://kohanaframework.org/license 16 */ 17 18include Kohana::find_file('tests', 'test_data/callback_routes'); 19 20class Kohana_RouteTest extends Unittest_TestCase 21{ 22 /** 23 * Remove all caches 24 */ 25 // @codingStandardsIgnoreStart 26 public function setUp() 27 // @codingStandardsIgnoreEnd 28 { 29 parent::setUp(); 30 31 Kohana::$config->load('url')->set('trusted_hosts', array('kohanaframework\.org')); 32 33 $this->cleanCacheDir(); 34 } 35 36 /** 37 * Removes cache files created during tests 38 */ 39 // @codingStandardsIgnoreStart 40 public function tearDown() 41 // @codingStandardsIgnoreEnd 42 { 43 parent::tearDown(); 44 45 $this->cleanCacheDir(); 46 } 47 48 /** 49 * If Route::get() is asked for a route that does not exist then 50 * it should throw a Kohana_Exception 51 * 52 * Note use of @expectedException 53 * 54 * @test 55 * @covers Route::get 56 * @expectedException Kohana_Exception 57 */ 58 public function test_get_throws_exception_if_route_dnx() 59 { 60 Route::get('HAHAHAHAHAHAHAHAHA'); 61 } 62 63 /** 64 * Route::all() should return all routes defined via Route::set() 65 * and not through new Route() 66 * 67 * @test 68 * @covers Route::all 69 */ 70 public function test_all_returns_all_defined_routes() 71 { 72 $defined_routes = self::readAttribute('Route', '_routes'); 73 74 $this->assertSame($defined_routes, Route::all()); 75 } 76 77 /** 78 * Route::name() should fetch the name of a passed route 79 * If route is not found then it should return FALSE 80 * 81 * @TODO: This test needs to segregate the Route::$_routes singleton 82 * @test 83 * @covers Route::name 84 */ 85 public function test_name_returns_routes_name_or_false_if_dnx() 86 { 87 $route = Route::set('flamingo_people', 'flamingo/dance'); 88 89 $this->assertSame('flamingo_people', Route::name($route)); 90 91 $route = new Route('dance/dance'); 92 93 $this->assertFalse(Route::name($route)); 94 } 95 96 /** 97 * If Route::cache() was able to restore routes from the cache then 98 * it should return TRUE and load the cached routes 99 * 100 * @test 101 * @covers Route::cache 102 */ 103 public function test_cache_stores_route_objects() 104 { 105 $routes = Route::all(); 106 107 // First we create the cache 108 Route::cache(TRUE); 109 110 // Now lets modify the "current" routes 111 Route::set('nonsensical_route', 'flabbadaga/ding_dong'); 112 113 // Then try and load said cache 114 $this->assertTrue(Route::cache()); 115 116 // Check the route cache flag 117 $this->assertTrue(Route::$cache); 118 119 // And if all went ok the nonsensical route should be gone... 120 $this->assertEquals($routes, Route::all()); 121 } 122 123 /** 124 * Check appending cached routes. See http://dev.kohanaframework.org/issues/4347 125 * 126 * @test 127 * @covers Route::cache 128 */ 129 public function test_cache_append_routes() 130 { 131 $cached = Route::all(); 132 133 // First we create the cache 134 Route::cache(TRUE); 135 136 // Now lets modify the "current" routes 137 Route::set('nonsensical_route', 'flabbadaga/ding_dong'); 138 139 $modified = Route::all(); 140 141 // Then try and load said cache 142 $this->assertTrue(Route::cache(NULL, TRUE)); 143 144 // Check the route cache flag 145 $this->assertTrue(Route::$cache); 146 147 // And if all went ok the nonsensical route should exist with the other routes... 148 $this->assertEquals(Route::all(), $cached + $modified); 149 } 150 151 /** 152 * Route::cache() should return FALSE if cached routes could not be found 153 * 154 * The cache is cleared before and after each test in setUp tearDown 155 * by cleanCacheDir() 156 * 157 * @test 158 * @covers Route::cache 159 */ 160 public function test_cache_returns_false_if_cache_dnx() 161 { 162 $this->assertSame(FALSE, Route::cache(), 'Route cache was not empty'); 163 164 // Check the route cache flag 165 $this->assertFalse(Route::$cache); 166 } 167 168 /** 169 * If the constructor is passed a NULL uri then it should assume it's 170 * being loaded from the cache & therefore shouldn't override the cached attributes 171 * 172 * @test 173 * @covers Route::__construct 174 */ 175 public function test_constructor_returns_if_uri_is_null() 176 { 177 // We use a mock object to make sure that the route wasn't recompiled 178 $route = $this->getMock('Route', array('_compile'), array(), '', FALSE); 179 180 $route 181 ->expects($this->never()) 182 ->method('_compile'); 183 184 $route->__construct(NULL,NULL); 185 186 $this->assertAttributeSame('', '_uri', $route); 187 $this->assertAttributeSame(array(), '_regex', $route); 188 $this->assertAttributeSame(array('action' => 'index', 'host' => FALSE), '_defaults', $route); 189 $this->assertAttributeSame(NULL, '_route_regex', $route); 190 } 191 192 /** 193 * Provider for test_constructor_only_changes_custom_regex_if_passed 194 * 195 * @return array 196 */ 197 public function provider_constructor_only_changes_custom_regex_if_passed() 198 { 199 return array( 200 array('<controller>/<action>', '<controller>/<action>'), 201 ); 202 } 203 204 /** 205 * The constructor should only use custom regex if passed a non-empty array 206 * 207 * Technically we can't "test" this as the default regex is an empty array, this 208 * is purely for improving test coverage 209 * 210 * @dataProvider provider_constructor_only_changes_custom_regex_if_passed 211 * 212 * @test 213 * @covers Route::__construct 214 */ 215 public function test_constructor_only_changes_custom_regex_if_passed($uri, $uri2) 216 { 217 $route = new Route($uri, array()); 218 219 $this->assertAttributeSame(array(), '_regex', $route); 220 221 $route = new Route($uri2, NULL); 222 223 $this->assertAttributeSame(array(), '_regex', $route); 224 } 225 226 /** 227 * When we pass custom regex to the route's constructor it should it 228 * in leu of the default. This does not apply to callback/lambda routes 229 * 230 * @test 231 * @covers Route::__construct 232 * @covers Route::compile 233 */ 234 public function test_route_uses_custom_regex_passed_to_constructor() 235 { 236 $regex = array('id' => '[0-9]{1,2}'); 237 238 $route = new Route('<controller>(/<action>(/<id>))', $regex); 239 240 $this->assertAttributeSame($regex, '_regex', $route); 241 $this->assertAttributeContains( 242 $regex['id'], 243 '_route_regex', 244 $route 245 ); 246 } 247 248 /** 249 * Provider for test_matches_returns_false_on_failure 250 * 251 * @return array 252 */ 253 public function provider_matches_returns_false_on_failure() 254 { 255 return array( 256 array('projects/(<project_id>/(<controller>(/<action>(/<id>))))', 'apple/pie'), 257 ); 258 } 259 260 /** 261 * Route::matches() should return false if the route doesn't match against a uri 262 * 263 * @dataProvider provider_matches_returns_false_on_failure 264 * 265 * @test 266 * @covers Route::matches 267 */ 268 public function test_matches_returns_false_on_failure($uri, $match) 269 { 270 $route = new Route($uri); 271 272 // Mock a request class with the $match uri 273 $stub = $this->get_request_mock($match); 274 275 $this->assertSame(FALSE, $route->matches($stub)); 276 } 277 278 /** 279 * Provider for test_matches_returns_array_of_parameters_on_successful_match 280 * 281 * @return array 282 */ 283 public function provider_matches_returns_array_of_parameters_on_successful_match() 284 { 285 return array( 286 array( 287 '(<controller>(/<action>(/<id>)))', 288 'welcome/index', 289 'Welcome', 290 'index', 291 ), 292 ); 293 } 294 295 /** 296 * Route::matches() should return an array of parameters when a match is made 297 * An parameters that are not matched should not be present in the array of matches 298 * 299 * @dataProvider provider_matches_returns_array_of_parameters_on_successful_match 300 * 301 * @test 302 * @covers Route::matches 303 */ 304 public function test_matches_returns_array_of_parameters_on_successful_match($uri, $m, $c, $a) 305 { 306 $route = new Route($uri); 307 308 // Mock a request class with the $m uri 309 $request = $this->get_request_mock($m); 310 311 $matches = $route->matches($request); 312 313 $this->assertInternalType('array', $matches); 314 $this->assertArrayHasKey('controller', $matches); 315 $this->assertArrayHasKey('action', $matches); 316 $this->assertArrayNotHasKey('id', $matches); 317 // $this->assertSame(5, count($matches)); 318 $this->assertSame($c, $matches['controller']); 319 $this->assertSame($a, $matches['action']); 320 } 321 322 /** 323 * Provider for test_matches_returns_array_of_parameters_on_successful_match 324 * 325 * @return array 326 */ 327 public function provider_defaults_are_used_if_params_arent_specified() 328 { 329 return array( 330 array( 331 '<controller>(/<action>(/<id>))', 332 NULL, 333 array('controller' => 'Welcome', 'action' => 'index'), 334 'Welcome', 335 'index', 336 'unit/test/1', 337 array( 338 'controller' => 'unit', 339 'action' => 'test', 340 'id' => '1' 341 ), 342 'Welcome', 343 ), 344 array( 345 '(<controller>(/<action>(/<id>)))', 346 NULL, 347 array('controller' => 'welcome', 'action' => 'index'), 348 'Welcome', 349 'index', 350 'unit/test/1', 351 array( 352 'controller' => 'unit', 353 'action' => 'test', 354 'id' => '1' 355 ), 356 '', 357 ), 358 ); 359 } 360 361 /** 362 * Defaults specified with defaults() should be used if their values aren't 363 * present in the uri 364 * 365 * @dataProvider provider_defaults_are_used_if_params_arent_specified 366 * 367 * @test 368 * @covers Route::matches 369 */ 370 public function test_defaults_are_used_if_params_arent_specified($uri, $regex, $defaults, $c, $a, $test_uri, $test_uri_array, $default_uri) 371 { 372 $route = new Route($uri, $regex); 373 $route->defaults($defaults); 374 375 $this->assertSame($defaults, $route->defaults()); 376 377 // Mock a request class 378 $request = $this->get_request_mock($default_uri); 379 380 $matches = $route->matches($request); 381 382 $this->assertInternalType('array', $matches); 383 $this->assertArrayHasKey('controller', $matches); 384 $this->assertArrayHasKey('action', $matches); 385 $this->assertArrayNotHasKey('id', $matches); 386 // $this->assertSame(4, count($matches)); 387 $this->assertSame($c, $matches['controller']); 388 $this->assertSame($a, $matches['action']); 389 $this->assertSame($test_uri, $route->uri($test_uri_array)); 390 $this->assertSame($default_uri, $route->uri()); 391 } 392 393 /** 394 * Provider for test_optional_groups_containing_specified_params 395 * 396 * @return array 397 */ 398 public function provider_optional_groups_containing_specified_params() 399 { 400 return array( 401 /** 402 * Specifying this should cause controller and action to show up 403 * refs #4113 404 */ 405 array( 406 '(<controller>(/<action>(/<id>)))', 407 array('controller' => 'welcome', 'action' => 'index'), 408 array('id' => '1'), 409 'welcome/index/1', 410 ), 411 array( 412 '<controller>(/<action>(/<id>))', 413 array('controller' => 'welcome', 'action' => 'index'), 414 array('action' => 'foo'), 415 'welcome/foo', 416 ), 417 array( 418 '<controller>(/<action>(/<id>))', 419 array('controller' => 'welcome', 'action' => 'index'), 420 array('action' => 'index'), 421 'welcome', 422 ), 423 /** 424 * refs #4630 425 */ 426 array( 427 'api(/<version>)/const(/<id>)(/<custom>)', 428 array('version' => 1), 429 NULL, 430 'api/const', 431 ), 432 array( 433 'api(/<version>)/const(/<id>)(/<custom>)', 434 array('version' => 1), 435 array('version' => 9), 436 'api/9/const', 437 ), 438 array( 439 'api(/<version>)/const(/<id>)(/<custom>)', 440 array('version' => 1), 441 array('id' => 2), 442 'api/const/2', 443 ), 444 array( 445 'api(/<version>)/const(/<id>)(/<custom>)', 446 array('version' => 1), 447 array('custom' => 'x'), 448 'api/const/x', 449 ), 450 array( 451 '(<controller>(/<action>(/<id>)(/<type>)))', 452 array('controller' => 'test', 'action' => 'index', 'type' => 'html'), 453 array('type' => 'json'), 454 'test/index/json', 455 ), 456 array( 457 '(<controller>(/<action>(/<id>)(/<type>)))', 458 array('controller' => 'test', 'action' => 'index', 'type' => 'html'), 459 array('id' => 123), 460 'test/index/123', 461 ), 462 array( 463 '(<controller>(/<action>(/<id>)(/<type>)))', 464 array('controller' => 'test', 'action' => 'index', 'type' => 'html'), 465 array('id' => 123, 'type' => 'html'), 466 'test/index/123', 467 ), 468 array( 469 '(<controller>(/<action>(/<id>)(/<type>)))', 470 array('controller' => 'test', 'action' => 'index', 'type' => 'html'), 471 array('id' => 123, 'type' => 'json'), 472 'test/index/123/json', 473 ), 474 ); 475 } 476 477 /** 478 * When an optional param is specified, the optional params leading up to it 479 * must be in the URI. 480 * 481 * @dataProvider provider_optional_groups_containing_specified_params 482 * 483 * @ticket 4113 484 * @ticket 4630 485 */ 486 public function test_optional_groups_containing_specified_params($uri, $defaults, $params, $expected) 487 { 488 $route = new Route($uri, NULL); 489 $route->defaults($defaults); 490 491 $this->assertSame($expected, $route->uri($params)); 492 } 493 494 /** 495 * Optional params should not be used if what is passed in is identical 496 * to the default. 497 * 498 * refs #4116 499 * 500 * @test 501 * @covers Route::uri 502 */ 503 public function test_defaults_are_not_used_if_param_is_identical() 504 { 505 $route = new Route('(<controller>(/<action>(/<id>)))'); 506 $route->defaults(array( 507 'controller' => 'welcome', 508 'action' => 'index' 509 )); 510 511 $this->assertSame('', $route->uri(array('controller' => 'welcome'))); 512 $this->assertSame('welcome2', $route->uri(array('controller' => 'welcome2'))); 513 } 514 515 /** 516 * Provider for test_required_parameters_are_needed 517 * 518 * @return array 519 */ 520 public function provider_required_parameters_are_needed() 521 { 522 return array( 523 array( 524 'admin(/<controller>(/<action>(/<id>)))', 525 'admin', 526 'admin/users/add', 527 ), 528 ); 529 } 530 531 /** 532 * This tests that routes with required parameters will not match uris without them present 533 * 534 * @dataProvider provider_required_parameters_are_needed 535 * 536 * @test 537 * @covers Route::matches 538 */ 539 public function test_required_parameters_are_needed($uri, $matches_route1, $matches_route2) 540 { 541 $route = new Route($uri); 542 543 // Mock a request class that will return empty uri 544 $request = $this->get_request_mock(''); 545 546 $this->assertFalse($route->matches($request)); 547 548 // Mock a request class that will return route1 549 $request = $this->get_request_mock($matches_route1); 550 551 $matches = $route->matches($request); 552 553 $this->assertInternalType('array', $matches); 554 555 // Mock a request class that will return route2 uri 556 $request = $this->get_request_mock($matches_route2); 557 558 $matches = $route->matches($request); 559 560 $this->assertInternalType('array', $matches); 561 // $this->assertSame(5, count($matches)); 562 $this->assertArrayHasKey('controller', $matches); 563 $this->assertArrayHasKey('action', $matches); 564 } 565 566 /** 567 * Provider for test_required_parameters_are_needed 568 * 569 * @return array 570 */ 571 public function provider_reverse_routing_returns_routes_uri_if_route_is_static() 572 { 573 return array( 574 array( 575 'info/about_us', 576 NULL, 577 'info/about_us', 578 array('some' => 'random', 'params' => 'to confuse'), 579 ), 580 ); 581 } 582 583 /** 584 * This tests the reverse routing returns the uri specified in the route 585 * if it's a static route 586 * 587 * A static route is a route without any parameters 588 * 589 * @dataProvider provider_reverse_routing_returns_routes_uri_if_route_is_static 590 * 591 * @test 592 * @covers Route::uri 593 */ 594 public function test_reverse_routing_returns_routes_uri_if_route_is_static($uri, $regex, $target_uri, $uri_params) 595 { 596 $route = new Route($uri, $regex); 597 598 $this->assertSame($target_uri, $route->uri($uri_params)); 599 } 600 601 /** 602 * Provider for test_uri_throws_exception_if_required_params_are_missing 603 * 604 * @return array 605 */ 606 public function provider_uri_throws_exception_if_required_params_are_missing() 607 { 608 return array( 609 array( 610 '<controller>(/<action)', 611 NULL, 612 array('action' => 'awesome-action'), 613 ), 614 /** 615 * Optional params are required when they lead to a specified param 616 * refs #4113 617 */ 618 array( 619 '(<controller>(/<action>))', 620 NULL, 621 array('action' => 'awesome-action'), 622 ), 623 ); 624 } 625 626 /** 627 * When Route::uri is working on a uri that requires certain parameters to be present 628 * (i.e. <controller> in '<controller(/<action)') then it should throw an exception 629 * if the param was not provided 630 * 631 * @dataProvider provider_uri_throws_exception_if_required_params_are_missing 632 * 633 * @test 634 * @covers Route::uri 635 */ 636 public function test_uri_throws_exception_if_required_params_are_missing($uri, $regex, $uri_array) 637 { 638 $route = new Route($uri, $regex); 639 640 $this->setExpectedException('Kohana_Exception', 'controller'); 641 $route->uri($uri_array); 642 } 643 644 /** 645 * Provider for test_uri_fills_required_uri_segments_from_params 646 * 647 * @return array 648 */ 649 public function provider_uri_fills_required_uri_segments_from_params() 650 { 651 return array( 652 array( 653 '<controller>/<action>(/<id>)', 654 NULL, 655 'users/edit', 656 array( 657 'controller' => 'users', 658 'action' => 'edit', 659 ), 660 'users/edit/god', 661 array( 662 'controller' => 'users', 663 'action' => 'edit', 664 'id' => 'god', 665 ), 666 ), 667 ); 668 } 669 670 /** 671 * The logic for replacing required segments is separate (but similar) to that for 672 * replacing optional segments. 673 * 674 * This test asserts that Route::uri will replace required segments with provided 675 * params 676 * 677 * @dataProvider provider_uri_fills_required_uri_segments_from_params 678 * 679 * @test 680 * @covers Route::uri 681 */ 682 public function test_uri_fills_required_uri_segments_from_params($uri, $regex, $uri_string1, $uri_array1, $uri_string2, $uri_array2) 683 { 684 $route = new Route($uri, $regex); 685 686 $this->assertSame( 687 $uri_string1, 688 $route->uri($uri_array1) 689 ); 690 691 $this->assertSame( 692 $uri_string2, 693 $route->uri($uri_array2) 694 ); 695 } 696 697 /** 698 * Provides test data for test_composing_url_from_route() 699 * @return array 700 */ 701 public function provider_composing_url_from_route() 702 { 703 return array( 704 array('/'), 705 array('/news/view/42', array('controller' => 'news', 'action' => 'view', 'id' => 42)), 706 array('http://kohanaframework.org/news', array('controller' => 'news'), 'http') 707 ); 708 } 709 710 /** 711 * Tests Route::url() 712 * 713 * Checks the url composing from specific route via Route::url() shortcut 714 * 715 * @test 716 * @dataProvider provider_composing_url_from_route 717 * @param string $expected 718 * @param array $params 719 * @param boolean $protocol 720 */ 721 public function test_composing_url_from_route($expected, $params = NULL, $protocol = NULL) 722 { 723 Route::set('foobar', '(<controller>(/<action>(/<id>)))') 724 ->defaults(array( 725 'controller' => 'welcome', 726 ) 727 ); 728 729 $this->setEnvironment(array( 730 '_SERVER' => array('HTTP_HOST' => 'kohanaframework.org'), 731 'Kohana::$base_url' => '/', 732 'Kohana::$index_file' => '', 733 )); 734 735 $this->assertSame($expected, Route::url('foobar', $params, $protocol)); 736 } 737 738 /** 739 * Tests Route::compile() 740 * 741 * Makes sure that compile will use custom regex if specified 742 * 743 * @test 744 * @covers Route::compile 745 */ 746 public function test_compile_uses_custom_regex_if_specificed() 747 { 748 $compiled = Route::compile( 749 '<controller>(/<action>(/<id>))', 750 array( 751 'controller' => '[a-z]+', 752 'id' => '\d+', 753 ) 754 ); 755 756 $this->assertSame('#^(?P<controller>[a-z]+)(?:/(?P<action>[^/.,;?\n]++)(?:/(?P<id>\d+))?)?$#uD', $compiled); 757 } 758 759 /** 760 * Tests Route::is_external(), ensuring the host can return 761 * whether internal or external host 762 */ 763 public function test_is_external_route_from_host() 764 { 765 // Setup local route 766 Route::set('internal', 'local/test/route') 767 ->defaults(array( 768 'controller' => 'foo', 769 'action' => 'bar' 770 ) 771 ); 772 773 // Setup external route 774 Route::set('external', 'local/test/route') 775 ->defaults(array( 776 'controller' => 'foo', 777 'action' => 'bar', 778 'host' => 'http://kohanaframework.org' 779 ) 780 ); 781 782 // Test internal route 783 $this->assertFalse(Route::get('internal')->is_external()); 784 785 // Test external route 786 $this->assertTrue(Route::get('external')->is_external()); 787 } 788 789 /** 790 * Provider for test_external_route_includes_params_in_uri 791 * 792 * @return array 793 */ 794 public function provider_external_route_includes_params_in_uri() 795 { 796 return array( 797 array( 798 '<controller>/<action>', 799 array( 800 'controller' => 'foo', 801 'action' => 'bar', 802 'host' => 'kohanaframework.org' 803 ), 804 'http://kohanaframework.org/foo/bar' 805 ), 806 array( 807 '<controller>/<action>', 808 array( 809 'controller' => 'foo', 810 'action' => 'bar', 811 'host' => 'http://kohanaframework.org' 812 ), 813 'http://kohanaframework.org/foo/bar' 814 ), 815 array( 816 'foo/bar', 817 array( 818 'controller' => 'foo', 819 'host' => 'http://kohanaframework.org' 820 ), 821 'http://kohanaframework.org/foo/bar' 822 ), 823 ); 824 } 825 826 /** 827 * Tests the external route include route parameters 828 * 829 * @dataProvider provider_external_route_includes_params_in_uri 830 */ 831 public function test_external_route_includes_params_in_uri($route, $defaults, $expected_uri) 832 { 833 Route::set('test', $route) 834 ->defaults($defaults); 835 836 $this->assertSame($expected_uri, Route::get('test')->uri()); 837 } 838 839 /** 840 * Provider for test_route_filter_modify_params 841 * 842 * @return array 843 */ 844 public function provider_route_filter_modify_params() 845 { 846 return array( 847 array( 848 '<controller>/<action>', 849 array( 850 'controller' => 'Test', 851 'action' => 'same', 852 ), 853 array('Route_Holder', 'route_filter_modify_params_array'), 854 'test/different', 855 array( 856 'controller' => 'Test', 857 'action' => 'modified', 858 ), 859 ), 860 array( 861 '<controller>/<action>', 862 array( 863 'controller' => 'test', 864 'action' => 'same', 865 ), 866 array('Route_Holder', 'route_filter_modify_params_false'), 867 'test/fail', 868 FALSE, 869 ), 870 ); 871 } 872 873 /** 874 * Tests that route filters can modify parameters 875 * 876 * @covers Route::filter 877 * @dataProvider provider_route_filter_modify_params 878 */ 879 public function test_route_filter_modify_params($route, $defaults, $filter, $uri, $expected_params) 880 { 881 $route = new Route($route); 882 883 // Mock a request class 884 $request = $this->get_request_mock($uri); 885 886 $params = $route->defaults($defaults)->filter($filter)->matches($request); 887 888 $this->assertSame($expected_params, $params); 889 } 890 891 /** 892 * Provides test data for test_route_uri_encode_parameters 893 * 894 * @return array 895 */ 896 public function provider_route_uri_encode_parameters() 897 { 898 return array( 899 array( 900 'article', 901 'blog/article/<article_name>', 902 array( 903 'controller' => 'home', 904 'action' => 'index' 905 ), 906 'article_name', 907 'Article name with special chars \\ ##', 908 'blog/article/Article%20name%20with%20special%20chars%20\\%20%23%23' 909 ) 910 ); 911 } 912 913 /** 914 * http://dev.kohanaframework.org/issues/4079 915 * 916 * @test 917 * @covers Route::get 918 * @ticket 4079 919 * @dataProvider provider_route_uri_encode_parameters 920 */ 921 public function test_route_uri_encode_parameters($name, $uri_callback, $defaults, $uri_key, $uri_value, $expected) 922 { 923 Route::set($name, $uri_callback)->defaults($defaults); 924 925 $get_route_uri = Route::get($name)->uri(array($uri_key => $uri_value)); 926 927 $this->assertSame($expected, $get_route_uri); 928 } 929 930 /** 931 * Get a mock of the Request class with a mocked `uri` method 932 * 933 * We are also mocking `method` method as it conflicts with newer PHPUnit, 934 * in order to avoid the fatal errors 935 * 936 * @param string $uri 937 * @return type 938 */ 939 public function get_request_mock($uri) 940 { 941 // Mock a request class with the $uri uri 942 $request = $this->getMock('Request', array('uri', 'method'), array($uri)); 943 944 // mock `uri` method 945 $request->expects($this->any()) 946 ->method('uri') 947 // Request::uri() called by Route::matches() in the tests will return $uri 948 ->will($this->returnValue($uri)); 949 950 // also mock `method` method 951 $request->expects($this->any()) 952 ->method('method') 953 ->withAnyParameters(); 954 955 return $request; 956 } 957 958} 959