<?php

/*
 * @copyright NetMonsters <team@netmonsters.ru>
 * @link http://netmonsters.ru
 * @package Majestic
 * @subpackage UnitTests
 * @since 2011-10-31
 * 
 * Unit tests for Layout class
 */

require_once dirname(__FILE__) . '/../../exception/ErrorHandler.php';
require_once dirname(__FILE__) . '/../../app/FrontController.php';
require_once dirname(__FILE__) . '/../../layout/Layout.php';

/**
 * @runTestsInSeparateProcesses
 */
class LayoutTest extends PHPUnit_Framework_TestCase
{

    public function run(PHPUnit_Framework_TestResult $result = NULL)
    {
        $this->setPreserveGlobalState(false);
        return parent::run($result);
    }

    public function setUp()
    {
        if (!class_exists('RouterMock')) {
            $this->getMock('Router', array(), array(), 'RouterMock', false);
        }
        if (!class_exists('PHPViewMock')) {
            $this->getMock('PHPView', array('fetch', 'append', 'prepend', 'assign', 'getTemplate'), array(), 'PHPViewMock', false);
        }

        set_new_overload(array($this, 'newCallback'));
    }

    public function testConstruct()
    {
        if (!defined('DEBUG')) {
            define('DEBUG', false);
        }
        $layout = $this->getMockForAbstractClass('Layout');
        $this->assertAttributeInstanceOf('PHPView', 'view', $layout);
    }

    public function testFetch()
    {
        if (!defined('DEBUG')) {
            define('DEBUG', false);
        }
        $layout = $this->getMockForAbstractClass('Layout');

        $action = $this->getMock('Action', array('fetch'));
        $action->expects($this->once())
            ->method('fetch')
            ->will($this->returnValue('this is the result of Action::fetch()'));
        
        $this->assertNull($layout->fetch($action));
    }

    public function testFetchWithTemplate()
    {
        if (!defined('DEBUG')) {
            define('DEBUG', false);
        }
        $layout = $this->getMockForAbstractClass('Layout');

        $class = new ReflectionClass('Layout');
        $template = $class->getProperty('template');
        $template->setAccessible(TRUE);

        $this->assertAttributeEquals(null, 'template', $layout);

        $template->setValue($layout, 'template');
        
        $this->assertAttributeEquals('template', 'template', $layout);
        
        $action = $this->getMock('Action', array('fetch'));
        $action->expects($this->once())
            ->method('fetch')
            ->will($this->returnValue('this is the result of Action::fetch()'));

        $this->assertNull($layout->fetch($action));
    }

    public function testAppend()
    {
        if (!defined('DEBUG')) {
            define('DEBUG', false);
        }
        $layout = $this->getMockForAbstractClass('Layout', array('append', 'prepend'), 'LayoutMock');
        $action = $this->getMock('Action', array('fetch'));

        $action->expects($this->exactly(3))
            ->method('fetch')
            ->will($this->returnValue(true));

        $class = new ReflectionClass('LayoutMock');

        $method = $class->getMethod('append');
        $method->setAccessible(true);
        $method->invoke($layout, 'var', $action);

        $method = $class->getMethod('prepend');
        $method->setAccessible(true);
        $method->invoke($layout, 'var', $action);

        $method = $class->getMethod('assign');
        $method->setAccessible(true);
        $method->invoke($layout, 'var', $action);
    }
    
    protected function newCallback($className)
    {
        switch ($className) {
            case 'Router':
                return 'RouterMock';
            case 'PHPView':
                return 'PHPViewMock';
            default:
                return $className;
        }
    }

    public function tearDown()
    {
//        if (defined('DEBUG')) {
//            $debug = DEBUG ? 'TRUE' : 'FALSE';
//            echo PHP_EOL . __CLASS__ . ' DEBUG = ' . $debug . PHP_EOL;
//        } else {
//            echo PHP_EOL . __CLASS__ . '   ' . 'DEBUG NOT DEFINED' . PHP_EOL;
//        }
        unset_new_overload();
    }
}