HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/helder.komma.pro/tests/Unit/ComponentAreaTest.php
<?php

namespace Tests\Unit;

use App\Komma\Dynamic\Component\Component;
use App\Komma\Dynamic\Component\ComponentAttributeKey;
use App\Komma\Dynamic\Component\ComponentSaveState;
use App\Komma\Dynamic\ComponentArea\ComponentAreaSaveState;
use App\Komma\Dynamic\ComponentArea\ComponentAreaService;
use App\Komma\Dynamic\ComponentType\ComponentType;
use App\Komma\Dynamic\ComponentType\ComponentTypeBuilder;
use App\Komma\Dynamic\ComponentType\ComponentTypeResolver;
use App\Komma\Dynamic\SaveState\SaveState;
use App\Komma\Kms\Core\Attributes\Attribute;
use App\Komma\Kms\Core\Attributes\ComponentArea;
use App\Komma\Dynamic\ComponentArea\ComponentArea as ComponentAreaModel;
use App\Komma\Kms\Core\Attributes\Documents;
use App\Komma\Kms\Core\Attributes\Models\ImageProperty;
use App\Komma\Kms\Core\Attributes\TextArea;
use App\Komma\Pages\Models\Page;
use App\Komma\Pages\Models\PageTranslation;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Collection;
use Tests\TestCase;

class ComponentAreaTest extends TestCase
{
    use DatabaseTransactions; //Automatically rolls back database actions after tests

    /**
     * @group DynamicAttributesSaveStateTest
     * @test
     */
    public function instanceCreationTest()
    {
        $ComponentAreaTypeBuilder = new ComponentTypeBuilder();
        $this->assertInstanceOf(ComponentTypeBuilder::class, $ComponentAreaTypeBuilder);
    }

    /**
     * Builds and resolves a componentType and tests its validity
     * and afterwards it tries to save it to the database.
     *
     * @group ComponentAreaTest
     * @test
     */
    public function buildAndResolveComponentAreaTypesTest()
    {
        //Definition of a dynamic group:
        //A class that groups configured instances of subclasses from the Attribute class.
        //Created using a ComponentTypeBuilder, resolved by a ComponentAreaTypesResolver

        //Build a group type that has two textarea's
        $ComponentAreaTypeBuilder = (new ComponentTypeBuilder());
        /** @var ComponentType $doubleText */
        $doubleTextComponentType = $ComponentAreaTypeBuilder
            ->setName('phpunit-double-text')
            ->setIcon('dynamic-text-text.svg')
            ->addAttribute(
                (new TextArea())
                    ->enableTinymceEditor()
                    ->setLabelText('Linker kolom')
                    ->mapValueFrom(Attribute::ValueFromItself, 'Left') //Needed to sustain Attribute integrity.
            )
            ->addAttribute(
                (new TextArea())
                    ->enableTinymceEditor()
                    ->setLabelText('Rechter kolom')
                    ->mapValueFrom(Attribute::ValueFromItself, 'Right') //Needed to sustain Attribute integrity.
            )
            ->build();

        $this->assertInstanceOf(ComponentType::class, $doubleTextComponentType);
        $this->assertInternalType('string', $doubleTextComponentType->save_state);
        $this->assertNotNull($doubleTextComponentType->id);

        //Build a group type that has one text area and one image
        $ComponentAreaTypeBuilder = (new ComponentTypeBuilder());
        /** @var ComponentType $doubleText */
        $textImageGroup = $ComponentAreaTypeBuilder
            ->setName('phpunit-text-image')
            ->setIcon('dynamic-phpunit-text-image.svg')
            ->addAttribute(
                (new TextArea())
                    ->enableTinymceEditor()
                    ->setLabelText('Tekst')
                    ->mapValueFrom(Attribute::ValueFromItself, 'Text') //Needed to sustain Attribute integrity.
            )
            ->addAttribute(
                (new Documents())
                    ->setLabelText('Plaatje')
                    ->onlyAllowImages()
                    ->setMaxDocuments(1)
                    ->setImageProperties([
                        (new ImageProperty())->setName('original')->setCropMethod(ImageProperty::Resize)->setWidth(2000),
                        (new ImageProperty())->setName('small')->setCropMethod(ImageProperty::Resize)->setWidth(300),
                    ])
                    ->mapValueFrom(Attribute::ValueFromItself, 'Image') //Needed to sustain Attribute integrity.
            )->build();

        //Resolve them. Does not only retrieve the ComponentType from the database, but also instantiates the attributes in it.
        //Notice that the ComponentAreaTypes resolver returns new instances of ComponentType. Acting as templates for ComponentAreaTypes
        $doubleTextComponentType = ComponentTypeResolver::resolve('phpunit-double-text');

        $this->assertInstanceOf(ComponentType::class, $doubleTextComponentType); //The resolve method does give the ComponentType the group type so that the ComponentType can re-render itself when it is loaded from the database
        $this->assertInstanceOf(SaveState::class, $doubleTextComponentType->save_state_instance);
        /** @var SaveState $saveStateInstance */
        $saveStateInstance = $doubleTextComponentType->save_state_instance;
        $count = 0;
        $saveStateInstance->getAttributeInstances()->each(function($attribute) use (&$count) {
           $this->assertInstanceOf(Attribute::class, $attribute);
           $count++;
        });
        $this->assertEquals(2, $count);


        $this->assertInstanceOf(ComponentType::class, ComponentTypeResolver::resolve('phpunit-text-image'));
        $this->assertEquals(0, ComponentTypeResolver::resolve('non-existing-group')->count());
        $allComponentAreas = ComponentTypeResolver::resolveAll();
        $this->assertInstanceOf(Collection::class, $allComponentAreas);
        $this->assertTrue($allComponentAreas->count() >= 2);
    }

    /**
     * @group ComponentAreaTest
     * @test
     */
    public function testComponentAreaSaveWithSingleComponent()
    {
        //Initialize the ComponentAreaService
        $componentAreaService = new ComponentAreaService();

        //Create a page for the component area so we can link the component area to it
        /** @var PageTranslation $pageTranslation */
        $pageTranslation = factory(PageTranslation::class)->create();
        /** @var Page $page */
        $page = $pageTranslation->translatable()->first();

        //Create a json string that represents a component of type 1 (double text)
        //Such json is provided by the frontend. The id of 0 means that a user pressed a button
        //to add this component to the translation. If it was an existing one it would be a greater number.
        $componentAreaJson =
        '[{
            "id":0,
            "version":"0.9",
            "componentTypeId":1,
            "data":
            {
                "ComponentArea|dynamic_group_sections|C0|A1|nl":"Left text",
                "ComponentArea|dynamic_group_sections|C0|A2|nl":"Right text"
            },
            "componentableData":{},
            "sortOrder":0
        }]';

        //Check that we have that component type in the database
        $type = ComponentTypeResolver::resolve(1);
        $this->assertInstanceOf(ComponentType::class, $type);

        //Simulate the generation of attributes in the most simple form
        $componentArea = new ComponentArea();
        $componentArea->setSubFolder('component_area_center_files');
        $componentArea->mapValueFrom(Attribute::ValueFromDynamicGroups, 'component_area_center');

        $componentArea->setAssociatedLanguage($pageTranslation->language);

        //Simulate the fillAttributes with data method from the sectionService
        $componentArea->setValue($componentAreaJson);

        //The pageTranslation should have no componentArea yet.
        $this->assertTrue($pageTranslation->componentAreas()->count() == 0);

        //Save the json from the componentArea via the service.
        $pageTranslation = $componentAreaService->saveOrUpdateComponentAreaForAttribute($page, $componentArea);

        //ComponentAreas count should be 1 after saving the the componentArea attribute
        $this->assertTrue($pageTranslation->componentAreas()->count() == 1);
        /** @var ComponentAreaModel $componentArea */
        $componentAreaModel = $pageTranslation->componentAreas()->first();

        //There should be one component for the component area. It's the double text type (componentTypeId 1)
        $this->assertTrue($componentAreaModel->components()->count() == 1);
    }

    /**
     * @test
     * @group ComponentAreaTest
     * @depends testComponentAreaSaveWithSingleComponent
     */
    public function testComponentAreaLoadWithSingleComponent()
    {
        //Save a component area that we can use later on
        //Initialize the ComponentAreaService
        $componentAreaService = new ComponentAreaService();

        //Create a page for the component area so we can link the component area to it
        /** @var PageTranslation $pageTranslation */
        $pageTranslation = factory(PageTranslation::class)->create();
        /** @var Page $page */
        $page = $pageTranslation->translatable()->first();

        //Create a json string that represents a component of type 1 (double text)
        //Such json is provided by the frontend. The id of 0 means that a user pressed a button
        //to add this component to the translation. If it was an existing one it would be a greater number.
        $componentAreaJson =
            '[{
            "id":0,
            "version":"0.9",
            "componentTypeId":1,
            "data":
            {
                "ComponentArea|component_area_center|C0|A1|nl":"Left text",
                "ComponentArea|component_area_center|C0|A2|nl":"Right text"
            },
            "componentableData":{},
            "sortOrder":0
        }]';

        $componentArea = new ComponentArea();
        $componentArea->setSubFolder('component_area_center_files');
        $componentArea->mapValueFrom(Attribute::ValueFromDynamicGroups, 'component_area_center');
        $componentArea->setAssociatedLanguage($pageTranslation->language);
        $componentArea->setValue($componentAreaJson);
        $pageTranslation = $componentAreaService->saveOrUpdateComponentAreaForAttribute($page, $componentArea);




        //Now try to load the component area and check that it is saved like it should.
        //Load the component area save state json
        $componentAreaJson = $componentAreaService->getComponentsSaveStateDataAsJsonFromModel($page, $componentArea);

        //Check that we have a json string
        $this->assertTrue(is_string($componentAreaJson));
        $this->assertTrue(strlen($componentAreaJson) > 0);
        $this->assertJson($componentAreaJson);

        //Check if we can recreate the ComponentAreaSaveState
        $componentAreaSaveState = ComponentAreaSaveState::fromJsonString($componentAreaJson);
        $this->assertInstanceOf(ComponentAreaSaveState::class, $componentAreaSaveState);
        /** @var ComponentAreaSaveState $componentAreaSaveState */

        $this->assertTrue($componentAreaSaveState->getComponentsCount() === 1);

        //Check that the component save state was saved correctly
        $componentSaveState = $componentAreaSaveState->getComponentSaveStateAt(0);

        //The id should no be 0 anymore because the component data is saved
        $this->assertNotEquals(0, $componentSaveState->getId());
        $this->assertEquals("0.9", $componentSaveState->getVersion());
        $this->assertEquals(1, $componentSaveState->getComponentTypeId());

        $data = $componentSaveState->getData();
        $this->assertCount(2, $data);

        $attributeKeysAsStrings = array_keys($data);
        $leftTextAreaAttributeKey = ComponentAttributeKey::createInstanceFromString($attributeKeysAsStrings[0]);
        $rightTextAreaAttributeKey = ComponentAttributeKey::createInstanceFromString($attributeKeysAsStrings[1]);

        $this->assertInstanceOf(ComponentAttributeKey::class, $leftTextAreaAttributeKey);
        $this->assertInstanceOf(ComponentAttributeKey::class, $rightTextAreaAttributeKey);

        $this->assertEquals("ComponentArea", $leftTextAreaAttributeKey->getAttributeShortClassName());
        $this->assertEquals("ComponentArea", $rightTextAreaAttributeKey->getAttributeShortClassName());
        $this->assertEquals("component_area_center", $leftTextAreaAttributeKey->getValuePart());
        $this->assertEquals("component_area_center", $rightTextAreaAttributeKey->getValuePart());
        $this->assertNotEquals(0, $leftTextAreaAttributeKey->getComponentId());
        $this->assertNotEquals(0, $rightTextAreaAttributeKey->getComponentId());
        $this->assertEquals(1, $leftTextAreaAttributeKey->getAttributeNumber());
        $this->assertEquals(2, $rightTextAreaAttributeKey->getAttributeNumber());
        $this->assertEquals('nl', $leftTextAreaAttributeKey->getTranslationIso2());
        $this->assertEquals('nl', $rightTextAreaAttributeKey->getTranslationIso2());

        $this->assertEquals("Left text", $data[$attributeKeysAsStrings[0]]);
        $this->assertEquals("Right text", $data[$attributeKeysAsStrings[1]]);
    }
}