[TASK] EXT:form - set of additional unit tests 24/54024/18
authorMarcel Jürgen Falk <marcel.falk@tritum.de>
Fri, 8 Sep 2017 13:58:11 +0000 (15:58 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Wed, 24 Jan 2018 11:20:38 +0000 (12:20 +0100)
Resolves: #82386
Releases: master
Change-Id: I40b83041149b8955b51c3a2c54d8690392356ae1
Reviewed-on: https://review.typo3.org/54024
Reviewed-by: Reiner Teubner <reiner.teubner@me.com>
Tested-by: Reiner Teubner <reiner.teubner@me.com>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/form/Tests/Unit/Domain/FormElements/AbstractFormElementTest.php
typo3/sysext/form/Tests/Unit/Domain/FormElements/AbstractSectionTest.php
typo3/sysext/form/Tests/Unit/Domain/FormElements/GridContainerTest.php [new file with mode: 0644]

index 15f3a94..1f95e2c 100644 (file)
@@ -1,41 +1,27 @@
 <?php
+declare(strict_types = 1);
 namespace TYPO3\CMS\Form\Tests\Unit\Domain\FormElements;
 
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException;
+use TYPO3\CMS\Form\Domain\Model\FormDefinition;
 use TYPO3\CMS\Form\Domain\Model\FormElements\AbstractFormElement;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 /**
- * Test TYPO3\CMS\Form\Domain\Model\FormElements\AbstractFormElement class
- *
- * Class AbstractFormElementTest
+ * Test case
  */
-class AbstractFormElementTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+class AbstractFormElementTest extends UnitTestCase
 {
-    protected static $IDENTIFIER = 'an_id';
-    protected static $TYPE = 'a_type';
-
-    /**
-     * An accessible instance of abstract class under test
-     * @var AbstractFormElement
-     */
-    protected $abstractFormElementInstance = null;
-
-    /**
-     * @before
-     */
-    public function setUp()
-    {
-        parent::setUp();
-        $this->abstractFormElementInstance = new class(self::$IDENTIFIER, self::$TYPE) extends AbstractFormElement {
-        };
-    }
-
     /**
      * @test
      */
     public function newInstanceHasNoProperties()
     {
-        $this->assertNotNull($this->abstractFormElementInstance);
-        $this->assertCount(0, $this->abstractFormElementInstance->getProperties());
+        /** @var AbstractFormElement $subject */
+        $subject = $this->getMockForAbstractClass(AbstractFormElement::class, ['an_id', 'a_type']);
+        $this->assertNotNull($subject);
+        $this->assertCount(0, $subject->getProperties());
     }
 
     /**
@@ -43,9 +29,12 @@ class AbstractFormElementTest extends \TYPO3\TestingFramework\Core\Unit\UnitTest
      */
     public function setSimpleProperties()
     {
-        $this->abstractFormElementInstance->setProperty('foo', 'bar');
-        $this->abstractFormElementInstance->setProperty('buz', 'qax');
-        $properties = $this->abstractFormElementInstance->getProperties();
+        /** @var AbstractFormElement $subject */
+        $subject = $this->getMockForAbstractClass(AbstractFormElement::class, ['an_id', 'a_type']);
+
+        $subject->setProperty('foo', 'bar');
+        $subject->setProperty('buz', 'qax');
+        $properties = $subject->getProperties();
 
         $this->assertCount(2, $properties);
         $this->assertTrue(array_key_exists('foo', $properties));
@@ -59,10 +48,13 @@ class AbstractFormElementTest extends \TYPO3\TestingFramework\Core\Unit\UnitTest
      */
     public function overrideProperties()
     {
-        $this->abstractFormElementInstance->setProperty('foo', 'bar');
-        $this->abstractFormElementInstance->setProperty('foo', 'buz');
+        /** @var AbstractFormElement $subject */
+        $subject = $this->getMockForAbstractClass(AbstractFormElement::class, ['an_id', 'a_type']);
+
+        $subject->setProperty('foo', 'bar');
+        $subject->setProperty('foo', 'buz');
 
-        $properties = $this->abstractFormElementInstance->getProperties();
+        $properties = $subject->getProperties();
         $this->assertEquals(1, count($properties));
         $this->assertTrue(array_key_exists('foo', $properties));
         $this->assertEquals('buz', $properties['foo']);
@@ -73,8 +65,11 @@ class AbstractFormElementTest extends \TYPO3\TestingFramework\Core\Unit\UnitTest
      */
     public function setArrayProperties()
     {
-        $this->abstractFormElementInstance->setProperty('foo', ['bar' => 'baz', 'bla' => 'blubb']);
-        $properties = $this->abstractFormElementInstance->getProperties();
+        /** @var AbstractFormElement $subject */
+        $subject = $this->getMockForAbstractClass(AbstractFormElement::class, ['an_id', 'a_type']);
+
+        $subject->setProperty('foo', ['bar' => 'baz', 'bla' => 'blubb']);
+        $properties = $subject->getProperties();
 
         $this->assertCount(1, $properties);
         $this->assertTrue(array_key_exists('foo', $properties));
@@ -85,4 +80,137 @@ class AbstractFormElementTest extends \TYPO3\TestingFramework\Core\Unit\UnitTest
         $this->assertTrue(array_key_exists('bar', $properties['foo']));
         $this->assertEquals('baz', $properties['foo']['bar']);
     }
+
+    /**
+     * @test
+     */
+    public function constructThrowsExceptionWhenIdentifierIsEmpty()
+    {
+        $this->expectException(IdentifierNotValidException::class);
+        $this->expectExceptionCode(1477082502);
+
+        $this->getAccessibleMockForAbstractClass(
+            AbstractFormElement::class,
+            ['', 'a_type'],
+            '',
+            true,
+            true,
+            true,
+            []
+        );
+    }
+
+    /**
+     * @test
+     */
+    public function constructMustNotThrowExceptionWhenIdentifierIsNonEmptyString()
+    {
+        $mock = $this->getAccessibleMockForAbstractClass(
+            AbstractFormElement::class,
+            ['is_in', 'a_type'],
+            '',
+            true,
+            true,
+            true,
+            []
+        );
+        self::assertInstanceOf(AbstractFormElement::class, $mock);
+    }
+
+    /**
+     * @test
+     */
+    public function initializeFormElementExpectedCallInitializeFormObjectHooks()
+    {
+        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|AbstractFormElement $abstractFormElementMock */
+        $abstractFormElementMock = $this->getAccessibleMockForAbstractClass(
+            AbstractFormElement::class,
+            [],
+            '',
+            false,
+            false,
+            true,
+            []
+        );
+        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|AbstractFormElement $secondMock */
+        $secondMock = $this->getAccessibleMockForAbstractClass(
+            AbstractFormElement::class,
+            [],
+            '',
+            false,
+            false,
+            true,
+            [
+                'initializeFormElement'
+            ]
+        );
+
+        $secondMock->
+        expects($this->once())
+            ->method('initializeFormElement')
+            ->with($abstractFormElementMock);
+
+        GeneralUtility::addInstance(get_class($secondMock), $secondMock);
+
+        $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['initializeFormElement'] = [
+            get_class($secondMock)
+        ];
+
+        $abstractFormElementMock->initializeFormElement();
+    }
+
+    /**
+     * @test
+     */
+    public function getUniqueIdentifierExpectedUnique()
+    {
+        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|AbstractFormElement $abstractFormElementMock1 */
+        $abstractFormElementMock1 = $this->getAccessibleMockForAbstractClass(
+            AbstractFormElement::class,
+            [],
+            '',
+            false,
+            false,
+            true,
+            [
+                'getRootForm'
+            ]
+        );
+
+        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|AbstractFormElement $abstractFormElementMock2 */
+        $abstractFormElementMock2 = $this->getAccessibleMockForAbstractClass(
+            AbstractFormElement::class,
+            [],
+            '',
+            false,
+            false,
+            true,
+            [
+                'getRootForm'
+            ]
+        );
+
+        $formDefinition1 = $this->createMock(FormDefinition::class);
+        $formDefinition1
+            ->method('getIdentifier')
+            ->willReturn('c');
+
+        $abstractFormElementMock1
+            ->method('getRootForm')
+            ->willReturn($formDefinition1);
+
+        $formDefinition2 = $this->createMock(FormDefinition::class);
+        $formDefinition2
+            ->method('getIdentifier')
+            ->willReturn('d');
+
+        $abstractFormElementMock2
+            ->method('getRootForm')
+            ->willReturn($formDefinition2);
+
+        self::assertNotSame(
+            $abstractFormElementMock1->getUniqueIdentifier(),
+            $abstractFormElementMock2->getUniqueIdentifier()
+        );
+    }
 }
index bb9459c..084553f 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+declare(strict_types = 1);
 namespace TYPO3\CMS\Form\Tests\Unit\Domain\FormElements;
 
 /*
@@ -14,56 +15,317 @@ namespace TYPO3\CMS\Form\Tests\Unit\Domain\FormElements;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Object\ObjectManager;
+use TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException;
 use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotFoundException;
+use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotValidException;
 use TYPO3\CMS\Form\Domain\Model\FormDefinition;
+use TYPO3\CMS\Form\Domain\Model\FormElements\AbstractFormElement;
 use TYPO3\CMS\Form\Domain\Model\FormElements\AbstractSection;
+use TYPO3\CMS\Form\Domain\Model\FormElements\UnknownFormElement;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
 /**
  * Test case
  */
-class AbstractSectionTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
+class AbstractSectionTest extends UnitTestCase
 {
+    /**
+     * @test
+     */
+    public function constructThrowsExceptionWhenIdentifierIsEmpty()
+    {
+        $this->expectException(IdentifierNotValidException::class);
+        $this->expectExceptionCode(1477082501);
+
+        $this->getAccessibleMockForAbstractClass(AbstractSection::class, ['', 'foobar']);
+    }
 
     /**
      * @test
      */
-    public function createElementThrowsExceptionIfTypeDefinitionNotFound()
+    public function constructMustNotThrowExceptionWhenIdentifierIsNonEmptyString()
     {
+        $mock = $this->getAccessibleMockForAbstractClass(AbstractSection::class, ['foobar', 'foobar']);
+        $this->assertInstanceOf(AbstractSection::class, $mock);
+    }
+
+    /**
+     * @test
+     */
+    public function createElementThrowsExceptionIfTypeDefinitionNotFoundAndSkipUnknownElementsIsFalse()
+    {
+        /** @var \PHPUnit_Framework_MockObject_MockObject|FormDefinition $rootForm */
+        $rootForm = $this->getMockBuilder(FormDefinition::class)
+            ->setMethods(['getRenderingOptions', 'getTypeDefinitions'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $rootForm
+            ->expects($this->any())
+            ->method('getRenderingOptions')
+            ->willReturn(['skipUnknownElements' => false]);
+        $rootForm
+            ->expects($this->any())
+            ->method('getTypeDefinitions')
+            ->willReturn([]);
+
         $mockAbstractSection = $this->getAccessibleMockForAbstractClass(
             AbstractSection::class,
             [],
             '',
             false,
-            true,
+            false,
             true,
             [
-                'getRootForm',
+                'getRootForm'
             ]
         );
 
-        $mockFormDefinition = $this->getAccessibleMock(FormDefinition::class, [
-            'getTypeDefinitions',
-            'getRenderingOptions'
-        ], [], '', false);
+        $mockAbstractSection
+            ->expects($this->once())
+            ->method('getRootForm')
+            ->willReturn($rootForm);
+
+        $this->expectException(TypeDefinitionNotFoundException::class);
+        $this->expectExceptionCode(1382364019);
+
+        $mockAbstractSection->_call('createElement', '', '');
+    }
 
-        $mockFormDefinition
+    /**
+     * @test
+     */
+    public function createElementReturnsUnknownElementsIfTypeDefinitionIsNotFoundAndSkipUnknownElementsIsTrue()
+    {
+        /** @var \PHPUnit_Framework_MockObject_MockObject|FormDefinition $rootForm */
+        $rootForm = $this->getMockBuilder(FormDefinition::class)
+            ->setMethods(['getRenderingOptions', 'getTypeDefinitions'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $rootForm
+            ->expects($this->any())
+            ->method('getRenderingOptions')
+            ->willReturn(['skipUnknownElements' => true]);
+        $rootForm
             ->expects($this->any())
             ->method('getTypeDefinitions')
             ->willReturn([]);
 
-        $mockFormDefinition
+        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|AbstractSection $mockAbstractSection */
+        $mockAbstractSection = $this->getAccessibleMockForAbstractClass(
+            AbstractSection::class,
+            [],
+            '',
+            false,
+            false,
+            true,
+            [
+                'getRootForm'
+            ]
+        );
+
+        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|AbstractSection $mockAbstractSection */
+        $mockAbstractSection
+            ->expects($this->any())
+            ->method('getRootForm')
+            ->willReturn($rootForm);
+
+        $objectManager = $this->getMockBuilder(ObjectManager::class)
+            ->setMethods(['get'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $objectManager
+            ->expects($this->any())
+            ->method('get')
+            ->willReturn(new UnknownFormElement('foo', 'bar'));
+
+        GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManager);
+        $result = $mockAbstractSection->createElement('foo', 'bar');
+        GeneralUtility::removeSingletonInstance(ObjectManager::class, $objectManager);
+
+        $this->assertInstanceOf(UnknownFormElement::class, $result);
+        $this->assertSame('foo', $result->getIdentifier());
+        $this->assertSame('bar', $result->getType());
+    }
+
+    /**
+     * @test
+     */
+    public function createElementThrowsExceptionIfTypeDefinitionIsNotSet()
+    {
+        /** @var \PHPUnit_Framework_MockObject_MockObject|FormDefinition $rootForm */
+        $rootForm = $this->getMockBuilder(FormDefinition::class)
+            ->setMethods(['getRenderingOptions', 'getTypeDefinitions'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $rootForm
             ->expects($this->any())
             ->method('getRenderingOptions')
-            ->willReturn(['skipUnknownElements' => false]);
+            ->willReturn(['skipUnknownElements' => true]);
+        $rootForm
+            ->expects($this->any())
+            ->method('getTypeDefinitions')
+            ->willReturn(['foobar' => []]);
+
+        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|AbstractSection $mockAbstractSection */
+        $mockAbstractSection = $this->getAccessibleMockForAbstractClass(
+            AbstractSection::class,
+            [],
+            '',
+            false,
+            false,
+            true,
+            [
+                'getRootForm'
+            ]
+        );
 
         $mockAbstractSection
             ->expects($this->any())
             ->method('getRootForm')
-            ->willReturn($mockFormDefinition);
+            ->willReturn($rootForm);
 
         $this->expectException(TypeDefinitionNotFoundException::class);
-        $this->expectExceptionCode(1382364019);
+        $this->expectExceptionCode(1325689855);
 
-        $mockAbstractSection->_call('createElement', '', '');
+        $mockAbstractSection->createElement('id', 'foobar');
+    }
+
+    /**
+     * @test
+     */
+    public function createElementThrowsExceptionIfTypeDefinitionNotInstanceOfFormElementInterface()
+    {
+        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|AbstractSection $mockAbstractSection */
+        $mockAbstractSection = $this->getAccessibleMockForAbstractClass(
+            AbstractSection::class,
+            [],
+            '',
+            false,
+            false,
+            true,
+            [
+                'getRootForm'
+            ]
+        );
+
+        /** @var \PHPUnit_Framework_MockObject_MockObject|FormDefinition $rootForm */
+        $rootForm = $this->getMockBuilder(FormDefinition::class)
+            ->setMethods(['getRenderingOptions', 'getTypeDefinitions'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $rootForm
+            ->expects($this->any())
+            ->method('getRenderingOptions')
+            ->willReturn([]);
+        $rootForm
+            ->expects($this->any())
+            ->method('getTypeDefinitions')
+            ->willReturn(
+                [
+                    'foobar' => [
+                        'implementationClassName' => self::class
+                    ]
+                ]
+            );
+
+        $mockAbstractSection
+            ->expects($this->any())
+            ->method('getRootForm')
+            ->willReturn($rootForm);
+
+        $objectManager = $this->createMock(ObjectManager::class);
+        $objectManager
+            ->method('get')
+            ->with(self::class)
+            ->willReturn($this);
+
+        GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManager);
+
+        $this->expectException(TypeDefinitionNotValidException::class);
+        $this->expectExceptionCode(1327318156);
+        $mockAbstractSection->createElement('id', 'foobar');
+
+        GeneralUtility::removeSingletonInstance(ObjectManager::class, $objectManager);
+    }
+
+    /**
+     * @test
+     */
+    public function createElementExpectedToAddAndInitializeElement()
+    {
+        $implementationMock = $this->getMockForAbstractClass(
+            AbstractFormElement::class,
+            [],
+            '',
+            false,
+            false,
+            true,
+            ['setOptions', 'initializeFormElement']
+        );
+
+        $typeDefinition = [
+            'foo' => 'bar',
+            'implementationClassName' => get_class($implementationMock),
+            'fizz' => 'buzz'
+        ];
+
+        $typeDefinitionWithoutImplementationClassName = $typeDefinition;
+        unset($typeDefinitionWithoutImplementationClassName['implementationClassName']);
+
+        $implementationMock
+            ->expects($this->once())
+            ->method('initializeFormElement');
+
+        $implementationMock
+            ->expects($this->once())
+            ->method('setOptions')
+            ->with($typeDefinitionWithoutImplementationClassName);
+
+        /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface|AbstractSection $mockAbstractSection */
+        $mockAbstractSection = $this->getAccessibleMockForAbstractClass(
+            AbstractSection::class,
+            [],
+            '',
+            false,
+            false,
+            true,
+            [
+                'getRootForm'
+            ]
+        );
+
+        /** @var \PHPUnit_Framework_MockObject_MockObject|FormDefinition $rootForm */
+        $rootForm = $this->getMockBuilder(FormDefinition::class)
+            ->setMethods(['getRenderingOptions', 'getTypeDefinitions'])
+            ->disableOriginalConstructor()
+            ->getMock();
+        $rootForm
+            ->expects($this->any())
+            ->method('getRenderingOptions')
+            ->willReturn([]);
+        $rootForm
+            ->expects($this->any())
+            ->method('getTypeDefinitions')
+            ->willReturn(['foobar' => $typeDefinition]);
+
+        $mockAbstractSection
+            ->expects($this->any())
+            ->method('getRootForm')
+            ->willReturn($rootForm);
+
+        $objectManager = $this->createMock(ObjectManager::class);
+        $objectManager
+            ->method('get')
+            ->with(get_class($implementationMock))
+            ->willReturn($implementationMock);
+
+        GeneralUtility::setSingletonInstance(ObjectManager::class, $objectManager);
+
+        $mockAbstractSection->createElement('id', 'foobar');
+
+        GeneralUtility::removeSingletonInstance(ObjectManager::class, $objectManager);
     }
 }
diff --git a/typo3/sysext/form/Tests/Unit/Domain/FormElements/GridContainerTest.php b/typo3/sysext/form/Tests/Unit/Domain/FormElements/GridContainerTest.php
new file mode 100644 (file)
index 0000000..a1d0c01
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Form\Tests\Unit\Domain\FormElements;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotValidException;
+use TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface;
+use TYPO3\CMS\Form\Domain\Model\FormElements\GridContainer;
+use TYPO3\CMS\Form\Domain\Model\FormElements\GridContainerInterface;
+use TYPO3\CMS\Form\Domain\Model\FormElements\GridRowInterface;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+/**
+ * Test case
+ */
+class GridContainerTest extends UnitTestCase
+{
+
+    /**
+     * @test
+     */
+    public function registerInFormIfPossibleThrowsTypeDefinitionNotValidExceptionIfAChildIsGridContainerInterface()
+    {
+        /** @var \PHPUnit_Framework_MockObject_MockObject|GridContainerInterface $gridContainerInterfaceMock */
+        $gridContainerInterfaceMock = $this->createMock(GridContainerInterface::class);
+        $gridContainerInterfaceMock
+            ->expects($this->any())
+            ->method('getIdentifier')
+            ->willReturn('bar');
+
+        /** @var \PHPUnit_Framework_MockObject_MockObject|GridContainer $gridContainerMock */
+        $gridContainerMock = $this->getMockBuilder(GridContainer::class)
+            ->setMethods(['getIdentifier', 'getElementsRecursively'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $gridContainerMock
+            ->expects($this->any())
+            ->method('getIdentifier')
+            ->willReturn('foo');
+
+        $gridContainerMock
+            ->expects($this->any())
+            ->method('getElementsRecursively')
+            ->willReturn([$gridContainerInterfaceMock]);
+
+        $this->assertSame([$gridContainerInterfaceMock], $gridContainerMock->getElementsRecursively());
+        $this->assertTrue($gridContainerMock->getElementsRecursively()[0] instanceof GridContainerInterface);
+
+        $this->expectException(TypeDefinitionNotValidException::class);
+        $this->expectExceptionCode(1489412790);
+
+        $gridContainerMock->registerInFormIfPossible();
+    }
+
+    /**
+     * @test
+     */
+    public function addElementThrowsTypeDefinitionNotValidExceptionIfNotInstanceOfGridRowInterface()
+    {
+        /** @var \PHPUnit_Framework_MockObject_MockObject|FormElementInterface $element */
+        $element = $this->createMock(FormElementInterface::class);
+
+        /** @var \PHPUnit_Framework_MockObject_MockObject|GridContainer $gridContainer */
+        $gridContainer = $this->getMockBuilder(GridContainer::class)
+            ->setMethods(['getElementsRecursively'])
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $element
+            ->expects($this->any())
+            ->method('getIdentifier')
+            ->willReturn('foobar');
+
+        $element
+            ->expects($this->any())
+            ->method('getType')
+            ->willReturn('FormElementOrSomethingLikeThat');
+
+        $gridContainer
+            ->expects($this->any())
+            ->method('getElementsRecursively')
+            ->willReturn($element);
+
+        $this->expectException(TypeDefinitionNotValidException::class);
+        $this->expectExceptionCode(1489486301);
+
+        $gridContainer->addElement($element);
+    }
+
+    /**
+     * @test
+     */
+    public function addElementExpectedCallAddRenderableIfInstanceOfGridRowInterface()
+    {
+        /** @var \PHPUnit_Framework_MockObject_MockObject|GridRowInterface $element */
+        $element = $this->createMock(GridRowInterface::class);
+
+        /** @var GridContainer|\PHPUnit_Framework_MockObject_MockObject $gridContainer */
+        $gridContainer = $this->getAccessibleMockForAbstractClass(
+            GridContainer::class,
+            [],
+            '',
+            [],
+            true,
+            true,
+            ['addRenderable']
+        );
+
+        $gridContainer->expects($this->once())->method('addRenderable');
+        $gridContainer->addElement($element);
+    }
+}