diff --git a/composer.json b/composer.json index fcebd9ab..69a2694f 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,6 @@ "zendframework/zend-stdlib": "~2.5" }, "require-dev": { - "zendframework/zend-i18n": "~2.5", "zendframework/zend-servicemanager": "~2.5", "fabpot/php-cs-fixer": "1.7.*", "phpunit/PHPUnit": "^4.5" diff --git a/test/ArrayInputTest.php b/test/ArrayInputTest.php index 1deb6273..940d8989 100644 --- a/test/ArrayInputTest.php +++ b/test/ArrayInputTest.php @@ -9,11 +9,8 @@ namespace ZendTest\InputFilter; -use PHPUnit_Framework_MockObject_MockObject as MockObject; -use Zend\Filter; use Zend\InputFilter\ArrayInput; use Zend\InputFilter\Exception\InvalidArgumentException; -use Zend\Validator; /** * @covers Zend\InputFilter\ArrayInput @@ -25,12 +22,7 @@ public function setUp() $this->input = new ArrayInput('foo'); } - public function testValueIsNullByDefault() - { - $this->markTestSkipped('Test is not enabled in ArrayInputTest'); - } - - public function testValueIsEmptyArrayByDefault() + public function testDefaultGetValue() { $this->assertCount(0, $this->input->getValue()); } @@ -44,137 +36,6 @@ public function testSetValueWithInvalidInputTypeThrowsInvalidArgumentException() $this->input->setValue('bar'); } - public function testValueMayBeInjected() - { - $this->input->setValue(['bar']); - $this->assertEquals(['bar'], $this->input->getValue()); - } - - public function testRetrievingValueFiltersTheValue() - { - $this->input->setValue(['bar']); - $filter = new Filter\StringToUpper(); - $this->input->getFilterChain()->attach($filter); - $this->assertEquals(['BAR'], $this->input->getValue()); - } - - public function testCanRetrieveRawValue() - { - $this->input->setValue(['bar']); - $filter = new Filter\StringToUpper(); - $this->input->getFilterChain()->attach($filter); - $this->assertEquals(['bar'], $this->input->getRawValue()); - } - - public function testValidationOperatesOnFilteredValue() - { - $this->input->setValue([' 123 ', ' 123']); - $filter = new Filter\StringTrim(); - $this->input->getFilterChain()->attach($filter); - $validator = new Validator\Digits(); - $this->input->getValidatorChain()->attach($validator); - $this->assertTrue( - $this->input->isValid(), - 'isValid() value not match. Detail . ' . json_encode($this->input->getMessages()) - ); - } - - public function testSpecifyingMessagesToInputReturnsThoseOnFailedValidation() - { - $this->input->setValue(['bar']); - $validator = new Validator\Digits(); - $this->input->getValidatorChain()->attach($validator); - $this->input->setErrorMessage('Please enter only digits'); - $this->assertFalse($this->input->isValid()); - $messages = $this->input->getMessages(); - $this->assertArrayNotHasKey(Validator\Digits::NOT_DIGITS, $messages); - $this->assertContains('Please enter only digits', $messages); - } - - public function testNotEmptyValidatorAddedWhenIsValidIsCalled() - { - $this->assertTrue($this->input->isRequired()); - $this->input->setValue(['bar', '']); - $validatorChain = $this->input->getValidatorChain(); - $this->assertEquals(0, count($validatorChain->getValidators())); - - $this->assertFalse($this->input->isValid()); - $messages = $this->input->getMessages(); - $this->assertArrayHasKey('isEmpty', $messages); - $this->assertEquals(1, count($validatorChain->getValidators())); - - // Assert that NotEmpty validator wasn't added again - $this->assertFalse($this->input->isValid()); - $this->assertEquals(1, count($validatorChain->getValidators())); - } - - public function testRequiredNotEmptyValidatorNotAddedWhenOneExists() - { - $this->assertTrue($this->input->isRequired()); - $this->input->setValue(['bar', '']); - - /** @var Validator\NotEmpty|MockObject $notEmptyMock */ - $notEmptyMock = $this->getMock(Validator\NotEmpty::class, ['isValid']); - $notEmptyMock->expects($this->exactly(1)) - ->method('isValid') - ->will($this->returnValue(false)); - - $validatorChain = $this->input->getValidatorChain(); - $validatorChain->prependValidator($notEmptyMock); - $this->assertFalse($this->input->isValid()); - - $validators = $validatorChain->getValidators(); - $this->assertEquals(1, count($validators)); - $this->assertEquals($notEmptyMock, $validators[0]['instance']); - } - - public function testDoNotInjectNotEmptyValidatorIfAnywhereInChain() - { - $this->assertTrue($this->input->isRequired()); - $this->input->setValue(['bar', '']); - - /** @var Validator\NotEmpty|MockObject $notEmptyMock */ - $notEmptyMock = $this->getMock(Validator\NotEmpty::class, ['isValid']); - $notEmptyMock->expects($this->exactly(1)) - ->method('isValid') - ->will($this->returnValue(false)); - - $validatorChain = $this->input->getValidatorChain(); - $validatorChain->attach(new Validator\Digits()); - $validatorChain->attach($notEmptyMock); - $this->assertFalse($this->input->isValid()); - - $validators = $validatorChain->getValidators(); - $this->assertEquals(2, count($validators)); - $this->assertEquals($notEmptyMock, $validators[1]['instance']); - } - - public function testNotAllowEmptyWithFilterConvertsNonemptyToEmptyIsNotValid() - { - $this->input->setValue(['nonempty']) - ->getFilterChain()->attach(new Filter\Callback(function () { - return ''; - })); - $this->assertFalse($this->input->isValid()); - } - - public function testNotAllowEmptyWithFilterConvertsEmptyToNonEmptyIsValid() - { - $this->input->setValue(['']) - ->getFilterChain()->attach(new Filter\Callback(function () { - return 'nonempty'; - })); - $this->assertTrue( - $this->input->isValid(), - 'isValid() value not match. Detail . ' . json_encode($this->input->getMessages()) - ); - } - - public function testMerge($sourceRawValue = 'bazRawValue') - { - parent::testMerge([$sourceRawValue]); - } - public function fallbackValueVsIsValidProvider() { $dataSets = parent::fallbackValueVsIsValidProvider(); @@ -206,4 +67,43 @@ public function mixedValueProvider() return $dataSets; } + + protected function createFilterChainMock($valueRaw = null, $valueFiltered = null) + { + // ArrayInput filters per each array value + if (is_array($valueRaw)) { + $valueRaw = current($valueRaw); + } + + if (is_array($valueFiltered)) { + $valueFiltered = current($valueFiltered); + } + + return parent::createFilterChainMock($valueRaw, $valueFiltered); + } + + protected function createValidatorChainMock($isValid = null, $value = null, $context = null, $messages = []) + { + // ArrayInput validates per each array value + if (is_array($value)) { + $value = current($value); + } + + return parent::createValidatorChainMock($isValid, $value, $context, $messages); + } + + protected function createNonEmptyValidatorMock($isValid, $value, $context = null) + { + // ArrayInput validates per each array value + if (is_array($value)) { + $value = current($value); + } + + return parent::createNonEmptyValidatorMock($isValid, $value, $context); + } + + protected function getDummyValue($raw = true) + { + return [parent::getDummyValue($raw)]; + } } diff --git a/test/BaseInputFilterTest.php b/test/BaseInputFilterTest.php index f2f39567..692adc93 100644 --- a/test/BaseInputFilterTest.php +++ b/test/BaseInputFilterTest.php @@ -15,7 +15,6 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject; use PHPUnit_Framework_TestCase as TestCase; use stdClass; -use Zend\Filter; use Zend\InputFilter\ArrayInput; use Zend\InputFilter\BaseInputFilter; use Zend\InputFilter\Exception\InvalidArgumentException; @@ -23,7 +22,6 @@ use Zend\InputFilter\Input; use Zend\InputFilter\InputFilterInterface; use Zend\InputFilter\InputInterface; -use Zend\Validator; /** * @covers Zend\InputFilter\BaseInputFilter @@ -349,62 +347,6 @@ public function testSetTraversableDataAndGetRawValueGetValue( ); } - public function getInputFilter() - { - $filter = $this->inputFilter; - - $foo = new Input(); - $foo->getFilterChain()->attachByName('stringtrim') - ->attachByName('alpha'); - $foo->getValidatorChain()->attach(new Validator\StringLength(3, 6)); - - $bar = new Input(); - $bar->getFilterChain()->attachByName('stringtrim'); - $bar->getValidatorChain()->attach(new Validator\Digits()); - - $baz = new Input(); - $baz->setRequired(false); - $baz->getFilterChain()->attachByName('stringtrim'); - $baz->getValidatorChain()->attach(new Validator\StringLength(1, 6)); - - $qux = new Input(); - $qux->setAllowEmpty(true); - $qux->getFilterChain()->attachByName('stringtrim'); - $qux->getValidatorChain()->attach(new Validator\StringLength(5, 6)); - - $filter->add($foo, 'foo') - ->add($bar, 'bar') - ->add($baz, 'baz') - ->add($qux, 'qux') - ->add($this->getChildInputFilter(), 'nest'); - - return $filter; - } - - public function getChildInputFilter() - { - $filter = new BaseInputFilter(); - - $foo = new Input(); - $foo->getFilterChain()->attachByName('stringtrim') - ->attachByName('alpha'); - $foo->getValidatorChain()->attach(new Validator\StringLength(3, 6)); - - $bar = new Input(); - $bar->getFilterChain()->attachByName('stringtrim'); - $bar->getValidatorChain()->attach(new Validator\Digits()); - - $baz = new Input(); - $baz->setRequired(false); - $baz->getFilterChain()->attachByName('stringtrim'); - $baz->getValidatorChain()->attach(new Validator\StringLength(1, 6)); - - $filter->add($foo, 'foo') - ->add($bar, 'bar') - ->add($baz, 'baz'); - return $filter; - } - public function testResetEmptyValidationGroupRecursively() { $data = [ @@ -414,8 +356,31 @@ public function testResetEmptyValidationGroupRecursively() 'deep-input2' => 'deep-foo2', ] ]; + $expectedData = array_merge($data, ['notSet' => null]); + /** @var Input|MockObject $resetInput */ + $flatInput = $this->getMockBuilder(Input::class) + ->enableProxyingToOriginalMethods() + ->setConstructorArgs(['flat']) + ->getMock() + ; + $flatInput->expects($this->once()) + ->method('setValue') + ->with('foo') + ; + // Inputs without value must be reset for to have clean states when use different setData arguments + /** @var Input|MockObject $flatInput */ + $resetInput = $this->getMockBuilder(Input::class) + ->enableProxyingToOriginalMethods() + ->setConstructorArgs(['notSet']) + ->getMock() + ; + $resetInput->expects($this->once()) + ->method('resetValue') + ; + $filter = $this->inputFilter; - $filter->add(new Input, 'flat'); + $filter->add($flatInput); + $filter->add($resetInput); $deepInputFilter = new BaseInputFilter; $deepInputFilter->add(new Input, 'deep-input1'); $deepInputFilter->add(new Input, 'deep-input2'); @@ -424,7 +389,7 @@ public function testResetEmptyValidationGroupRecursively() $filter->setValidationGroup(['deep' => 'deep-input1']); // reset validation group $filter->setValidationGroup(InputFilterInterface::VALIDATE_ALL); - $this->assertEquals($data, $filter->getValues()); + $this->assertEquals($expectedData, $filter->getValues()); } /* @@ -540,60 +505,20 @@ public function testValidationSkipsFieldsMarkedNotRequiredWhenNoDataPresent() ); } - public function testHasUnknown() + /** + * @dataProvider unknownScenariosProvider + */ + public function testUnknown($inputs, $data, $hasUnknown, $getUnknown) { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); + $inputFilter = $this->inputFilter; + foreach ($inputs as $name => $input) { + $inputFilter->add($input, $name); } - $filter = $this->getInputFilter(); - $validData = [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '' - ]; - $filter->setData($validData); - $this->assertFalse($filter->hasUnknown()); - - $filter = $this->getInputFilter(); - $invalidData = [ - 'bar' => '12345', - 'baz' => '', - 'gru' => '', - ]; - $filter->setData($invalidData); - $this->assertTrue($filter->hasUnknown()); - } - public function testGetUknown() - { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); - } + $inputFilter->setData($data); - $filter = $this->getInputFilter(); - $unknown = [ - 'bar' => '12345', - 'baz' => '', - 'gru' => 10, - 'test' => 'ok', - ]; - $filter->setData($unknown); - $unknown = $filter->getUnknown(); - $this->assertEquals(2, count($unknown)); - $this->assertArrayHasKey('gru', $unknown); - $this->assertEquals(10, $unknown['gru']); - $this->assertArrayHasKey('test', $unknown); - $this->assertEquals('ok', $unknown['test']); - - $filter = $this->getInputFilter(); - $validData = [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '' - ]; - $filter->setData($validData); - $unknown = $filter->getUnknown(); - $this->assertEquals(0, count($unknown)); + $this->assertEquals($getUnknown, $inputFilter->getUnknown(), 'getUnknown() value not match'); + $this->assertEquals($hasUnknown, $inputFilter->hasUnknown(), 'hasUnknown() value not match'); } public function testGetInputs() @@ -631,53 +556,6 @@ public function testAddingExistingInputWillMergeIntoExisting() $this->assertFalse($filter->get('foo')->isRequired()); } - /** - * @group 5270 - * @requires extension intl - */ - public function testIsValidWhenValuesSetOnFilters() - { - $filter = $this->inputFilter; - - $foo = new Input(); - $foo->getFilterChain()->attachByName('stringtrim') - ->attachByName('alpha'); - $foo->getValidatorChain()->attach(new Validator\StringLength(15, 18)); - - $filter->add($foo, 'foo'); - - //test valid with setData - $filter->setData(['foo' => 'invalid']); - $this->assertFalse($filter->isValid()); - - //test invalid with setData - $filter->setData(['foo' => 'thisisavalidstring']); - $this->assertTrue( - $filter->isValid(), - 'isValid() value not match. Detail . ' . json_encode($filter->getMessages()) - ); - - //test invalid when setting data on actual filter - $filter->get('foo')->setValue('invalid'); - $this->assertFalse($filter->get('foo')->isValid(), 'Filtered value is valid, should be invalid'); - $this->assertFalse($filter->isValid(), 'Input filter did not return value from filter'); - - //test valid when setting data on actual filter - $filter->get('foo')->setValue('thisisavalidstring'); - $this->assertTrue( - $filter->get('foo') - ->isValid(), - 'Filtered value is not valid. Detail . ' . json_encode( - $filter->get('foo') - ->getMessages() - ) - ); - $this->assertTrue( - $filter->isValid(), - 'Input filter did return value from filter. Detail . ' . json_encode($filter->getMessages()) - ); - } - /** * @group 5638 */ @@ -714,7 +592,7 @@ public function testMerge() [ 'foo', 'bar', - 'baz' + 'baz', ], array_keys($inputFilter->getInputs()) ); @@ -865,6 +743,26 @@ function (&$set) { return $dataSets; } + public function unknownScenariosProvider() + { + $inputA = $this->createInputInterfaceMock('inputA', true); + $dataA = ['inputA' => 'foo']; + $dataUnknown = ['inputUnknown' => 'unknownValue']; + $dataAAndUnknown = array_merge($dataA, $dataUnknown); + + // @codingStandardsIgnoreStart + return [ + // Description => [$inputs, $data, $hasUnknown, $getUnknown] + 'empty data and inputs' => [[] , [] , false, []], + 'empty data' => [[$inputA], [] , false, []], + 'data and fields match' => [[$inputA], $dataA , false, []], + 'data known and unknown' => [[$inputA], $dataAAndUnknown, true , $dataUnknown], + 'data unknown' => [[$inputA], $dataUnknown , true , $dataUnknown], + 'data unknown, no input' => [[] , $dataUnknown , true , $dataUnknown], + ]; + // @codingStandardsIgnoreEnd + } + public function inputProvider() { $input = $this->createInputInterfaceMock('fooInput', null); diff --git a/test/CollectionInputFilterTest.php b/test/CollectionInputFilterTest.php index c6db938a..aeefdb7b 100644 --- a/test/CollectionInputFilterTest.php +++ b/test/CollectionInputFilterTest.php @@ -9,6 +9,8 @@ namespace ZendTest\InputFilter; +use ArrayIterator; +use PHPUnit_Framework_MockObject_MockObject as MockObject; use PHPUnit_Framework_TestCase as TestCase; use stdClass; use Zend\InputFilter\BaseInputFilter; @@ -16,7 +18,6 @@ use Zend\InputFilter\Exception\RuntimeException; use Zend\InputFilter\Input; use Zend\InputFilter\InputFilter; -use Zend\Validator; /** * @covers Zend\InputFilter\CollectionInputFilter @@ -26,16 +27,16 @@ class CollectionInputFilterTest extends TestCase /** * @var CollectionInputFilter */ - protected $filter; + protected $inputFilter; public function setUp() { - $this->filter = new CollectionInputFilter(); + $this->inputFilter = new CollectionInputFilter(); } - public function testSetDataWithInvalidDataTypeThrowsInvalidArgumentException() + public function testSetInputFilterWithInvalidTypeThrowsInvalidArgumentException() { - $inputFilter = $this->filter; + $inputFilter = $this->inputFilter; $this->setExpectedException( RuntimeException::class, @@ -45,126 +46,43 @@ public function testSetDataWithInvalidDataTypeThrowsInvalidArgumentException() $inputFilter->setInputFilter(new stdClass()); } - public function getBaseInputFilter() - { - $filter = new BaseInputFilter(); - - $foo = new Input(); - $foo->getFilterChain()->attachByName('stringtrim') - ->attachByName('alpha'); - $foo->getValidatorChain()->attach(new Validator\StringLength(3, 6)); - - $bar = new Input(); - $bar->getFilterChain()->attachByName('stringtrim'); - $bar->getValidatorChain()->attach(new Validator\Digits()); - - $baz = new Input(); - $baz->setRequired(false); - $baz->getFilterChain()->attachByName('stringtrim'); - $baz->getValidatorChain()->attach(new Validator\StringLength(1, 6)); - - $filter->add($foo, 'foo') - ->add($bar, 'bar') - ->add($baz, 'baz') - ->add($this->getChildInputFilter(), 'nest'); - - return $filter; - } - - public function getChildInputFilter() + /** + * @dataProvider inputFilterProvider + */ + public function testSetInputFilter($inputFilter, $expectedType) { - $filter = new BaseInputFilter(); - - $foo = new Input(); - $foo->getFilterChain()->attachByName('stringtrim') - ->attachByName('alpha'); - $foo->getValidatorChain()->attach(new Validator\StringLength(3, 6)); - - $bar = new Input(); - $bar->getFilterChain()->attachByName('stringtrim'); - $bar->getValidatorChain()->attach(new Validator\Digits()); - - $baz = new Input(); - $baz->setRequired(false); - $baz->getFilterChain()->attachByName('stringtrim'); - $baz->getValidatorChain()->attach(new Validator\StringLength(1, 6)); - - $filter->add($foo, 'foo') - ->add($bar, 'bar') - ->add($baz, 'baz'); - return $filter; - } + $this->inputFilter->setInputFilter($inputFilter); - public function getValidCollectionData() - { - return [ - [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - 'nest' => [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - ], - ], - [ - 'foo' => ' batbaz ', - 'bar' => '54321', - 'baz' => '', - 'nest' => [ - 'foo' => ' batbaz ', - 'bar' => '54321', - 'baz' => '', - ], - ] - ]; - } - - public function testSetInputFilter() - { - $this->filter->setInputFilter(new BaseInputFilter()); - $this->assertInstanceOf(BaseInputFilter::class, $this->filter->getInputFilter()); + $this->assertInstanceOf($expectedType, $this->inputFilter->getInputFilter(), 'getInputFilter() type not match'); } public function testGetDefaultInputFilter() { - $this->assertInstanceOf(BaseInputFilter::class, $this->filter->getInputFilter()); - } - - public function testSetCount() - { - $this->filter->setCount(5); - $this->assertEquals(5, $this->filter->getCount()); - } - - public function testSetCountBelowZero() - { - $this->filter->setCount(-1); - $this->assertEquals(0, $this->filter->getCount()); + $this->assertInstanceOf(BaseInputFilter::class, $this->inputFilter->getInputFilter()); } - public function testGetCountUsesCountOfCollectionDataWhenNotSet() + /** + * @dataProvider isRequiredProvider + */ + public function testSetRequired($value) { - $collectionData = [ - ['foo' => 'bar'], - ['foo' => 'baz'] - ]; - - $this->filter->setData($collectionData); - $this->assertEquals(2, $this->filter->getCount()); + $this->inputFilter->setIsRequired($value); + $this->assertEquals($value, $this->inputFilter->getIsRequired()); } - public function testGetCountUsesSpecifiedCount() + /** + * @dataProvider countVsDataProvider + */ + public function testSetCount($count, $data, $expectedCount) { - $collectionData = [ - ['foo' => 'bar'], - ['foo' => 'baz'] - ]; + if ($count !== null) { + $this->inputFilter->setCount($count); + } + if ($data !== null) { + $this->inputFilter->setData($data); + } - $this->filter->setCount(3); - $this->filter->setData($collectionData); - $this->assertEquals(3, $this->filter->getCount()); + $this->assertEquals($expectedCount, $this->inputFilter->getCount(), 'getCount() value not match'); } /** @@ -174,564 +92,140 @@ public function testGetCountReturnsRightCountOnConsecutiveCallsWithDifferentData { $collectionData1 = [ ['foo' => 'bar'], - ['foo' => 'baz'] + ['foo' => 'baz'], ]; $collectionData2 = [ - ['foo' => 'bar'] + ['foo' => 'bar'], ]; - $this->filter->setData($collectionData1); - $this->assertEquals(2, $this->filter->getCount()); - $this->filter->setData($collectionData2); - $this->assertEquals(1, $this->filter->getCount()); + $this->inputFilter->setData($collectionData1); + $this->assertEquals(2, $this->inputFilter->getCount()); + $this->inputFilter->setData($collectionData2); + $this->assertEquals(1, $this->inputFilter->getCount()); } - public function testCanValidateValidData() + public function testInvalidCollectionIsNotValid() { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); - } + $data = 1; - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($this->getValidCollectionData()); - $this->assertTrue( - $this->filter->isValid(), - 'isValid() value not match. Detail . ' . json_encode($this->filter->getMessages()) - ); + $this->inputFilter->setData($data); + + $this->assertFalse($this->inputFilter->isValid()); } - public function testCanValidateValidDataWithNonConsecutiveKeys() - { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); + /** + * @dataProvider dataVsValidProvider + */ + public function testDataVsValid( + $required, + $count, + $data, + $inputFilter, + $expectedRaw, + $expecteValues, + $expectedValid, + $expectedMessages + ) { + $this->inputFilter->setInputFilter($inputFilter); + $this->inputFilter->setData($data); + if ($count !== null) { + $this->inputFilter->setCount($count); } + $this->inputFilter->setIsRequired($required); - $collectionData = $this->getValidCollectionData(); - $collectionData[2] = $collectionData[0]; - unset($collectionData[0]); - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($collectionData); - $this->assertTrue( - $this->filter->isValid(), - 'isValid() value not match. Detail . ' . json_encode($this->filter->getMessages()) + $this->assertEquals( + $expectedValid, + $this->inputFilter->isValid(), + 'isValid() value not match. Detail . ' . json_encode($this->inputFilter->getMessages()) ); + $this->assertEquals($expectedRaw, $this->inputFilter->getRawValues(), 'getRawValues() value not match'); + $this->assertEquals($expecteValues, $this->inputFilter->getValues(), 'getValues() value not match'); + $this->assertEquals($expectedMessages, $this->inputFilter->getMessages(), 'getMessages() value not match'); } - public function testInvalidDataReturnsFalse() + public function dataVsValidProvider() { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); - } - - $invalidCollectionData = [ - [ - 'foo' => ' bazbatlong ', - 'bar' => '12345', - 'baz' => '', - ], - [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - ] + $dataRaw = [ + 'fooInput' => 'fooRaw', ]; - - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($invalidCollectionData); - $this->assertFalse($this->filter->isValid()); - } - - public function testDataLessThanCountIsInvalid() - { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); - } - - $invalidCollectionData = [ - [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - 'nest' => [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - ], - ], + $dataFiltered = [ + 'fooInput' => 'fooFiltered', ]; - - $this->filter->setCount(2); - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($invalidCollectionData); - $this->assertFalse($this->filter->isValid()); - } - - public function testGetValues() - { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); - } - - $expectedData = [ - [ - 'foo' => 'bazbat', - 'bar' => '12345', - 'baz' => '', - 'nest' => [ - 'foo' => 'bazbat', - 'bar' => '12345', - 'baz' => '', - ], - ], - [ - 'foo' => 'batbaz', - 'bar' => '54321', - 'baz' => '', - 'nest' => [ - 'foo' => 'batbaz', - 'bar' => '54321', - 'baz' => '', - ], - ] + $colRaw = [$dataRaw]; + $colFiltered = [$dataFiltered]; + $errorMessage = [ + 'fooInput' => 'fooError', ]; - - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($this->getValidCollectionData()); - - $this->assertTrue( - $this->filter->isValid(), - 'isValid() value not match. Detail . ' . json_encode($this->filter->getMessages()) - ); - $this->assertEquals($expectedData, $this->filter->getValues()); - - $this->assertCount(2, $this->filter->getValidInput()); - foreach ($this->filter->getValidInput() as $validInputs) { - $this->assertCount(4, $validInputs); - } - } - - public function testGetRawValues() - { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); - } - - $expectedData = [ - [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - 'nest' => [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - ], - ], - [ - 'foo' => ' batbaz ', - 'bar' => '54321', - 'baz' => '', - 'nest' => [ - 'foo' => ' batbaz ', - 'bar' => '54321', - 'baz' => '', - ], - ] + $colMessages = [$errorMessage]; + + $invalidIF = function () use ($dataRaw, $dataFiltered, $errorMessage) { + return $this->createBaseInputFilterMock(false, $dataRaw, $dataFiltered, $errorMessage); + }; + $validIF = function () use ($dataRaw, $dataFiltered) { + return $this->createBaseInputFilterMock(true, $dataRaw, $dataFiltered); + }; + $isRequired = true; + + // @codingStandardsIgnoreStart + $dataSets = [ + // Description => [$required, $count, $data, $inputFilter, $expectedRaw, $expecteValues, $expectedValid, $expectedMessages] + 'Required: T, Count: N, Valid: T' => [ $isRequired, null, $colRaw, $validIF , $colRaw, $colFiltered, true , []], + 'Required: T, Count: N, Valid: F' => [ $isRequired, null, $colRaw, $invalidIF, $colRaw, $colFiltered, false, $colMessages], + 'Required: T, Count: +1, Valid: F' => [ $isRequired, 2, $colRaw, $invalidIF, $colRaw, $colFiltered, false, $colMessages], + 'Required: F, Count: N, Valid: T' => [!$isRequired, null, $colRaw, $validIF , $colRaw, $colFiltered, true , []], + 'Required: F, Count: N, Valid: F' => [!$isRequired, null, $colRaw, $invalidIF, $colRaw, $colFiltered, false, $colMessages], + 'Required: F, Count: +1, Valid: F' => [!$isRequired, 2, $colRaw, $invalidIF, $colRaw, $colFiltered, false, $colMessages], + 'Required: T, Data: [], Valid: X' => [ $isRequired, null, [] , $invalidIF, [] , [] , false, []], + 'Required: F, Data: [], Valid: X' => [!$isRequired, null, [] , $invalidIF, [] , [] , true , []], ]; + // @codingStandardsIgnoreEnd - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($this->getValidCollectionData()); + array_walk( + $dataSets, + function (&$set) { + // Create unique mock input instances for each set + $inputFilter = $set[3](); - $this->assertTrue( - $this->filter->isValid(), - 'isValid() value not match. Detail . ' . json_encode($this->filter->getMessages()) + $set[3] = $inputFilter; + } ); - $this->assertEquals($expectedData, $this->filter->getRawValues()); - } - - public function testGetMessagesForInvalidInputs() - { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); - } - - $invalidCollectionData = [ - [ - 'foo' => ' bazbattoolong ', - 'bar' => '12345', - 'baz' => '', - 'nest' => [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - ], - ], - [ - 'foo' => ' bazbat ', - 'bar' => 'notstring', - 'baz' => '', - 'nest' => [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - ], - ], - [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - 'nest' => [ - // missing 'foo' here - 'bar' => '12345', - 'baz' => '', - ], - ], - ]; - - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($invalidCollectionData); - - $this->assertFalse($this->filter->isValid()); - - $this->assertCount(3, $this->filter->getInvalidInput()); - foreach ($this->filter->getInvalidInput() as $invalidInputs) { - $this->assertCount(1, $invalidInputs); - } - $messages = $this->filter->getMessages(); - - $this->assertCount(3, $messages); - $this->assertArrayHasKey('foo', $messages[0]); - $this->assertArrayHasKey('bar', $messages[1]); - $this->assertArrayHasKey('nest', $messages[2]); - - $this->assertCount(1, $messages[0]['foo']); - $this->assertCount(1, $messages[1]['bar']); - $this->assertCount(1, $messages[2]['nest']); + return $dataSets; } public function testSetValidationGroupUsingFormStyle() { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); - } - - // forms set an array of identical validation groups for each set of data - $formValidationGroup = [ - [ - 'foo', - 'bar', - ], - [ - 'foo', - 'bar', - ], - [ - 'foo', - 'bar', - ] + $validationGroup = [ + 'fooGroup', ]; + $colValidationGroup = [$validationGroup]; - $data = [ - [ - 'foo' => ' bazbat ', - 'bar' => '12345' - ], - [ - 'foo' => ' batbaz ', - 'bar' => '54321' - ], - [ - 'foo' => ' batbaz ', - 'bar' => '54321' - ] + $dataRaw = [ + 'fooInput' => 'fooRaw', ]; - - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($data); - $this->filter->setValidationGroup($formValidationGroup); - - $this->assertTrue( - $this->filter->isValid(), - 'isValid() value not match. Detail . ' . json_encode($this->filter->getMessages()) - ); - } - - public function testEmptyCollectionIsValidByDefault() - { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); - } - - $data = []; - - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($data); + $dataFiltered = [ + 'fooInput' => 'fooFiltered', + ]; + $colRaw = [$dataRaw]; + $colFiltered = [$dataFiltered]; + $baseInputFilter = $this->createBaseInputFilterMock(true, $dataRaw, $dataFiltered); + $baseInputFilter->expects($this->once()) + ->method('setValidationGroup') + ->with($validationGroup) + ; + + $this->inputFilter->setInputFilter($baseInputFilter); + $this->inputFilter->setData($colRaw); + $this->inputFilter->setValidationGroup($colValidationGroup); $this->assertTrue( - $this->filter->isValid(), - 'isValid() value not match. Detail . ' . json_encode($this->filter->getMessages()) + $this->inputFilter->isValid(), + 'isValid() value not match. Detail . ' . json_encode($this->inputFilter->getMessages()) ); - } - - public function testEmptyCollectionIsNotValidIfRequired() - { - if (!extension_loaded('intl')) { - $this->markTestSkipped('ext/intl not enabled'); - } - - $data = []; - - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($data); - $this->filter->setIsRequired(true); - - $this->assertFalse($this->filter->isValid()); - } - - public function testSetRequired() - { - $this->filter->setIsRequired(true); - $this->assertEquals(true, $this->filter->getIsRequired()); - } - - public function testNonRequiredFieldsAreValidated() - { - $invalidCollectionData = [ - [ - 'foo' => ' bazbattoolong ', - 'bar' => '12345', - 'baz' => 'baztoolong', - 'nest' => [ - 'foo' => ' bazbat ', - 'bar' => '12345', - 'baz' => '', - ], - ] - ]; - - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($invalidCollectionData); - - $this->assertFalse($this->filter->isValid()); - $this->assertCount(2, current($this->filter->getInvalidInput())); - $this->assertArrayHasKey('baz', current($this->filter->getMessages())); - } - - public function testNestedCollectionWithEmptyChild() - { - $items_inputfilter = new BaseInputFilter(); - $items_inputfilter->add(new Input(), 'id') - ->add(new Input(), 'type'); - $items = new CollectionInputFilter(); - $items->setInputFilter($items_inputfilter); - - $groups_inputfilter = new BaseInputFilter(); - $groups_inputfilter->add(new Input(), 'group_class') - ->add($items, 'items'); - $groups = new CollectionInputFilter(); - $groups->setInputFilter($groups_inputfilter); - - $inputFilter = new BaseInputFilter(); - $inputFilter->add($groups, 'groups'); - - $preFilterdata = [ - 'groups' => [ - [ - 'group_class' => 'bar', - 'items' => [ - [ - 'id' => 100, - 'type' => 'item-1', - ], - ], - ], - [ - 'group_class' => 'bar', - 'items' => [ - [ - 'id' => 200, - 'type' => 'item-2', - ], - [ - 'id' => 300, - 'type' => 'item-3', - ], - [ - 'id' => 400, - 'type' => 'item-4', - ], - ], - ], - [ - 'group_class' => 'biz', - ], - ], - ]; - - $postFilterdata = [ - 'groups' => [ - [ - 'group_class' => 'bar', - 'items' => [ - [ - 'id' => 100, - 'type' => 'item-1', - ], - ], - ], - [ - 'group_class' => 'bar', - 'items' => [ - [ - 'id' => 200, - 'type' => 'item-2', - ], - [ - 'id' => 300, - 'type' => 'item-3', - ], - [ - 'id' => 400, - 'type' => 'item-4', - ], - ], - ], - [ - 'group_class' => 'biz', - 'items' => [], - ], - ], - ]; - - $inputFilter->setData($preFilterdata); - $inputFilter->isValid(); - $values = $inputFilter->getValues(); - $this->assertEquals($postFilterdata, $values); - } - - public function testNestedCollectionWithEmptyData() - { - $items_inputfilter = new BaseInputFilter(); - $items_inputfilter->add(new Input(), 'id') - ->add(new Input(), 'type'); - $items = new CollectionInputFilter(); - $items->setInputFilter($items_inputfilter); - - $groups_inputfilter = new BaseInputFilter(); - $groups_inputfilter->add(new Input(), 'group_class') - ->add($items, 'items'); - $groups = new CollectionInputFilter(); - $groups->setInputFilter($groups_inputfilter); - - $inputFilter = new BaseInputFilter(); - $inputFilter->add($groups, 'groups'); - - $data = [ - 'groups' => [ - [ - 'group_class' => 'bar', - 'items' => [ - [ - 'id' => 100, - 'type' => 'item-1', - ], - ], - ], - [ - 'group_class' => 'biz', - 'items' => [], - ], - [ - 'group_class' => 'bar', - 'items' => [ - [ - 'id' => 200, - 'type' => 'item-2', - ], - [ - 'id' => 300, - 'type' => 'item-3', - ], - [ - 'id' => 400, - 'type' => 'item-4', - ], - ], - ], - ], - ]; - - $inputFilter->setData($data); - $inputFilter->isValid(); - $values = $inputFilter->getValues(); - $this->assertEquals($data, $values); - } - - /** - * @group 6472 - */ - public function testNestedCollectionWhereChildDataIsNotOverwritten() - { - $items_inputfilter = new BaseInputFilter(); - $items_inputfilter->add(new Input(), 'id') - ->add(new Input(), 'type'); - $items = new CollectionInputFilter(); - $items->setInputFilter($items_inputfilter); - - $groups_inputfilter = new BaseInputFilter(); - $groups_inputfilter->add(new Input(), 'group_class') - ->add($items, 'items'); - $groups = new CollectionInputFilter(); - $groups->setInputFilter($groups_inputfilter); - - $inputFilter = new BaseInputFilter(); - $inputFilter->add($groups, 'groups'); - - $data = [ - 'groups' => [ - [ - 'group_class' => 'bar', - 'items' => [ - [ - 'id' => 100, - 'type' => 'item-100', - ], - [ - 'id' => 101, - 'type' => 'item-101', - ], - [ - 'id' => 102, - 'type' => 'item-102', - ], - [ - 'id' => 103, - 'type' => 'item-103', - ], - ], - ], - [ - 'group_class' => 'foo', - 'items' => [ - [ - 'id' => 200, - 'type' => 'item-200', - ], - [ - 'id' => 201, - 'type' => 'item-201', - ], - ], - ], - ], - ]; - - $inputFilter->setData($data); - $inputFilter->isValid(); - $values = $inputFilter->getValues(); - $this->assertEquals($data, $values); + $this->assertEquals($colRaw, $this->inputFilter->getRawValues(), 'getRawValues() value not match'); + $this->assertEquals($colFiltered, $this->inputFilter->getValues(), 'getValues() value not match'); + $this->assertEquals([], $this->inputFilter->getMessages(), 'getMessages() value not match'); } public function dataNestingCollection() @@ -739,24 +233,24 @@ public function dataNestingCollection() return [ 'count not specified' => [ 'count' => null, - 'isValid' => true + 'isValid' => true, ], 'count=0' => [ 'count' => 0, - 'isValid' => true + 'isValid' => true, ], 'count = 1' => [ 'count' => 1, - 'isValid' => true + 'isValid' => true, ], 'count = 2' => [ 'count' => 2, - 'isValid' => false + 'isValid' => false, ], 'count = 3' => [ 'count' => 3, - 'isValid' => false - ] + 'isValid' => false, + ], ]; } @@ -790,34 +284,116 @@ public function testNestingCollectionCountCached($count, $expectedIsValid) [ 'second_collection' => [ [ - 'input' => 'some value' + 'input' => 'some value', ], [ - 'input' => 'some value' - ] - ] + 'input' => 'some value', + ], + ], ], [ 'second_collection' => [ [ - 'input' => 'some value' + 'input' => 'some value', ], - ] - ] - ] + ], + ], + ], ]; $mainInputFilter->setData($data); $this->assertSame($expectedIsValid, $mainInputFilter->isValid()); } - public function testInvalidCollectionIsNotValid() + public function inputFilterProvider() { - $data = 1; + $baseInputFilter = new BaseInputFilter(); + + $inputFilterSpecificationAsArray = []; + $inputSpecificationAsTraversable = new ArrayIterator($inputFilterSpecificationAsArray); + + $inputFilterSpecificationResult = new InputFilter(); + $inputFilterSpecificationResult->getFactory()->getInputFilterManager(); + + $dataSets = [ + // Description => [inputFilter, $expectedType] + 'BaseInputFilter' => [$baseInputFilter, BaseInputFilter::class], + 'array' => [$inputFilterSpecificationAsArray, InputFilter::class], + 'Traversable' => [$inputSpecificationAsTraversable, InputFilter::class], + ]; - $this->filter->setInputFilter($this->getBaseInputFilter()); - $this->filter->setData($data); + return $dataSets; + } + + public function countVsDataProvider() + { + $data0 = []; + $data1 = ['A' => 'a']; + $data2 = ['A' => 'a', 'B' => 'b']; + + // @codingStandardsIgnoreStart + return [ + // Description => [$count, $data, $expectedCount] + 'C: -1, D: null' => [ -1, null , 0], + 'C: 0, D: null' => [ 0, null , 0], + 'C: 1, D: null' => [ 1, null , 1], + 'C: null, D: 0' => [null, $data0, 0], + 'C: null, D: 1' => [null, $data1, 1], + 'C: null, D: 2' => [null, $data2, 2], + 'C: -1, D: 0' => [ -1, $data0, 0], + 'C: 0, D: 0' => [ 0, $data0, 0], + 'C: 1, D: 0' => [ 1, $data0, 1], + 'C: -1, D: 1' => [ -1, $data1, 0], + 'C: 0, D: 1' => [ 0, $data1, 0], + 'C: 1, D: 1' => [ 1, $data1, 1], + ]; + // @codingStandardsIgnoreEnd + } + + public function isRequiredProvider() + { + return [ + 'enabled' => [true], + 'disabled' => [false], + ]; + } + + /** + * @param null|bool $isValid + * @param mixed[] $getRawValues + * @param mixed[] $getValues + * @param string[] $getMessages + * + * @return MockObject|BaseInputFilter + */ + protected function createBaseInputFilterMock( + $isValid = null, + $getRawValues = [], + $getValues = [], + $getMessages = [] + ) { + /** @var BaseInputFilter|MockObject $inputFilter */ + $inputFilter = $this->getMock(BaseInputFilter::class); + $inputFilter->method('getRawValues') + ->willReturn($getRawValues) + ; + $inputFilter->method('getValues') + ->willReturn($getValues) + ; + if (($isValid === false) || ($isValid === true)) { + $inputFilter->expects($this->once()) + ->method('isValid') + ->willReturn($isValid) + ; + } else { + $inputFilter->expects($this->never()) + ->method('isValid') + ; + } + $inputFilter->method('getMessages') + ->willReturn($getMessages) + ; - $this->assertFalse($this->filter->isValid()); + return $inputFilter; } } diff --git a/test/FileInputTest.php b/test/FileInputTest.php index 80792bf3..a3700fbb 100644 --- a/test/FileInputTest.php +++ b/test/FileInputTest.php @@ -29,13 +29,6 @@ public function setUp() $this->input->setAutoPrependUploadValidator(false); } - public function testValueMayBeInjected() - { - $value = ['tmp_name' => 'bar']; - $this->input->setValue($value); - $this->assertEquals($value, $this->input->getValue()); - } - public function testRetrievingValueFiltersTheValue() { $this->markTestSkipped('Test are not enabled in FileInputTest'); @@ -215,18 +208,6 @@ public function testCanValidateArrayOfMultiFileData() $this->assertFalse($this->input->isValid()); } - public function testSpecifyingMessagesToInputReturnsThoseOnFailedValidation() - { - $this->input->setValue(['tmp_name' => 'bar']); - $validator = new Validator\Digits(); - $this->input->getValidatorChain()->attach($validator); - $this->input->setErrorMessage('Please enter only digits'); - $this->assertFalse($this->input->isValid()); - $messages = $this->input->getMessages(); - $this->assertArrayNotHasKey(Validator\Digits::NOT_DIGITS, $messages); - $this->assertContains('Please enter only digits', $messages); - } - public function testAutoPrependUploadValidatorIsOnByDefault() { $input = new FileInput('foo'); @@ -315,12 +296,12 @@ public function testValidationsRunWithoutFileArrayDueToAjaxPost() $this->assertEquals($uploadMock, $validators[0]['instance']); } - public function testNotEmptyValidatorAddedWhenIsValidIsCalled() + public function testNotEmptyValidatorAddedWhenIsValidIsCalled($value = null) { $this->markTestSkipped('Test is not enabled in FileInputTest'); } - public function testRequiredNotEmptyValidatorNotAddedWhenOneExists() + public function testRequiredNotEmptyValidatorNotAddedWhenOneExists($value = null) { $this->markTestSkipped('Test is not enabled in FileInputTest'); } @@ -338,10 +319,7 @@ public function testFallbackValueVsIsValidRules( public function testFallbackValueVsIsValidRulesWhenValueNotSet( $required = null, - $fallbackValue = null, - $originalValue = null, - $isValid = null, - $expectedValue = null + $fallbackValue = null ) { $this->markTestSkipped('Input::setFallbackValue is not implemented on FileInput'); } @@ -394,16 +372,6 @@ public function testIsEmptyFileMultiFileOk() $this->assertFalse($this->input->isEmptyFile($rawValue)); } - public function testNotAllowEmptyWithFilterConvertsNonemptyToEmptyIsNotValid() - { - $this->markTestSkipped('does not apply to FileInput'); - } - - public function testNotAllowEmptyWithFilterConvertsEmptyToNonEmptyIsValid() - { - $this->markTestSkipped('does not apply to FileInput'); - } - /** * Specific FileInput::merge extras */ @@ -495,4 +463,9 @@ public function mixedValueProvider() ], ]; } + + protected function getDummyValue($raw = true) + { + return ['tmp_name' => 'bar']; + } } diff --git a/test/InputFilterTest.php b/test/InputFilterTest.php index 30d84c8b..45faf6e2 100644 --- a/test/InputFilterTest.php +++ b/test/InputFilterTest.php @@ -43,33 +43,6 @@ public function testCanComposeAFactory() $this->assertSame($factory, $this->inputFilter->getFactory()); } - /** - * @covers \Zend\InputFilter\BaseInputFilter::getValue - * - * @group 6028 - */ - public function testGetValueReturnsArrayIfNestedInputFilters() - { - $inputFilter = new InputFilter(); - $inputFilter->add(new Input(), 'name'); - - $this->inputFilter->add($inputFilter, 'people'); - - $data = [ - 'people' => [ - 'name' => 'Wanderson' - ] - ]; - - $this->inputFilter->setData($data); - $this->assertTrue( - $this->inputFilter->isValid(), - 'isValid() value not match. Detail . ' . json_encode($this->inputFilter->getMessages()) - ); - - $this->assertInternalType('array', $this->inputFilter->getValue('people')); - } - public function inputProvider() { $dataSets = parent::inputProvider(); diff --git a/test/InputTest.php b/test/InputTest.php index 96c3582c..e7dd27ae 100644 --- a/test/InputTest.php +++ b/test/InputTest.php @@ -12,13 +12,12 @@ use PHPUnit_Framework_MockObject_MockObject as MockObject; use PHPUnit_Framework_TestCase as TestCase; use stdClass; -use Zend\Filter; use Zend\Filter\FilterChain; use Zend\InputFilter\Input; use Zend\InputFilter\InputInterface; -use Zend\Validator; -use Zend\Validator\NotEmpty; +use Zend\Validator\NotEmpty as NotEmptyValidator; use Zend\Validator\ValidatorChain; +use Zend\Validator\ValidatorInterface; /** * @covers Zend\InputFilter\Input @@ -35,7 +34,7 @@ public function setUp() $this->input = new Input('foo'); } - public function assertRequiredValidationErrorMessage($input, $message = '') + public function assertRequiredValidationErrorMessage(Input $input, $message = '') { $message = $message ?: 'Expected failure message for required input'; $message .= ';'; @@ -43,10 +42,10 @@ public function assertRequiredValidationErrorMessage($input, $message = '') $messages = $input->getMessages(); $this->assertInternalType('array', $messages, $message . ' non-array messages array'); - $notEmpty = new NotEmpty(); + $notEmpty = new NotEmptyValidator(); $messageTemplates = $notEmpty->getOption('messageTemplates'); $this->assertSame([ - NotEmpty::IS_EMPTY => $messageTemplates[NotEmpty::IS_EMPTY], + NotEmptyValidator::IS_EMPTY => $messageTemplates[NotEmptyValidator::IS_EMPTY], ], $messages, $message . ' missing NotEmpty::IS_EMPTY key and/or contains additional messages'); } @@ -58,27 +57,27 @@ public function testConstructorRequiresAName() public function testInputHasEmptyFilterChainByDefault() { $filters = $this->input->getFilterChain(); - $this->assertInstanceOf(Filter\FilterChain::class, $filters); + $this->assertInstanceOf(FilterChain::class, $filters); $this->assertEquals(0, count($filters)); } public function testInputHasEmptyValidatorChainByDefault() { $validators = $this->input->getValidatorChain(); - $this->assertInstanceOf(Validator\ValidatorChain::class, $validators); + $this->assertInstanceOf(ValidatorChain::class, $validators); $this->assertEquals(0, count($validators)); } public function testCanInjectFilterChain() { - $chain = new Filter\FilterChain(); + $chain = $this->createFilterChainMock(); $this->input->setFilterChain($chain); $this->assertSame($chain, $this->input->getFilterChain()); } public function testCanInjectValidatorChain() { - $chain = new Validator\ValidatorChain(); + $chain = $this->createValidatorChainMock(); $this->input->setValidatorChain($chain); $this->assertSame($chain, $this->input->getValidatorChain()); } @@ -107,13 +106,13 @@ public function testAllowEmptyFlagIsMutable() public function testContinueIfEmptyFlagIsFalseByDefault() { - $input = new Input('foo'); + $input = $this->input; $this->assertFalse($input->continueIfEmpty()); } public function testContinueIfEmptyFlagIsMutable() { - $input = new Input('foo'); + $input = $this->input; $input->setContinueIfEmpty(true); $this->assertTrue($input->continueIfEmpty()); } @@ -141,7 +140,7 @@ public function testFallbackValueVsIsValidRules($required, $fallbackValue, $orig $input->setContinueIfEmpty(true); $input->setRequired($required); - $input->setValidatorChain($this->createValidatorChainMock($isValid)); + $input->setValidatorChain($this->createValidatorChainMock($isValid, $originalValue)); $input->setFallbackValue($fallbackValue); $input->setValue($originalValue); @@ -158,7 +157,7 @@ public function testFallbackValueVsIsValidRules($required, $fallbackValue, $orig /** * @dataProvider fallbackValueVsIsValidProvider */ - public function testFallbackValueVsIsValidRulesWhenValueNotSet($required, $fallbackValue, $originalValue, $isValid) + public function testFallbackValueVsIsValidRulesWhenValueNotSet($required, $fallbackValue) { $expectedValue = $fallbackValue; // Should always return the fallback value @@ -166,7 +165,7 @@ public function testFallbackValueVsIsValidRulesWhenValueNotSet($required, $fallb $input->setContinueIfEmpty(true); $input->setRequired($required); - $input->setValidatorChain($this->createValidatorChainMock($isValid)); + $input->setValidatorChain($this->createValidatorChainMock(null)); $input->setFallbackValue($fallbackValue); $this->assertTrue( @@ -258,69 +257,78 @@ public function testNotRequiredWithoutFallbackAndValueNotSetThenIsValid() $this->assertEquals([], $input->getMessages(), 'getMessages() should be empty because the input is valid'); } - public function testNotEmptyValidatorNotInjectedIfContinueIfEmptyIsTrue() + /** + * @dataProvider emptyValueProvider + */ + public function testNotEmptyValidatorNotInjectedIfContinueIfEmptyIsTrue($value) { - $input = new Input('foo'); + $input = $this->input; $input->setContinueIfEmpty(true); - $input->setValue(''); + $input->setValue($value); $input->isValid(); $validators = $input->getValidatorChain() ->getValidators(); $this->assertEmpty($validators); } - public function testValueIsNullByDefault() + public function testDefaultGetValue() { $this->assertNull($this->input->getValue()); } public function testValueMayBeInjected() { - $this->input->setValue('bar'); - $this->assertEquals('bar', $this->input->getValue()); + $valueRaw = $this->getDummyValue(); + + $this->input->setValue($valueRaw); + $this->assertEquals($valueRaw, $this->input->getValue()); } public function testRetrievingValueFiltersTheValue() { - $this->input->setValue('bar'); - $filter = new Filter\StringToUpper(); - $this->input->getFilterChain()->attach($filter); - $this->assertEquals('BAR', $this->input->getValue()); + $valueRaw = $this->getDummyValue(); + $valueFiltered = $this->getDummyValue(false); + + $filterChain = $this->createFilterChainMock($valueRaw, $valueFiltered); + + $this->input->setFilterChain($filterChain); + $this->input->setValue($valueRaw); + + $this->assertSame($valueFiltered, $this->input->getValue()); } public function testCanRetrieveRawValue() { - $this->input->setValue('bar'); - $filter = new Filter\StringToUpper(); - $this->input->getFilterChain()->attach($filter); - $this->assertEquals('bar', $this->input->getRawValue()); + $valueRaw = $this->getDummyValue(); + + $filterChain = $this->createFilterChainMock(); + + $this->input->setFilterChain($filterChain); + $this->input->setValue($valueRaw); + + $this->assertEquals($valueRaw, $this->input->getRawValue()); } public function testValidationOperatesOnFilteredValue() { - $this->input->setValue(' 123 '); - $filter = new Filter\StringTrim(); - $this->input->getFilterChain()->attach($filter); - $validator = new Validator\Digits(); - $this->input->getValidatorChain()->attach($validator); + $valueRaw = $this->getDummyValue(); + $valueFiltered = $this->getDummyValue(false); + + $filterChain = $this->createFilterChainMock($valueRaw, $valueFiltered); + + $validatorChain = $this->createValidatorChainMock(true, $valueFiltered); + + $this->input->setAllowEmpty(true); + $this->input->setFilterChain($filterChain); + $this->input->setValidatorChain($validatorChain); + $this->input->setValue($valueRaw); + $this->assertTrue( $this->input->isValid(), 'isValid() value not match. Detail . ' . json_encode($this->input->getMessages()) ); } - public function testSpecifyingMessagesToInputReturnsThoseOnFailedValidation() - { - $this->input->setValue('bar'); - $validator = new Validator\Digits(); - $this->input->getValidatorChain()->attach($validator); - $this->input->setErrorMessage('Please enter only digits'); - $this->assertFalse($this->input->isValid()); - $messages = $this->input->getMessages(); - $this->assertArrayNotHasKey(Validator\Digits::NOT_DIGITS, $messages); - $this->assertContains('Please enter only digits', $messages); - } - public function testBreakOnFailureFlagIsOffByDefault() { $this->assertFalse($this->input->breakOnFailure()); @@ -332,10 +340,13 @@ public function testBreakOnFailureFlagIsMutable() $this->assertTrue($this->input->breakOnFailure()); } - public function testNotEmptyValidatorAddedWhenIsValidIsCalled() + /** + * @dataProvider emptyValueProvider + */ + public function testNotEmptyValidatorAddedWhenIsValidIsCalled($value) { $this->assertTrue($this->input->isRequired()); - $this->input->setValue(''); + $this->input->setValue($value); $validatorChain = $this->input->getValidatorChain(); $this->assertEquals(0, count($validatorChain->getValidators())); @@ -349,16 +360,15 @@ public function testNotEmptyValidatorAddedWhenIsValidIsCalled() $this->assertEquals(1, count($validatorChain->getValidators())); } - public function testRequiredNotEmptyValidatorNotAddedWhenOneExists() + /** + * @dataProvider emptyValueProvider + */ + public function testRequiredNotEmptyValidatorNotAddedWhenOneExists($value) { - $this->assertTrue($this->input->isRequired()); - $this->input->setValue(''); + $this->input->setRequired(true); + $this->input->setValue($value); - /** @var Validator\NotEmpty|MockObject $notEmptyMock */ - $notEmptyMock = $this->getMock(Validator\NotEmpty::class, ['isValid']); - $notEmptyMock->expects($this->exactly(1)) - ->method('isValid') - ->will($this->returnValue(false)); + $notEmptyMock = $this->createNonEmptyValidatorMock(false, $value); $validatorChain = $this->input->getValidatorChain(); $validatorChain->prependValidator($notEmptyMock); @@ -369,41 +379,23 @@ public function testRequiredNotEmptyValidatorNotAddedWhenOneExists() $this->assertEquals($notEmptyMock, $validators[0]['instance']); } - public function testNotAllowEmptyWithFilterConvertsNonemptyToEmptyIsNotValid() - { - $this->input->setValue('nonempty') - ->getFilterChain()->attach(new Filter\Callback(function () { - return ''; - })); - $this->assertFalse($this->input->isValid()); - } - - public function testNotAllowEmptyWithFilterConvertsEmptyToNonEmptyIsValid() + /** + * @dataProvider emptyValueProvider + */ + public function testDoNotInjectNotEmptyValidatorIfAnywhereInChain($valueRaw, $valueFiltered) { - $this->input->setValue('') - ->getFilterChain()->attach(new Filter\Callback(function () { - return 'nonempty'; - })); - $this->assertTrue( - $this->input->isValid(), - 'isValid() value not match. Detail . ' . json_encode($this->input->getMessages()) - ); - } + $filterChain = $this->createFilterChainMock($valueRaw, $valueFiltered); + $validatorChain = $this->input->getValidatorChain(); - public function testDoNotInjectNotEmptyValidatorIfAnywhereInChain() - { - $this->assertTrue($this->input->isRequired()); - $this->input->setValue(''); + $this->input->setRequired(true); + $this->input->setFilterChain($filterChain); + $this->input->setValue($valueRaw); - /** @var Validator\NotEmpty|MockObject $notEmptyMock */ - $notEmptyMock = $this->getMock(Validator\NotEmpty::class, ['isValid']); - $notEmptyMock->expects($this->exactly(1)) - ->method('isValid') - ->will($this->returnValue(false)); + $notEmptyMock = $this->createNonEmptyValidatorMock(false, $valueFiltered); - $validatorChain = $this->input->getValidatorChain(); - $validatorChain->attach(new Validator\Digits()); + $validatorChain->attach($this->createValidatorMock(true)); $validatorChain->attach($notEmptyMock); + $this->assertFalse($this->input->isValid()); $validators = $validatorChain->getValidators(); @@ -471,8 +463,10 @@ public function testResetValueReturnsInputValueToDefaultValue($value) $this->assertEquals($originalInput, $input, 'Input was not reset to the default value state'); } - public function testMerge($sourceRawValue = 'bazRawValue') + public function testMerge() { + $sourceRawValue = $this->getDummyValue(); + $source = $this->createInputInterfaceMock(); $source->method('getName')->willReturn('bazInput'); $source->method('getErrorMessage')->willReturn('bazErrorMessage'); @@ -772,32 +766,54 @@ protected function createInputInterfaceMock() } /** + * @param mixed $valueRaw + * @param mixed $valueFiltered + * * @return FilterChain|MockObject */ - protected function createFilterChainMock() + protected function createFilterChainMock($valueRaw = null, $valueFiltered = null) { /** @var FilterChain|MockObject $filterChain */ $filterChain = $this->getMock(FilterChain::class); + $filterChain->method('filter') + ->with($valueRaw) + ->willReturn($valueFiltered) + ; + return $filterChain; } /** * @param null|bool $isValid If set stub isValid method for return the argument value. + * @param mixed $value + * @param mixed $context + * @param string[] $messages * * @return ValidatorChain|MockObject */ - protected function createValidatorChainMock($isValid = null) + protected function createValidatorChainMock($isValid = null, $value = null, $context = null, $messages = []) { /** @var ValidatorChain|MockObject $validatorChain */ $validatorChain = $this->getMock(ValidatorChain::class); - if ($isValid !== null) { - $validatorChain->method('isValid') + if (($isValid === false) || ($isValid === true)) { + $validatorChain->expects($this->once()) + ->method('isValid') + ->with($value, $context) ->willReturn($isValid) ; + } else { + $validatorChain->expects($this->never()) + ->method('isValid') + ->with($value, $context) + ; } + $validatorChain->method('getMessages') + ->willReturn($messages) + ; + return $validatorChain; } @@ -807,25 +823,26 @@ protected function createValidatorChainMock($isValid = null) * @param mixed $context * @param string[] $messages * - * @return Validator\ValidatorInterface|MockObject + * @return ValidatorInterface|MockObject */ - protected function createValidatorMock($isValid, $value, $context = null, $messages = []) + protected function createValidatorMock($isValid, $value = 'not-set', $context = null, $messages = []) { - /** @var Validator\ValidatorInterface|MockObject $validator */ - $validator = $this->getMock(Validator\ValidatorInterface::class); + /** @var ValidatorInterface|MockObject $validator */ + $validator = $this->getMock(ValidatorInterface::class); if (($isValid === false) || ($isValid === true)) { - $validator->expects($this->once()) + $isValidMethod = $validator->expects($this->once()) ->method('isValid') - ->with($value, $context) ->willReturn($isValid) ; } else { - $validator->expects($this->never()) + $isValidMethod = $validator->expects($this->never()) ->method('isValid') - ->with($value, $context) ; } + if ($value !== 'not-set') { + $isValidMethod->with($value, $context); + } $validator->method('getMessages') ->willReturn($messages) @@ -833,4 +850,33 @@ protected function createValidatorMock($isValid, $value, $context = null, $messa return $validator; } + + /** + * @param bool $isValid + * @param mixed $value + * @param mixed $context + * + * @return NotEmptyValidator|MockObject + */ + protected function createNonEmptyValidatorMock($isValid, $value, $context = null) + { + /** @var NotEmptyValidator|MockObject $notEmptyMock */ + $notEmptyMock = $this->getMock(NotEmptyValidator::class, ['isValid']); + $notEmptyMock->expects($this->once()) + ->method('isValid') + ->with($value, $context) + ->willReturn($isValid) + ; + + return $notEmptyMock; + } + + protected function getDummyValue($raw = true) + { + if ($raw) { + return 'foo'; + } else { + return 'filtered'; + } + } }