<?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_Form_Group_DisplayTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var Core_Form_Group_Display
     */
    protected $_object;

    protected function setUp()
    {
        $this->_object = new Core_Form_Group_Display();
    }
    
    /**
     * @covers Core_Form_Group_Display::__construct
     */
    public function testCanSetOptionsViaConstructor()
    {
        $object = new Core_Form_Group_Display(array('attribs' => array('class' => 'g_h_23')));

        $this->assertEquals('g_h_23', $object->getAttrib('class'));
    }

    /**
     * @covers Core_Form_Group_Display::__construct
     */
    public function testCanSetConfigViaConstructor()
    {
        $config = $this->getMock('Zend_Config', null, array(array('attribs' => array('class' => 'g_h_23'))));
        $object = new Core_Form_Group_Display($config);

        $this->assertEquals('g_h_23', $object->getAttrib('class'));
    }
    
    /**
     * @covers Core_Form_Group_Display::isIgnored
     */
    public function testItIsIgnoredByDefault()
    {
        $this->assertTrue($this->_object->isIgnored());
    }
    
    /**
     * @covers Core_Form_Group_Display::isEscalateErrors
     */
    public function testItEscalatesErrorsByDefault()
    {
        $this->assertTrue($this->_object->isEscalateErrors());
    }

    /**
     * @covers Core_Form_Group_Display::getMacro
     */
    public function testDefaultMacroIsSet()
    {
        $this->assertEquals('display_group', $this->_object->getMacro());
    }
    
    /**
     * @covers Core_Form_Group_Display::setOwner
     * @covers Core_Form_Group_Display::getParent
     */
    public function testCanSetAndGetParent()
    {
        $parent = $this->getMock('Core_Form', array(), array(), '', false);
        $this->_object->setOwner($parent);
        
        $this->assertEquals($parent, $this->_object->getParent());
    }
    
    /**
     * @covers Core_Form_Group_Display::getParent
     */
    public function testFetchingParentWithNoParentSetThrowsARuntimeException()
    {
        $this->setExpectedException('RuntimeException');
        
        $this->_object->getParent();
    }
    
    /**
     * @covers Core_Form_Group_Display::setPluginManager
     */
    public function testSetPluginManagerWillProxyToParent()
    {
        $parent        = $this->getMock('Core_Form', array('setPluginManager'), array(), '', false);
        $pluginManager = $this->getMock('Core_Plugin_Manager', array(), array($parent));
        $parent
            ->expects($this->once())
            ->method('setPluginManager')
            ->with($this->equalTo($pluginManager));
        $this->_object->setOwner($parent);
        
        $this->_object->setPluginManager($pluginManager);
    }
    
    /**
     * @covers Core_Form_Group_Display::getPluginManager
     */
    public function testGetPluginManagerWillProxyToParent()
    {
        $parent        = $this->getMock('Core_Form', array('getPluginManager'), array(), '', false);
        $pluginManager = $this->getMock('Core_Plugin_Manager', array(), array($parent));
        $parent
            ->expects($this->once())
            ->method('getPluginManager')
            ->will($this->returnValue($pluginManager));
        $this->_object->setOwner($parent);
        
        $this->assertEquals($pluginManager, $this->_object->getPluginManager());
    }
    
    /**
     * @covers Core_Form_Group_Display::addGroups
     */
    public function testCanAddGroups()
    {
        $parent = $this->getMock('Core_Form_Group_Interface');
        $group  = $this->getMock('Core_Form_Group_Interface');
        $object = $this->getMock('Core_Form_Group_Display', array('addGroup', 'createGroup', 'getParent'));
        $object
            ->expects($this->once())
            ->method('getParent')
            ->will($this->returnValue($parent));
        $object
            ->expects($this->once())
            ->method('addGroup')
            ->with($this->equalTo($group));
        $object
            ->expects($this->once())
            ->method('createGroup')
            ->with($this->equalTo('someType'), $this->equalTo('someName'), $this->equalTo(array('owner' => $parent, 'a' => 'b')));
        
        $object->addGroups(array(
            $group,
            'someName' => array(
                'type'    => 'someType',
                'options' => array('a' => 'b')
            )
        ));
    }
    
    /**
     * @covers Core_Form_Group_Display::addGroups
     */
    public function testAddingGroupsWhichAreNotInstanceOfGroupInterfaceOrArrayThrowsAnInvalidArgumentException()
    {
        $this->setExpectedException('InvalidArgumentException');
        
        $this->_object->addGroups(array('invalid'));
    }
    
    /**
     * @covers Core_Form_Group_Display::createGroup
     */
    public function testCanCreateGroup()
    {
        $options       = array('a' => 'b', '__autoAdd' => false);
        $group         = $this->getMock('Core_Form_Group_Interface');
        $pluginManager = $this->getMock('Core_Plugin_Manager', array('createPlugin'), array($group));
        $pluginManager
            ->expects($this->once())
            ->method('createPlugin')
            ->with($this->equalTo('Core_Form_Group_Interface'), $this->equalTo('someType'), $this->equalTo('someName'), $this->equalTo($options))
            ->will($this->returnValue($group));
        $object  = $this->getMock('Core_Form_Group_Display', array('addGroup', 'getPluginManager'));
        $object
            ->expects($this->once())
            ->method('getPluginManager')
            ->will($this->returnValue($pluginManager));
        $object
            ->expects($this->once())
            ->method('addGroup')
            ->with($this->equalTo($group));
        
        $this->assertEquals($group, $object->createGroup('someType', 'someName', array('a' => 'b')));
    }
    
    /**
     * @covers Core_Form_Group_Display::addGroup
     * @covers Core_Form_Group_Display::getGroups
     */
    public function testCanAddGroup()
    {
        $group = $this->getMockForAbstractClass('Core_Form_Group_Abstract', array(), '', true, true, true, array('getName'));
        $group
            ->expects($this->once())
            ->method('getName')
            ->will($this->returnValue('myGroup'));
        
        $parent        = $this->getMock('Core_Form', array('getPluginManager'), array(), '', false);
        $pluginManager = $this->getMock('Core_Plugin_Manager', array('addPlugin', 'getPlugins'), array($parent));
        $pluginManager
            ->expects($this->once())
            ->method('addPlugin')
            ->with($this->equalTo('Core_Form_Group_Interface'), $this->equalTo($group), $this->equalTo(false));
        $pluginManager
            ->expects($this->once())
            ->method('getPlugins')
            ->with($this->equalTo('Core_Form_Group_Interface'), $this->equalTo(array('mygroup')));
        $parent
            ->expects($this->exactly(2))
            ->method('getPluginManager')
            ->will($this->returnValue($pluginManager));
        $this->_object->setOwner($parent);
        
        $this->_object->addGroup($group);
        $this->_object->getGroups();
    }
    
    /**
     * @covers Core_Form_Group_Display::removeGroup
     * @covers Core_Form_Group_Display::getGroups
     */
    public function testCanRemoveGroup()
    {
        $group = $this->getMockForAbstractClass('Core_Form_Group_Abstract', array(), '', true, true, true, array('getName'));
        $group
            ->expects($this->once())
            ->method('getName')
            ->will($this->returnValue('myGroup'));
        
        $parent        = $this->getMock('Core_Form', array('getPluginManager'), array(), '', false);
        $pluginManager = $this->getMock('Core_Plugin_Manager', array('addPlugin', 'removePlugin', 'getPlugins'), array($parent));
        $pluginManager
            ->expects($this->once())
            ->method('getPlugins')
            ->with($this->equalTo('Core_Form_Group_Interface'), $this->equalTo(array()));
        $parent
            ->expects($this->exactly(3))
            ->method('getPluginManager')
            ->will($this->returnValue($pluginManager));
        $this->_object->setOwner($parent);
        $this->_object->addGroup($group);
        $this->_object->removeGroup('myGroup');
        
        $this->_object->getGroups();
    }
    
    /**
     * @covers Core_Form_Group_Display::addElements
     */
    public function testCanAddElements()
    {
        $parent  = $this->getMock('Core_Form_Group_Interface');
        $element = $this->getMock('Core_Form_Element_Interface');
        $object  = $this->getMock('Core_Form_Group_Display', array('addElement', 'createElement', 'getParent'));
        $object
            ->expects($this->once())
            ->method('getParent')
            ->will($this->returnValue($parent));
        $object
            ->expects($this->once())
            ->method('addElement')
            ->with($this->equalTo($element));
        $object
            ->expects($this->once())
            ->method('createElement')
            ->with($this->equalTo('someType'), $this->equalTo('someName'), $this->equalTo(array('owner' => $parent, 'a' => 'b')));
        
        $object->addElements(array(
            $element,
            'someName' => array(
                'type'    => 'someType',
                'options' => array('a' => 'b')
            )
        ));
    }
    
    /**
     * @covers Core_Form_Group_Display::addElements
     */
    public function testAddingElementsWhichAreNotInstanceOfElementInterfaceOrArrayThrowsAnInvalidArgumentException()
    {
        $this->setExpectedException('InvalidArgumentException');
        
        $this->_object->addElements(array('invalid'));
    }
    
    /**
     * @covers Core_Form_Group_Display::createElement
     */
    public function testCanCreateElement()
    {
        $options       = array('a' => 'b', '__autoAdd' => false);
        $element       = $this->getMock('Core_Form_Element_Interface');
        $pluginManager = $this->getMock('Core_Plugin_Manager', array('createPlugin'), array($element));
        $pluginManager
            ->expects($this->once())
            ->method('createPlugin')
            ->with($this->equalTo('Core_Form_Element_Interface'), $this->equalTo('someType'), $this->equalTo('someName'), $this->equalTo($options))
            ->will($this->returnValue($element));
        $object  = $this->getMock('Core_Form_Group_Display', array('addElement', 'getPluginManager'));
        $object
            ->expects($this->once())
            ->method('getPluginManager')
            ->will($this->returnValue($pluginManager));
        $object
            ->expects($this->once())
            ->method('addElement')
            ->with($this->equalTo($element));
        
        $this->assertEquals($element, $object->createElement('someType', 'someName', array('a' => 'b')));
    }
    
    /**
     * @covers Core_Form_Group_Display::addElement
     * @covers Core_Form_Group_Display::getElements
     */
    public function testCanAddElement()
    {
        $element = $this->getMockForAbstractClass('Core_Form_Element_Abstract', array(), '', true, true, true, array('getName'));
        $element
            ->expects($this->once())
            ->method('getName')
            ->will($this->returnValue('myElement'));
        
        $parent        = $this->getMock('Core_Form', array('getPluginManager'), array(), '', false);
        $pluginManager = $this->getMock('Core_Plugin_Manager', array('addPlugin', 'getPlugins'), array($parent));
        $pluginManager
            ->expects($this->once())
            ->method('addPlugin')
            ->with($this->equalTo('Core_Form_Element_Interface'), $this->equalTo($element), $this->equalTo(false));
        $pluginManager
            ->expects($this->once())
            ->method('getPlugins')
            ->with($this->equalTo('Core_Form_Element_Interface'), $this->equalTo(array('myelement')));
        $parent
            ->expects($this->exactly(2))
            ->method('getPluginManager')
            ->will($this->returnValue($pluginManager));
        $this->_object->setOwner($parent);
        
        $this->_object->addElement($element);
        $this->_object->getElements();
    }
    
    /**
     * @covers Core_Form_Group_Display::removeElement
     * @covers Core_Form_Group_Display::getElements
     */
    public function testCanRemoveElement()
    {
        $element = $this->getMockForAbstractClass('Core_Form_Element_Abstract', array(), '', true, true, true, array('getName'));
        $element
            ->expects($this->once())
            ->method('getName')
            ->will($this->returnValue('myElement'));
        
        $parent        = $this->getMock('Core_Form', array('getPluginManager'), array(), '', false);
        $pluginManager = $this->getMock('Core_Plugin_Manager', array('addPlugin', 'removePlugin', 'getPlugins'), array($parent));
        $pluginManager
            ->expects($this->once())
            ->method('getPlugins')
            ->with($this->equalTo('Core_Form_Element_Interface'), $this->equalTo(array()));
        $parent
            ->expects($this->exactly(3))
            ->method('getPluginManager')
            ->will($this->returnValue($pluginManager));
        $this->_object->setOwner($parent);
        $this->_object->addElement($element);
        $this->_object->removeElement('myElement');
        
        $this->_object->getElements();
    }
    
    /**
     * @covers Core_Form_Group_Display::__clone
     */
    public function testWillResetPrototypeFlagWhenCloning()
    {
        $this->_object->setPrototype(true);
        $object = clone $this->_object;

        $this->assertFalse($object->isPrototype());
    }
}
