GivenInput('test'); $oOutputIO = $this->GivenOutput('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->GivenInput('test'); $oOutputIO1 = $this->GivenOutput('test1'); $oOutputIO2 = $this->GivenOutput('test2'); // When new FormBinding($oOutputIO1, $oInputIO); // Then $this->expectException(FormBlockIOException::class); new FormBinding($oOutputIO2, $oInputIO); } public function testBindingTwiceToTheSameOutputIsNotPossible() { $oOutputIO1 = $this->GivenOutput('test1'); $oOutputIO2 = $this->GivenOutput('test2'); $oOutputIO3 = $this->GivenOutput('test3'); // When new FormBinding($oOutputIO1, $oOutputIO3); // Then $this->expectException(FormBlockIOException::class); new FormBinding($oOutputIO2, $oOutputIO3); } public function testOutputCanBeBoundToInputAndInputIsBoundAfterThat() { $oInputIO = $this->GivenInput('test'); $oOutputIO = $this->GivenOutput('test1'); $this->assertFalse($oInputIO->IsBound(), 'Input must not be Bound by default'); // When $oOutputIO->BindToInput($oInputIO); // Then $this->assertTrue($oInputIO->IsBound(), 'Input must be Bound when binding from an output'); } public function testInputCanBeBoundToAnotherInputAndItIsBoundAfterThat() { $oInputIO1 = $this->GivenInput('test1'); $oInputIO2 = $this->GivenInput('test2'); // When $oInputIO1->BindToInput($oInputIO2); // Then $this->assertTrue($oInputIO2->IsBound(), 'Input must be Bound when binding from an input'); } public function testOutputCanBeBoundToAnotherOutputAndItIsBoundAfterThat() { $oOutputIO1 = $this->GivenOutput('test1'); $oOutputIO2 = $this->GivenOutput('test2'); $this->assertFalse($oOutputIO2->IsBound(), 'Output must not be bound by default'); // When $oOutputIO1->BindToOutput($oOutputIO2); // Then $this->assertTrue($oOutputIO2->IsBound(), 'Output must be Bound when binding from an output'); } public function testOutBindingsAreStoredWhenBindToInput() { $oInputIO1 = $this->GivenInput('test1'); $oInputIO2 = $this->GivenInput('test2'); $oOutputIO1 = $this->GivenOutput('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->GivenOutput('test1'); $oOutputIO2 = $this->GivenOutput('test2'); $oOutputIO3 = $this->GivenOutput('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'); } public function testSourceValueIsPropagatedToDestIO() { $oOutputIO1 = $this->GivenOutput('test1'); $oInputIO1 = $this->GivenInput('test1'); $oBinding = $oOutputIO1->BindToInput($oInputIO1); $oOutputIO1->SetValue(FormEvents::PRE_SET_DATA, 'The Value'); // When $oBinding->PropagateValues(); // Then $this->assertEquals('The Value', $oOutputIO1->GetValue(FormEvents::PRE_SET_DATA)); } /** * @dataProvider BindingIncompatibleFormatsProvider * * @param string $sSourceFormat * @param string $sDestinationFormat * * @return void */ public function testBindingIncompatibleFormatsThrowsException(string $sSourceFormat, string $sDestinationFormat) { $oOutputIO = $this->GivenOutput('test', $sSourceFormat); $oInputIO = $this->GivenInput('test', $sDestinationFormat); $this->expectException(FormBlockIOException::class); $oOutputIO->BindToInput($oInputIO); } public function BindingIncompatibleFormatsProvider(): array { return [ 'Attribute -> Boolean' => [AttributeIOFormat::class, BooleanIOFormat::class], 'Attribute -> Class' => [AttributeIOFormat::class, ClassIOFormat::class], 'Attribute -> Number' => [AttributeIOFormat::class, NumberIOFormat::class], 'Boolean => Attribute' => [BooleanIOFormat::class, AttributeIOFormat::class], 'Boolean => Class' => [BooleanIOFormat::class, ClassIOFormat::class], 'Boolean => Number' => [BooleanIOFormat::class, NumberIOFormat::class], 'Boolean -> String' => [BooleanIOFormat::class, StringIOFormat::class], 'Class => Attribute' => [ClassIOFormat::class, AttributeIOFormat::class], 'Class => Boolean' => [ClassIOFormat::class, BooleanIOFormat::class], 'Class => Number' => [ClassIOFormat::class, NumberIOFormat::class], 'Number => Attribute' => [NumberIOFormat::class, AttributeIOFormat::class], 'Number => Class' => [NumberIOFormat::class, ClassIOFormat::class], 'Number => Boolean' => [NumberIOFormat::class, BooleanIOFormat::class], 'Number -> String' => [NumberIOFormat::class, StringIOFormat::class], 'String => Attribute' => [StringIOFormat::class, AttributeIOFormat::class], 'String => Class' => [StringIOFormat::class, ClassIOFormat::class], 'String => Boolean' => [StringIOFormat::class, BooleanIOFormat::class], 'String -> Number' => [StringIOFormat::class, NumberIOFormat::class], ]; } /** * @dataProvider BindingCompatibleFormatsProvider * * @param string $sSourceFormat * @param string $sDestinationFormat * * @return void */ public function testBindingCompatibleFormatsWorks(string $sSourceFormat, string $sDestinationFormat) { $oOutputIO = $this->GivenOutput('test', $sSourceFormat); $oInputIO = $this->GivenInput('test', $sDestinationFormat); $oBinding = $oOutputIO->BindToInput($oInputIO); $this->assertTrue(is_a($oBinding, FormBinding::class)); } public function BindingCompatibleFormatsProvider(): array { return [ 'Attribute -> Attribute' => [AttributeIOFormat::class, AttributeIOFormat::class], 'Attribute -> String' => [AttributeIOFormat::class, StringIOFormat::class], 'Boolean => Boolean' => [BooleanIOFormat::class, BooleanIOFormat::class], 'Class => Class' => [ClassIOFormat::class, ClassIOFormat::class], 'Class -> String' => [ClassIOFormat::class, StringIOFormat::class], 'Number => Number' => [NumberIOFormat::class, NumberIOFormat::class], 'String => String' => [StringIOFormat::class, StringIOFormat::class], ]; } }