mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-18 14:58:43 +02:00
✅ N°8772 - AbstractFormIO and FormBinding tests
This commit is contained in:
@@ -12,9 +12,9 @@ use Throwable;
|
||||
|
||||
class FormsException extends Exception
|
||||
{
|
||||
public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null, array $aContext = [])
|
||||
public function __construct(string $sMessage = '', int $iCode = 0, ?Throwable $oPrevious = null, array $aContext = [])
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
IssueLog::Exception(get_class($this).' occurs', $this, null, $aContext);
|
||||
parent::__construct($sMessage, $iCode, $oPrevious);
|
||||
IssueLog::Exception(get_class($this).' occurs: '.$sMessage, $this, null, $aContext);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,8 @@ class AbstractFormIO
|
||||
*
|
||||
* @param string $sName name of the IO
|
||||
* @param string $sType type of the IO
|
||||
*
|
||||
* @throws \Combodo\iTop\Forms\IO\FormBlockIOException
|
||||
*/
|
||||
public function __construct(string $sName, string $sType, AbstractFormBlock $oOwnerBlock)
|
||||
{
|
||||
@@ -82,12 +84,12 @@ class AbstractFormIO
|
||||
$sName = json_encode($sName);
|
||||
$sParsedName = json_encode($sParsedName);
|
||||
$sBlockName = json_encode($this->getName());
|
||||
Throw new FormBlockIOException("Input $sName does not match $sParsedName for block $sBlockName.");
|
||||
throw new FormBlockIOException("Input $sName does not match $sParsedName for block $sBlockName.");
|
||||
}
|
||||
} else {
|
||||
$sName = json_encode($sName);
|
||||
$sBlockName = json_encode($this->getName());
|
||||
Throw new FormBlockIOException("Input $sName is not valid for block $sBlockName.");
|
||||
throw new FormBlockIOException("Input $sName is not valid for block $sBlockName.");
|
||||
}
|
||||
|
||||
// Name is valid
|
||||
@@ -130,9 +132,10 @@ class AbstractFormIO
|
||||
*/
|
||||
public function GetValue(string $sEventType = null): mixed
|
||||
{
|
||||
if($sEventType === null) {
|
||||
if ($sEventType === null) {
|
||||
return $this->Value();
|
||||
}
|
||||
|
||||
return $this->aValues[$sEventType] ?? null;
|
||||
}
|
||||
|
||||
@@ -155,9 +158,10 @@ class AbstractFormIO
|
||||
*/
|
||||
public function HasEventValue(string $sEventType = null): bool
|
||||
{
|
||||
if($sEventType === null){
|
||||
if ($sEventType === null) {
|
||||
return $this->HasValue();
|
||||
}
|
||||
|
||||
return array_key_exists($sEventType, $this->aValues) && $this->aValues[$sEventType] !== null;
|
||||
}
|
||||
|
||||
@@ -208,15 +212,13 @@ class AbstractFormIO
|
||||
* @param FormInput $oDestinationIO
|
||||
*
|
||||
* @return FormBinding
|
||||
* @throws \Combodo\iTop\Forms\IO\FormBlockIOException
|
||||
*/
|
||||
public function BindToInput(FormInput $oDestinationIO): FormBinding
|
||||
{
|
||||
$oBinding = new FormBinding($this, $oDestinationIO);
|
||||
|
||||
$this->aBindingsToInputs[] = $oBinding;
|
||||
|
||||
$oDestinationIO->Attach($oBinding);
|
||||
|
||||
return $oBinding;
|
||||
}
|
||||
|
||||
@@ -226,9 +228,13 @@ class AbstractFormIO
|
||||
* @param FormBinding $oFormBinding
|
||||
*
|
||||
* @return void
|
||||
* @throws \Combodo\iTop\Forms\IO\FormBlockIOException when already bound
|
||||
*/
|
||||
public function Attach(FormBinding $oFormBinding): void
|
||||
{
|
||||
if ($this->IsBound()) {
|
||||
throw new FormBlockIOException("Can't attach ".json_encode($oFormBinding->oSourceIO->GetName())." to ".json_encode($this->GetName()).", already bound to ".json_encode($this->oBinding->oSourceIO->GetName()));
|
||||
}
|
||||
$this->oBinding = $oFormBinding;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,14 @@ class FormBinding
|
||||
/**
|
||||
* @param AbstractFormIO $oSourceIO
|
||||
* @param AbstractFormIO $oDestinationIO
|
||||
*
|
||||
* @throws \Combodo\iTop\Forms\IO\FormBlockIOException
|
||||
*/
|
||||
public function __construct(AbstractFormIO $oSourceIO, AbstractFormIO $oDestinationIO)
|
||||
{
|
||||
$this->oDestinationIO = $oDestinationIO;
|
||||
$this->oSourceIO = $oSourceIO;
|
||||
$oDestinationIO->Attach($this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,18 +87,32 @@ class FormOutput extends AbstractFormIO
|
||||
* @param FormOutput $oDestinationIO
|
||||
*
|
||||
* @return FormBinding
|
||||
* @throws \Combodo\iTop\Forms\IO\FormBlockIOException
|
||||
*/
|
||||
public function BindToOutput(FormOutput $oDestinationIO): FormBinding
|
||||
{
|
||||
$oBinding = new FormBinding($this, $oDestinationIO);
|
||||
|
||||
$this->aBindingsToOutputs[] = $oBinding;
|
||||
|
||||
$oDestinationIO->Attach($oBinding);
|
||||
|
||||
return $oBinding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetBindingsToOutputs(): array
|
||||
{
|
||||
return $this->aBindingsToOutputs;
|
||||
}
|
||||
|
||||
public function HasBindingOut(): bool
|
||||
{
|
||||
if (parent::HasBindingOut()) {
|
||||
return true; // has bindings to inputs
|
||||
}
|
||||
|
||||
return count($this->aBindingsToOutputs) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bindings.
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
namespace Combodo\iTop\Test\UnitTest\sources\Forms;
|
||||
|
||||
use Combodo\iTop\Forms\Block\AbstractFormBlock;
|
||||
use Combodo\iTop\Forms\Block\Base\FormBlock;
|
||||
use Combodo\iTop\Forms\IO\Format\RawFormat;
|
||||
use Combodo\iTop\Forms\IO\FormBinding;
|
||||
use Combodo\iTop\Forms\IO\FormInput;
|
||||
use Combodo\iTop\Forms\IO\FormOutput;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class AbstractFormsTest extends ItopDataTestCase
|
||||
{
|
||||
public function GivenRawFormBinding($sName): FormBinding
|
||||
{
|
||||
return new FormBinding($this->GivenRawOutput($sName), $this->GivenRawInput($sName));
|
||||
}
|
||||
|
||||
public function GivenRawInput(string $sName): FormInput
|
||||
{
|
||||
$oBlock = $this->GivenFormBlock($sName.'_block');
|
||||
|
||||
return new FormInput($sName.'_input', RawFormat::class, $oBlock);
|
||||
}
|
||||
|
||||
public function GivenRawOutput(string $sName): FormOutput
|
||||
{
|
||||
$oBlock = $this->GivenFormBlock($sName.'_block');
|
||||
|
||||
return new FormOutput($sName.'_output', RawFormat::class, $oBlock);
|
||||
}
|
||||
|
||||
public function GivenFormBlock(string $sName, array $aOptions = [], array $aIOs = []): AbstractFormBlock
|
||||
{
|
||||
$oBlock = new FormBlock($sName, $aOptions);
|
||||
|
||||
foreach ($aIOs as $aIO) {
|
||||
if ($aIO['io_type'] === FormInput::class) {
|
||||
$oBlock->AddInput($aIO['name'], $aIO['data_type']);
|
||||
} else {
|
||||
if (isset($aIO['converter_class'])) {
|
||||
$oBlock->AddOutput($aIO['name'], $aIO['data_type'], new $aIO['converter_class']);
|
||||
} else {
|
||||
$oBlock->AddOutput($aIO['name'], $aIO['data_type']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $oBlock;
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\sources\Forms\Block\IO;
|
||||
|
||||
use Combodo\iTop\Forms\Block\AbstractFormBlock;
|
||||
use Combodo\iTop\Forms\Block\Base\FormBlock;
|
||||
use Combodo\iTop\Forms\Block\IO\Format\RawFormat;
|
||||
use Combodo\iTop\Forms\Block\IO\FormInput;
|
||||
use Combodo\iTop\Forms\Block\IO\FormOutput;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
class AbstractFormIOTest extends ItopDataTestCase
|
||||
{
|
||||
|
||||
public function testRawBlockHasOnlyVisibilityInputs(): void
|
||||
{
|
||||
$oBlock = $this->GivenFormBlock('test');
|
||||
|
||||
self::assertEquals(['visible'], array_keys($oBlock->GetInputs()), 'Row form block have only "visible" input by default');
|
||||
self::assertEquals(['value'], array_keys($oBlock->GetOutputs()), 'Row form block have only raw output by default');
|
||||
}
|
||||
|
||||
public function testAddingOneInputToABlock_StoresIt(): void
|
||||
{
|
||||
$oBlock = $this->GivenFormBlock('test', [], [
|
||||
['io_type' => FormInput::class, 'name' => 'input', 'data_type' => RawFormat::class,],
|
||||
]);
|
||||
|
||||
self::assertCount(2, $oBlock->GetInputs(), 'Inputs must be saved in block forms');
|
||||
$aInputs = $oBlock->GetInputs();
|
||||
self::assertEquals(['visible', 'input'], array_keys($aInputs), 'Inputs must be saved in block forms');
|
||||
self::assertEquals(RawFormat::class, $oBlock->GetInput('input')->GetDataType(), 'Format must be kept in inputs saved in block forms');
|
||||
}
|
||||
|
||||
public function testAddingOneOutputToABlock_StoresIt(): void
|
||||
{
|
||||
$oBlock = $this->GivenFormBlock('test', [], [
|
||||
['io_type' => FormOutput::class, 'name' => 'output', 'data_type' => RawFormat::class],
|
||||
]);
|
||||
|
||||
self::assertCount(2, $oBlock->GetOutputs(), 'Outputs must be saved in block forms');
|
||||
$aInputs = $oBlock->GetOutputs();
|
||||
self::assertEquals(['value', 'output'], array_keys($aInputs), 'Outputs must be saved in block forms');
|
||||
self::assertEquals(RawFormat::class, $oBlock->GetOutput('output')->GetDataType(), 'Format must be kept in outputs saved in block forms');
|
||||
}
|
||||
|
||||
public function testAddingMultipleInputsAndOutputsToABlock_StoresThem(): void
|
||||
{
|
||||
$oBlock = $this->GivenFormBlock('test', [], [
|
||||
['io_type' => FormInput::class, 'name' => 'input1', 'data_type' => RawFormat::class,],
|
||||
['io_type' => FormInput::class, 'name' => 'input2', 'data_type' => RawFormat::class,],
|
||||
['io_type' => FormInput::class, 'name' => 'input3', 'data_type' => RawFormat::class,],
|
||||
['io_type' => FormOutput::class, 'name' => 'output1', 'data_type' => RawFormat::class],
|
||||
['io_type' => FormOutput::class, 'name' => 'output2', 'data_type' => RawFormat::class],
|
||||
]);
|
||||
|
||||
self::assertCount(4, $oBlock->GetInputs(), 'Inputs must be saved in block forms');
|
||||
self::assertCount(3, $oBlock->GetOutputs(), 'Outputs must be saved in block forms');
|
||||
}
|
||||
|
||||
|
||||
///////////////////////
|
||||
/// GIVEN methods
|
||||
///
|
||||
private function GivenFormBlock(string $sName, array $aOptions = [], array $aIOs = []): AbstractFormBlock
|
||||
{
|
||||
$oBlock = new FormBlock($sName, $aOptions);
|
||||
|
||||
foreach ($aIOs as $aIO) {
|
||||
if ($aIO['io_type'] === FormInput::class) {
|
||||
$oBlock->AddInput($aIO['name'], $aIO['data_type']);
|
||||
} else {
|
||||
if (isset($aIO['converter_class'])) {
|
||||
$oBlock->AddOutput($aIO['name'], $aIO['data_type'], new $aIO['converter_class']);
|
||||
} else {
|
||||
$oBlock->AddOutput($aIO['name'], $aIO['data_type']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $oBlock;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\sources\Forms\IO;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\sources\Forms\AbstractFormsTest;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
|
||||
class AbstractFormIOTest extends AbstractFormsTest
|
||||
{
|
||||
|
||||
public function testFormIoHasNoDataAtCreation()
|
||||
{
|
||||
|
||||
$oInput = $this->GivenRawInput('test');
|
||||
|
||||
$this->assertFalse($oInput->IsDataReady(), 'Created Input must no have data ready at creation');
|
||||
$this->assertFalse($oInput->HasValue(), 'Created Input must no have value at creation');
|
||||
$this->assertFalse($oInput->HasBindingOut());
|
||||
|
||||
$oOutput = $this->GivenRawOutput('test');
|
||||
|
||||
$this->assertFalse($oOutput->IsDataReady(), 'Created output must no have data ready at creation');
|
||||
$this->assertFalse($oOutput->HasValue(), 'Created output must no have value at creation');
|
||||
$this->assertFalse($oOutput->HasBindingOut());
|
||||
}
|
||||
|
||||
public function testFormIoHasDataAfterSetValue()
|
||||
{
|
||||
|
||||
$oInput = $this->GivenRawInput('test');
|
||||
$oInput->SetValue(FormEvents::POST_SET_DATA, 'test');
|
||||
|
||||
$this->assertTrue($oInput->IsDataReady(), 'Input must have data ready when set');
|
||||
$this->assertTrue($oInput->HasValue(), 'Input must have value when set');
|
||||
|
||||
$oOutput = $this->GivenRawOutput('test');
|
||||
$oOutput->SetValue(FormEvents::POST_SET_DATA, 'test');
|
||||
|
||||
$this->assertTrue($oOutput->IsDataReady(), 'Output must have data ready when set');
|
||||
$this->assertTrue($oOutput->HasValue(), 'Output must have value when set');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Forms\IO;
|
||||
|
||||
use Combodo\iTop\Forms\IO\FormBinding;
|
||||
use Combodo\iTop\Forms\IO\FormBlockIOException;
|
||||
use Combodo\iTop\Test\UnitTest\sources\Forms\AbstractFormsTest;
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2025 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
class FormBindingTest extends AbstractFormsTest
|
||||
{
|
||||
public function testCreatingABinding()
|
||||
{
|
||||
$oInputIO = $this->GivenRawInput('test');
|
||||
$oOutputIO = $this->GivenRawOutput('test');
|
||||
|
||||
// When Linking output to input
|
||||
new FormBinding($oOutputIO, $oInputIO);
|
||||
|
||||
// Then
|
||||
$this->assertTrue($oInputIO->IsBound(), 'DestinationIO must be Bound when creating a new binding');
|
||||
}
|
||||
|
||||
public function testBindingTwiceToTheSameInputIsNotPossible()
|
||||
{
|
||||
$oInputIO = $this->GivenRawInput('test');
|
||||
$oOutputIO1 = $this->GivenRawOutput('test1');
|
||||
$oOutputIO2 = $this->GivenRawOutput('test2');
|
||||
|
||||
// When
|
||||
new FormBinding($oOutputIO1, $oInputIO);
|
||||
|
||||
// Then
|
||||
$this->expectException(FormBlockIOException::class);
|
||||
new FormBinding($oOutputIO2, $oInputIO);
|
||||
}
|
||||
|
||||
public function testBindingTwiceToTheSameOutputIsNotPossible()
|
||||
{
|
||||
$oOutputIO1 = $this->GivenRawOutput('test1');
|
||||
$oOutputIO2 = $this->GivenRawOutput('test2');
|
||||
$oOutputIO3 = $this->GivenRawOutput('test3');
|
||||
|
||||
// When
|
||||
new FormBinding($oOutputIO1, $oOutputIO3);
|
||||
|
||||
// Then
|
||||
$this->expectException(FormBlockIOException::class);
|
||||
new FormBinding($oOutputIO2, $oOutputIO3);
|
||||
|
||||
}
|
||||
|
||||
public function testOutputCanBeBoundToInputAndInputIsBoundAfterThat()
|
||||
{
|
||||
$oInputIO = $this->GivenRawInput('test');
|
||||
$oOutputIO = $this->GivenRawOutput('test1');
|
||||
|
||||
// When
|
||||
$oOutputIO->BindToInput($oInputIO);
|
||||
|
||||
// Then
|
||||
$this->assertTrue($oInputIO->IsBound(), 'Input must be Bound when binding from an output');
|
||||
}
|
||||
|
||||
public function testInputCanBeBoundToAnotherInputAndItIsBoundAfterThat()
|
||||
{
|
||||
$oInputIO1 = $this->GivenRawInput('test1');
|
||||
$oInputIO2 = $this->GivenRawInput('test2');
|
||||
|
||||
// When
|
||||
$oInputIO1->BindToInput($oInputIO2);
|
||||
|
||||
// Then
|
||||
$this->assertTrue($oInputIO2->IsBound(), 'Input must be Bound when binding from an output');
|
||||
}
|
||||
|
||||
public function testOutputCanBeBoundToAnotherOutputAndItIsBoundAfterThat()
|
||||
{
|
||||
$oOutputIO1 = $this->GivenRawOutput('test1');
|
||||
$oOutputIO2 = $this->GivenRawOutput('test2');
|
||||
|
||||
// When
|
||||
$oOutputIO1->BindToOutput($oOutputIO2);
|
||||
|
||||
// Then
|
||||
$this->assertTrue($oOutputIO2->IsBound(), 'Output must be Bound when binding from an output');
|
||||
}
|
||||
|
||||
public function testOutBindingsAreStoredWhenBindToInput()
|
||||
{
|
||||
$oInputIO1 = $this->GivenRawInput('test1');
|
||||
$oInputIO2 = $this->GivenRawInput('test2');
|
||||
$oOutputIO1 = $this->GivenRawOutput('test1');
|
||||
|
||||
// When
|
||||
$oBindingO2ToI1 = $oOutputIO1->BindToInput($oInputIO1);
|
||||
|
||||
// Then
|
||||
$this->assertTrue($oOutputIO1->HasBindingOut(), 'Must have bindings after BindToInput');
|
||||
$this->assertEquals([$oBindingO2ToI1], $oOutputIO1->GetBindingsToInputs(), 'Must have bindings after BindToInput');
|
||||
|
||||
// When
|
||||
$oBindingO1ToI2 = $oOutputIO1->BindToInput($oInputIO2);
|
||||
|
||||
// Then
|
||||
$this->assertEquals([$oBindingO2ToI1, $oBindingO1ToI2], $oOutputIO1->GetBindingsToInputs(), 'Must have bindings after BindToInput');
|
||||
}
|
||||
|
||||
public function testOutBindingsAreStoredWhenBindToOutput()
|
||||
{
|
||||
$oOutputIO1 = $this->GivenRawOutput('test1');
|
||||
$oOutputIO2 = $this->GivenRawOutput('test2');
|
||||
$oOutputIO3 = $this->GivenRawOutput('test3');
|
||||
|
||||
// When
|
||||
$oBindingO1ToO2 = $oOutputIO1->BindToOutput($oOutputIO2);
|
||||
|
||||
// Then
|
||||
$this->assertTrue($oOutputIO1->HasBindingOut(), 'Must have bindings after BindToInput');
|
||||
$this->assertEquals([$oBindingO1ToO2], $oOutputIO1->GetBindingsToOutputs(), 'Must have bindings after BindToOutput');
|
||||
|
||||
// When
|
||||
$oBindingO1ToO3 = $oOutputIO1->BindToOutput($oOutputIO3);
|
||||
|
||||
// Then
|
||||
$this->assertEquals([$oBindingO1ToO2, $oBindingO1ToO3], $oOutputIO1->GetBindingsToOutputs(), 'Must have bindings after BindToOutput');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user