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

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

    protected function setUp()
    {
        $this->_object = new Core_Form;
    }
    
    protected function tearDown()
    {
        Core_Application::resetInstance();
    }

    /**
     * @covers Core_Form::__construct
     * @covers Core_Form::__call
     */
    public function testCanManagePlugins()
    {
        $plugin = $this->_mockPlugin('myPlugin');
        $this->_object->addPlugin($plugin);

        $this->assertTrue($this->_object->hasPlugin('MyPlugin'));
    }

    /**
     * @covers Core_Form::setOptions
     */
    public function testCanAddPluginsViaOptions()
    {
        $plugin = $this->_mockPlugin('myPlugin');
        $this->_object->setOptions(array('plugins' => array($plugin)));

        $this->assertTrue($this->_object->hasPlugin('MyPlugin'));
    }

    /**
     * @covers Core_Form::getId
     */
    public function testDefaultIdIsClassName()
    {
        $this->assertEquals('Form', $this->_object->getId());
    }

    /**
     * @covers Core_Form::setMethod
     * @covers Core_Form::getMethod
     */
    public function testCanSetAndGetMethod()
    {
        $this->_object->setMethod('post');
        $this->assertEquals('post', $this->_object->getMethod());
    }

    /**
     * @covers Core_Form::getMethod
     */
    public function testDefaultMethodIsPost()
    {
        $this->assertEquals('post', $this->_object->getMethod());
    }

    /**
     * @covers Core_Form::setRequest
     * @covers Core_Form::getRequest
     */
    public function testCanSetAndGetRequest()
    {
        $request = $this->getMock('Core_Request');
        $this->_object->setRequest($request);

        $this->assertSame($request, $this->_object->getRequest());
    }

    /**
     * @covers Core_Form::getRequest
     */
    public function testIfNoRequestIsSetGetRequestWillPullItFromApplicationInstanceAsRequest()
    {
        $request   = $this->getMock('Core_Request');
        $container = $this->_mockContainer('Request', $request);
        Core_Application::getInstance()->setContainer($container);

        $this->assertSame($request, $this->_object->getRequest());
    }

    /**
     * @covers Core_Form::setAction
     * @covers Core_Form::getAction
     */
    public function testCanSetAndGetAction()
    {
        $this->_object->setAction('post');
        $this->assertEquals('post', $this->_object->getAction());
    }

    /**
     * @covers Core_Form::getAction
     */
    public function testDefaultActionIsCurrentUrl()
    {
        $request = $this->getMock('Core_Request');
        $request
            ->expects($this->once())
            ->method('getUri')
            ->will($this->returnValue('https://www.example.com/foo'));
        $this->_object->setRequest($request);

        $this->assertEquals('https://www.example.com/foo', $this->_object->getAction());
    }

    /**
     * @covers Core_Form::getMacro
     */
    public function testDefaultMacroIsSet()
    {
        $this->assertEquals('form', $this->_object->getMacro());
    }

    /**
     * @covers Core_Form::getAttribs
     * @covers Core_Form::<protected>
     */
    public function testDefaultMandatoryAttribsForDefaultContextAreSet()
    {
        $this->_object
            ->setContext(Core_Form::CONTEXT_DEFAULT)
            ->setName('form')
            ->setMethod('POST')
            ->setAction('http://example.com');
        $attribs = $this->_object->getAttribs();

        $this->assertArrayHasKey('method', $attribs);
        $this->assertArrayHasKey('action', $attribs);
        $this->assertArrayHasKey('id', $attribs);
    }

    /**
     * @covers Core_Form::getAttribs
     * @covers Core_Form::<protected>
     */
    public function testDefaultMandatoryAttribsForAngularContextAreSet()
    {
        $this->_object
            ->setContext(Core_Form::CONTEXT_ANGULAR)
            ->setModel('form');
        $attribs = $this->_object->getAttribs();

        $this->assertArrayHasKey('id',              $attribs);
        $this->assertArrayHasKey('name',            $attribs);
        $this->assertArrayHasKey('ng-model',        $attribs);
        $this->assertArrayHasKey('errors',          $attribs);
        $this->assertArrayHasKey('submit-callback', $attribs);
    }

    /**
     * @covers Core_Form::getTranslator
     */
    public function testWillReturnFalseFromGetTranslatorIfNoneIsRegisterdWithApplicationContainer()
    {
        $container = $this->getMock('Core_Yadif_Container', array('hasComponent'));
        $container
            ->expects($this->once())
            ->method('hasComponent')
            ->with($this->equalTo('translator'))
            ->will($this->returnValue(false));
        Core_Application::getInstance()->setContainer($container);
        
        $this->assertFalse($this->_object->getTranslator());
    }

    /**
     * @covers Core_Form::getTranslator
     */
    public function testIfTranslatorNotSetGetTranslatorWillPullFromContainerAsTranslator()
    {
        $translator = $this->getMock('Zend_Translate');
        $container  = $this->getMock('Core_Yadif_Container', array('hasComponent', 'getComponent'));
        $container
            ->expects($this->once())
            ->method('hasComponent')
            ->with($this->equalTo('translator'))
            ->will($this->returnValue(true));
        $container
            ->expects($this->once())
            ->method('getComponent')
            ->with($this->equalTo('translator'))
            ->will($this->returnValue($translator));
        Core_Application::getInstance()->setContainer($container);
        
        $this->assertEquals($translator, $this->_object->getTranslator());
    }

    protected function _mockPlugin($name)
    {
        $class  = 'Core_Form_Plugin_Abstract';
        $plugin = $this->getMockForAbstractClass($class, array(), '', false, true, true, array('getName'));
        $plugin
            ->expects($this->once())
            ->method('getName')
            ->will($this->returnValue($name));
        return $plugin;
    }
}
