<?php
/**
 * core.framework
 *
 * @category   Core
 * @package    Core_Router
 * @subpackage IntegrationTests
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 */

/**
 * @category   Core
 * @package    Core_Router
 * @subpackage IntegrationTests
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 * @group      Core_Router
 * @group      IntegrationTests
 */
class Core_Router_RouteIntegrationTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var Core_Router
     */
    protected $_object;

    /**
     * @var Core_Config
     */
    protected $_config;

    /**
     * @var Core_Loader_PluginLoader
     */
    protected $_pluginLoader;

    /**
     * @var Core_Request
     */
    protected $_request;

    public function __construct()
    {
        // where is the file fixture?
        $path                = TESTS_ROOT .'/resources/fixtures/Core/Router/'. $this->_suiteName() .'.ini';
        $this->_config       = new Core_Config($path);
        $this->_pluginLoader = new Core_Loader_PluginLoader;
        $this->_request      = new Core_Request;
    }

    protected function setUp()
    {
        $this->_object = new Core_Router;
        $this->_object
            ->setPluginLoader($this->_pluginLoader)
            ->setRequest($this->_request)
            ->setConfig($this->_config);
    }

    /**
     * @covers Core_Router::route
     */
    public function testWillThrowAnExceptionIfNoMatchingRouteFound()
    {
        $this->setExpectedException('RuntimeException');
        $this->_object->route('/kre');
    }

    /**
     * @covers Core_Router::route
     */
    public function testWillMatchPathToRoute()
    {
        $this->assertInstanceOf('Core_Router_Route_Abstract', $this->_object->route('/array'));
    }

    /**
     * @covers Core_Router::route
     */
    public function testWillExtractValuesFromRouteIncludingDefaults()
    {
        $route = $this->_object->route('/array/grr');
        $this->assertEquals(
            array(
                'module'     => 'form',
                'controller' => 'test',
                'action'     => 'array',
                'var'        => 'grr',
            ),
            $route->getValues()
        );
    }

    /**
     * @covers Core_Router::route
     */
    public function testCanMatchTokenRoute()
    {
        $route = $this->_object->route('/site/23');
        $this->assertEquals(
            array(
                'module'     => 'site',
                'controller' => 'index',
                'action'     => 'action',
                'site_id'    => '23',
            ),
            $route->getValues()
        );
    }

    /**
     * @covers Core_Router::route
     */
    public function testWillUseCurrentRouteWhenGeneratingUrlsWhenNoRouteSpecified()
    {
        // current URL has matched a certain route
        $this->_object->route('/site/23/');

        // will use the same route for generating URLs by default
        $this->assertEquals('/site/24/', $this->_object->path(array('site_id' => 24)));
    }

    /**
     * #CF-13
     *
     * @covers Core_Router::route
     */
    public function testShouldNotFailIfRouteWithAnParamContainsAnTrailingSlashBeforeQueryString()
    {
        try {
            // this one is OK
            $this->_object->route('/deploy/6?deploy=1');

            // this one fails (trailing slash)
            $this->_object->route('/deploy/6/?deploy=1');
        } catch (Exception $e) {
            $this->fail($e->getMessage());
        }
        $this->assertTrue(true);
    }

    /**
     * @covers Core_Router::route
     */
    public function testWillIgnoreCaseWhenRouting()
    {
        try {
            $route = $this->_object->route('/SITE/new');
        } catch (Exception $e) {
            $this->fail($e->getMessage());
        }
        $this->assertTrue(true);
    }

    /**
     * @covers Core_Router::route
     */
    public function testCanMatchCyrillicRoute()
    {
        $route = $this->_object->route('/site/контакт/');
        $this->assertEquals(
            array(
                'module'     => 'site',
                'controller' => 'index',
                'action'     => 'action',
                'site_id'    => 'контакт',
            ),
            $route->getValues()
        );
    }

    /**
     * @covers Core_Router::route
     */
    public function testCanMatchCyrillicRouteWhenUsingNonUrldecodedRequest()
    {
        $_SERVER = array(
            'REQUEST_URI' => '/site/%D0%BA%D0%BE%D0%BD%D1%82%D0%B0%D0%BA%D1%82/'
        );
        $request = new Core_Request;
        $route   = $this->_object->route($request->getPath());
        $this->assertEquals(
            array(
                'module'     => 'site',
                'controller' => 'index',
                'action'     => 'action',
                'site_id'    => 'контакт',
            ),
            $route->getValues()
        );
    }

    /**
     * @covers Core_Router::route
     */
    public function testWillNotMatchRouteIfRequestMethodDoesNotMatchRouteMethod()
    {
        $_SERVER = array(
            'REQUEST_METHOD' => 'GET'
        );
        $this->setExpectedException('RuntimeException');

        $this->_object->route('/method');
    }

    /**
     * @covers Core_Router::route
     */
    public function testWillMatchRouteIfRequestMethodMatchesRouteMethod()
    {
        $_SERVER = array(
            'REQUEST_METHOD' => 'POST'
        );

        $this->assertInstanceOf('Core_Router_Route_Abstract', $this->_object->route('/method'));
    }

    /**
     * @covers Core_Router::route
     */
    public function testWillMatchRouteWithAttachedPlugin()
    {
        include_once TESTS_ROOT .'/resources/fixtures/Core/Router/Route/Plugin/Model.php';
        $plugin = new Invalid_Router_Route_Plugin_Model;
        $route  = $this->_object->getRoute('plugin');
        $route->addPlugin($plugin);

        $this->assertInstanceOf('Core_Router_Route_Abstract', $this->_object->route('/plugin/one'));
    }

    /**
     * @covers Core_Router::route
     */
    public function testWillMatchRouteIfHostnameMatches()
    {
        $_SERVER = array(
            'SERVER_NAME' => 'example.com'
        );

        $this->assertInstanceOf('Core_Router_Route_Abstract', $this->_object->route('/hostname'));
    }

    /**
     * @covers Core_Router::route
     */
    public function testWillNotMatchRouteIfHostnameDoesNotMatch()
    {
        $_SERVER = array(
            'SERVER_NAME' => 'not.example.com'
        );
        $this->setExpectedException('RuntimeException');

        $this->assertInstanceOf('Core_Router_Route_Abstract', $this->_object->route('/hostname'));
    }

    protected function _suiteName()
    {
        return strtolower(basename(__FILE__, 'IntegrationTest.php'));
    }
}
