From 1bb377c079623d6a7986c002495ae2ec89fce3e5 Mon Sep 17 00:00:00 2001 From: George Steel Date: Wed, 24 May 2023 15:07:38 +0100 Subject: [PATCH] Migrate tests for PHPUnit 10 compatibility Signed-off-by: George Steel --- psalm-baseline.xml | 116 +++++++++---- src/InputFilterAwareTrait.php | 2 +- test/ArrayInputTest.php | 26 ++- test/BaseInputFilterTest.php | 142 ++++++---------- test/CollectionInputFilterTest.php | 59 +++---- test/FactoryTest.php | 13 +- .../HttpServerFileInputDecoratorTest.php | 13 +- test/FileInput/PsrFileInputDecoratorTest.php | 26 ++- .../InputFilterAbstractServiceFactoryTest.php | 14 +- test/InputFilterAwareTraitTest.php | 11 +- test/InputFilterPluginManagerFactoryTest.php | 8 +- test/InputFilterPluginManagerTest.php | 52 ++---- test/InputFilterTest.php | 7 +- test/InputTest.php | 136 ++++++--------- test/OptionalInputFilterTest.php | 5 +- test/TestAsset/InputFilterAware.php | 12 ++ test/TestAsset/InputFilterInterfaceStub.php | 50 ++++++ test/TestAsset/InputInterfaceStub.php | 159 ++++++++++++++++++ test/TestAsset/UploadedFileInterfaceStub.php | 48 ++++++ test/TestAsset/ValidatorStub.php | 51 ++++++ ...utFilterCollectionsValidationGroupTest.php | 18 +- 21 files changed, 607 insertions(+), 361 deletions(-) create mode 100644 test/TestAsset/InputFilterAware.php create mode 100644 test/TestAsset/InputFilterInterfaceStub.php create mode 100644 test/TestAsset/InputInterfaceStub.php create mode 100644 test/TestAsset/UploadedFileInterfaceStub.php create mode 100644 test/TestAsset/ValidatorStub.php diff --git a/psalm-baseline.xml b/psalm-baseline.xml index a0faed02..5d159a66 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -285,6 +285,11 @@ setInputFilter + + + InputFilterInterface + + InputFilterInterface @@ -432,12 +437,16 @@ + + enableProxyingToOriginalMethods + enableProxyingToOriginalMethods + ['nested-input1', 'nested-input2']]]]> - - public function addMethodArgumentsProvider(): array - + + $dataSets + $inputTypeData $inputTypeData @@ -453,6 +462,7 @@ $set[6] + $getMessages $msg $msg $name @@ -480,14 +490,6 @@ $tmpTemplate[2] $tmpTemplate[3] - - ]]> - $dataSets ]]> + + ]]> + $input $input @@ -518,11 +528,56 @@ getName isRequired + + addMethodArgumentsProvider + contextProvider + setDataArgumentsProvider + unknownScenariosProvider + - $context $inputName + + + $errorMessage + + + [$required, $count, $data, $inputFilter, $expectedRaw, $expectedValues, $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, [] , $noValidIF(), [] , [] , false, [['isEmpty' => 'Value is required and can\'t be empty']]], + 'Required: F, Data: [], Valid: X' => [! $isRequired, null, [] , $noValidIF(), [] , [] , true , []], + ]]]> + + + ]]> + + + contextProvider + countVsDataProvider + dataNestingCollection + dataVsValidProvider + inputFilterProvider + invalidCollections + invalidDataType + isRequiredProvider + + getPluginManager @@ -532,6 +587,9 @@ breakOnFailure breakOnFailure + + inputTypeSpecificationProvider + continueIfEmpty @@ -595,23 +653,16 @@ $generator instanceof Generator - - - InputFilterAwareTrait::class - InputFilterAwareTrait::class - - - getInputFilter - getInputFilter - setInputFilter - setInputFilter - - getInstanceOf + + + pluginProvider + + * }>]]> + + defaultInvokableClassesProvider + serviceProvider + @@ -716,14 +771,6 @@ array_merge($emptyValues, $mixedValues) - - $context - $context - $context - $value - $value - $value - @@ -768,4 +815,9 @@ addServiceManager + + + collectionCountProvider + + diff --git a/src/InputFilterAwareTrait.php b/src/InputFilterAwareTrait.php index 59936f07..53f0bdc0 100644 --- a/src/InputFilterAwareTrait.php +++ b/src/InputFilterAwareTrait.php @@ -6,7 +6,7 @@ trait InputFilterAwareTrait { - /** @var InputFilterInterface */ + /** @var InputFilterInterface|null */ protected $inputFilter; /** diff --git a/test/ArrayInputTest.php b/test/ArrayInputTest.php index 0c7d78b5..db2525b7 100644 --- a/test/ArrayInputTest.php +++ b/test/ArrayInputTest.php @@ -7,8 +7,9 @@ use Laminas\Filter\FilterChain; use Laminas\InputFilter\ArrayInput; use Laminas\InputFilter\Exception\InvalidArgumentException; -use Laminas\Validator\NotEmpty; +use Laminas\Validator\NotEmpty as NotEmptyValidator; use Laminas\Validator\ValidatorChain; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\MockObject\MockObject; use Webmozart\Assert\Assert; @@ -18,9 +19,7 @@ use function current; use function is_array; -/** - * @covers \Laminas\InputFilter\ArrayInput - */ +#[CoversClass(ArrayInput::class)] class ArrayInputTest extends InputTest { protected function setUp(): void @@ -76,7 +75,7 @@ public function testSetValueWithInvalidInputTypeThrowsInvalidArgumentException() * 4: string[] * }> */ - public function fallbackValueVsIsValidProvider(): array + public static function fallbackValueVsIsValidProvider(): array { $dataSets = parent::fallbackValueVsIsValidProvider(); Assert::isArray($dataSets); @@ -95,7 +94,7 @@ public function fallbackValueVsIsValidProvider(): array * filtered: null|string|array * }> */ - public function emptyValueProvider(): iterable + public static function emptyValueProvider(): iterable { $dataSets = parent::emptyValueProvider(); Assert::isArray($dataSets); @@ -112,7 +111,7 @@ public function emptyValueProvider(): iterable * filtered: bool|int|float|string|list|object * }> */ - public function mixedValueProvider(): array + public static function mixedValueProvider(): array { $dataSets = parent::mixedValueProvider(); Assert::isArray($dataSets); @@ -167,14 +166,11 @@ static function ($values) { return parent::createValidatorChainMock($valueMap, $messages); } - /** - * @param bool $isValid - * @param mixed $value - * @param mixed $context - * @return NotEmpty&MockObject - */ - protected function createNonEmptyValidatorMock($isValid, $value, $context = null) - { + protected function createNonEmptyValidatorMock( + bool $isValid, + mixed $value, + mixed $context = null, + ): NotEmptyValidator&MockObject { // ArrayInput validates per each array value if (is_array($value)) { $value = current($value); diff --git a/test/BaseInputFilterTest.php b/test/BaseInputFilterTest.php index 3043da77..0ec4607e 100644 --- a/test/BaseInputFilterTest.php +++ b/test/BaseInputFilterTest.php @@ -12,6 +12,10 @@ use Laminas\InputFilter\InputFilterInterface; use Laminas\InputFilter\InputInterface; use Laminas\InputFilter\UnfilteredDataInterface; +use LaminasTest\InputFilter\TestAsset\InputFilterInterfaceStub; +use LaminasTest\InputFilter\TestAsset\InputInterfaceStub; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use ReflectionObject; @@ -28,9 +32,7 @@ use const JSON_THROW_ON_ERROR; -/** - * @covers \Laminas\InputFilter\BaseInputFilter - */ +#[CoversClass(BaseInputFilter::class)] class BaseInputFilterTest extends TestCase { /** @var BaseInputFilter */ @@ -207,9 +209,8 @@ public function testGetUnknownThrowExceptionIfDataWasNotSetYet(): void /** * Verify the state of the input filter is the desired after change it using the method `add()` - * - * @dataProvider addMethodArgumentsProvider */ + #[DataProvider('addMethodArgumentsProvider')] public function testAddHasGet( InputInterface|InputFilterInterface|iterable $input, ?string $name, @@ -236,9 +237,8 @@ public function testAddHasGet( /** * Verify the state of the input filter is the desired after change it using the method `add()` and `remove()` - * - * @dataProvider addMethodArgumentsProvider */ + #[DataProvider('addMethodArgumentsProvider')] public function testAddRemove( InputInterface|InputFilterInterface|iterable $input, ?string $name, @@ -268,9 +268,7 @@ public function testAddingInputWithNameDoesNotInjectNameInInput(): void self::assertEquals('foo', $foo->getName(), 'Input name should not change'); } - /** - * @dataProvider inputProvider - */ + #[DataProvider('inputProvider')] public function testReplace( InputInterface|InputFilterInterface|iterable $input, ?string $inputName, @@ -292,7 +290,6 @@ public function testReplace( } /** - * @dataProvider setDataArgumentsProvider * @param array $inputs * @param iterable $data * @param array $expectedRawValues @@ -301,6 +298,7 @@ public function testReplace( * @param list $expectedValidInputs * @param string[] $expectedMessages */ + #[DataProvider('setDataArgumentsProvider')] public function testSetDataAndGetRawValueGetValue( array $inputs, iterable $data, @@ -351,7 +349,6 @@ public function testSetDataAndGetRawValueGetValue( } /** - * @dataProvider setDataArgumentsProvider * @param array $inputs * @param iterable $data * @param array $expectedRawValues @@ -360,6 +357,7 @@ public function testSetDataAndGetRawValueGetValue( * @param list $expectedValidInputs * @param string[] $expectedMessages */ + #[DataProvider('setDataArgumentsProvider')] public function testSetTraversableDataAndGetRawValueGetValue( array $inputs, iterable $data, @@ -436,7 +434,7 @@ public function testResetEmptyValidationGroupRecursively(): void * 2: array|string * }> */ - public function contextProvider(): array + public static function contextProvider(): array { $data = ['fooInput' => 'fooValue']; $traversableData = new ArrayObject(['fooInput' => 'fooValue']); @@ -451,15 +449,15 @@ public function contextProvider(): array } /** - * @dataProvider contextProvider * @param iterable $data * @param string|array $expectedContext */ + #[DataProvider('contextProvider')] public function testValidationContext($data, ?string $customContext, $expectedContext): void { $filter = $this->inputFilter; - $input = $this->createInputInterfaceMock('fooInput', true, true, $expectedContext); + $input = self::createInputInterfaceMock('fooInput', true, true, $expectedContext); $filter->add($input, 'fooInput'); $filter->setData($data); @@ -476,7 +474,7 @@ public function testBuildValidationContextUsingInputGetRawValue(): void $expectedContext = ['fooInput' => 'fooRawValue']; $filter = $this->inputFilter; - $input = $this->createInputInterfaceMock('fooInput', true, true, $expectedContext, 'fooRawValue'); + $input = self::createInputInterfaceMock('fooInput', true, true, $expectedContext, 'fooRawValue'); $filter->add($input, 'fooInput'); $filter->setData($data); @@ -496,8 +494,8 @@ public function testContextIsTheSameWhenARequiredInputIsGivenAndOptionalInputIsM 'inputRequired' => 'inputRequiredValue', 'inputOptional' => null, ]; - $inputRequired = $this->createInputInterfaceMock('fooInput', true, true, $expectedContext); - $inputOptional = $this->createInputInterfaceMock('fooInput', false); + $inputRequired = self::createInputInterfaceMock('fooInput', true, true, $expectedContext); + $inputOptional = self::createInputInterfaceMock('fooInput', false); $filter = $this->inputFilter; $filter->add($inputRequired, 'inputRequired'); @@ -544,9 +542,7 @@ public function testValidationSkipsFieldsMarkedNotRequiredWhenNoDataPresent(): v ); } - /** - * @dataProvider unknownScenariosProvider - */ + #[DataProvider('unknownScenariosProvider')] public function testUnknown(array $inputs, array $data, bool $hasUnknown, array $getUnknown): void { $inputFilter = $this->inputFilter; @@ -705,16 +701,16 @@ public function testSetDataUsingSetDataAndApplyFiltersReturningSameAsOriginalFor } /** - * @psalm-return */ - public function addMethodArgumentsProvider(): array + public static function addMethodArgumentsProvider(): array { - $inputTypes = $this->inputProvider(); + $inputTypes = static::inputProvider(); $inputName = static fn($inputTypeData) => $inputTypeData[1]; @@ -759,7 +755,7 @@ public function addMethodArgumentsProvider(): array * 7: string[] * }> */ - public function setDataArgumentsProvider(): array + public static function setDataArgumentsProvider(): array { $iAName = 'InputA'; $iBName = 'InputB'; @@ -783,7 +779,7 @@ public function setDataArgumentsProvider(): array /** * @param array $msg - * @return callable(): InputInterface&MockObject + * @return callable(): InputInterface */ $input = function ( string $iName, @@ -795,7 +791,7 @@ public function setDataArgumentsProvider(): array $vRaw, $vFiltered ): callable { - return fn(array|null|string $context): InputInterface => $this->createInputInterfaceMock( + return fn(array|null|string $context): InputInterface => self::createInputInterfaceMock( $iName, $required, $isValid, @@ -808,10 +804,10 @@ public function setDataArgumentsProvider(): array }; $inputFilter = fn(bool $isValid, array $msg = []): callable => - function (array|null|string $context) use ($isValid, $vRaw, $vFiltered, $msg): InputFilterInterface { + function () use ($isValid, $vRaw, $vFiltered, $msg): InputFilterInterface { $vRaw = ['fooInput' => $vRaw]; $vFiltered = ['fooInput' => $vFiltered]; - return $this->createInputFilterInterfaceMock($isValid, $context, $vRaw, $vFiltered, $msg); + return BaseInputFilterTest::createInputFilterInterfaceMock($isValid, $vRaw, $vFiltered, $msg); }; // phpcs:disable Generic.Formatting.MultipleStatementAlignment.NotSame,Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma,WebimpressCodingStandard.WhiteSpace.CommaSpacing.SpacingAfterComma @@ -891,9 +887,9 @@ static function (array &$set): void { * 3: array * }> */ - public function unknownScenariosProvider(): array + public static function unknownScenariosProvider(): array { - $inputA = $this->createInputInterfaceMock('inputA', true); + $inputA = self::createInputInterfaceMock('inputA', true); $dataA = ['inputA' => 'foo']; $dataUnknown = ['inputUnknown' => 'unknownValue']; $dataAAndUnknown = array_merge($dataA, $dataUnknown); @@ -913,15 +909,15 @@ public function unknownScenariosProvider(): array /** * @psalm-return array */ - public function inputProvider(): array + public static function inputProvider(): array { - $input = $this->createInputInterfaceMock('fooInput', null); - $inputFilter = $this->createInputFilterInterfaceMock(); + $input = self::createInputInterfaceMock('fooInput', null); + $inputFilter = self::createInputFilterInterfaceMock(); // phpcs:disable WebimpressCodingStandard.WhiteSpace.CommaSpacing.SpaceBeforeComma return [ @@ -935,41 +931,19 @@ public function inputProvider(): array /** * @param array $getRawValues * @param array $getValues - * @param string[] $getMessages - * @return MockObject&InputFilterInterface + * @param array> $getMessages */ - protected function createInputFilterInterfaceMock( + private static function createInputFilterInterfaceMock( bool|null $isValid = null, - mixed $context = null, array $getRawValues = [], array $getValues = [], array $getMessages = [] - ) { - /** @var InputFilterInterface&MockObject $inputFilter */ - $inputFilter = $this->createMock(InputFilterInterface::class); - $inputFilter->method('getRawValues') - ->willReturn($getRawValues); - $inputFilter->method('getValues') - ->willReturn($getValues); - if (($isValid === false) || ($isValid === true)) { - $inputFilter->expects(self::once()) - ->method('isValid') - ->willReturn($isValid); - } else { - $inputFilter->expects(self::never()) - ->method('isValid'); - } - $inputFilter->method('getMessages') - ->willReturn($getMessages); - - return $inputFilter; + ): InputFilterInterfaceStub { + return new InputFilterInterfaceStub($isValid, $getRawValues, $getValues, $getMessages); } - /** - * @param string[] $getMessages - * @return MockObject&InputInterface - */ - protected function createInputInterfaceMock( + /** @param array $getMessages */ + private static function createInputInterfaceMock( string $name, bool|null $isRequired, bool|null $isValid = null, @@ -978,33 +952,17 @@ protected function createInputInterfaceMock( mixed $getValue = null, array $getMessages = [], bool $breakOnFailure = false - ) { - /** @var InputInterface&MockObject $input */ - $input = $this->createMock(InputInterface::class); - $input->method('getName') - ->willReturn($name); - $input->method('isRequired') - ->willReturn($isRequired); - $input->method('getRawValue') - ->willReturn($getRawValue); - $input->method('getValue') - ->willReturn($getValue); - $input->method('breakOnFailure') - ->willReturn($breakOnFailure); - if (($isValid === false) || ($isValid === true)) { - $input->expects(self::any()) - ->method('isValid') - ->with($context) - ->willReturn($isValid); - } else { - $input->expects(self::never()) - ->method('isValid') - ->with($context); - } - $input->method('getMessages') - ->willReturn($getMessages); - - return $input; + ): InputInterfaceStub { + return new InputInterfaceStub( + $name, + $isRequired, + $isValid, + $context, + $getRawValue, + $getValue, + $getMessages, + $breakOnFailure, + ); } /** diff --git a/test/CollectionInputFilterTest.php b/test/CollectionInputFilterTest.php index 1d85c2a6..dcd49763 100644 --- a/test/CollectionInputFilterTest.php +++ b/test/CollectionInputFilterTest.php @@ -15,6 +15,9 @@ use Laminas\Validator\Between; use Laminas\Validator\Digits; use Laminas\Validator\NotEmpty; +use LaminasTest\InputFilter\TestAsset\InputFilterInterfaceStub; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use stdClass; @@ -26,9 +29,9 @@ use const JSON_THROW_ON_ERROR; /** - * @covers \Laminas\InputFilter\CollectionInputFilter * @psalm-import-type InputFilterSpecification from InputFilterInterface */ +#[CoversClass(CollectionInputFilter::class)] class CollectionInputFilterTest extends TestCase { private CollectionInputFilter $inputFilter; @@ -51,10 +54,10 @@ public function testSetInputFilterWithInvalidTypeThrowsInvalidArgumentException( } /** - * @dataProvider inputFilterProvider * @param InputFilterSpecification|Traversable|BaseInputFilter $inputFilter * @param class-string $expectedType */ + #[DataProvider('inputFilterProvider')] public function testSetInputFilter(mixed $inputFilter, string $expectedType): void { $this->inputFilter->setInputFilter($inputFilter); @@ -67,18 +70,14 @@ public function testGetDefaultInputFilter(): void self::assertInstanceOf(BaseInputFilter::class, $this->inputFilter->getInputFilter()); } - /** - * @dataProvider isRequiredProvider - */ + #[DataProvider('isRequiredProvider')] public function testSetRequired(bool $value): void { $this->inputFilter->setIsRequired($value); self::assertEquals($value, $this->inputFilter->getIsRequired()); } - /** - * @dataProvider countVsDataProvider - */ + #[DataProvider('countVsDataProvider')] public function testSetCount(?int $count, ?array $data, int $expectedCount): void { if ($count !== null) { @@ -108,9 +107,7 @@ public function testGetCountReturnsRightCountOnConsecutiveCallsWithDifferentData self::assertEquals(1, $this->inputFilter->getCount()); } - /** - * @dataProvider dataVsValidProvider - */ + #[DataProvider('dataVsValidProvider')] public function testDataVsValid( bool $required, ?int $count, @@ -150,7 +147,7 @@ public function testDataVsValid( * 7: array * }> */ - public function dataVsValidProvider(): array + public static function dataVsValidProvider(): array { $dataRaw = [ 'fooInput' => 'fooRaw', @@ -166,11 +163,11 @@ public function dataVsValidProvider(): array $colMessages = [$errorMessage]; $invalidIF = fn(): BaseInputFilter => - $this->createBaseInputFilterMock(false, $dataRaw, $dataFiltered, $errorMessage); + new InputFilterInterfaceStub(false, $dataRaw, $dataFiltered, $errorMessage); $validIF = fn(): BaseInputFilter => - $this->createBaseInputFilterMock(true, $dataRaw, $dataFiltered); + new InputFilterInterfaceStub(true, $dataRaw, $dataFiltered); $noValidIF = fn(): BaseInputFilter => - $this->createBaseInputFilterMock(null, $dataRaw, $dataFiltered); + new InputFilterInterfaceStub(null, $dataRaw, $dataFiltered); $isRequired = true; // @phpcs:disable Generic.Files.LineLength.TooLong,WebimpressCodingStandard.Arrays.Format.SingleLineSpaceBefore,WebimpressCodingStandard.WhiteSpace.CommaSpacing.SpaceBeforeComma @@ -222,7 +219,7 @@ public function testSetValidationGroupUsingFormStyle(): void } /** @psalm-return array */ - public function dataNestingCollection(): array + public static function dataNestingCollection(): array { return [ 'count not specified' => [ @@ -248,9 +245,7 @@ public function dataNestingCollection(): array ]; } - /** - * @dataProvider dataNestingCollection - */ + #[DataProvider('dataNestingCollection')] public function testNestingCollectionCountCached(?int $count, bool $expectedIsValid): void { $firstInputFilter = new InputFilter(); @@ -305,7 +300,7 @@ public function testNestingCollectionCountCached(?int $count, bool $expectedIsVa * 1: class-string * }> */ - public function inputFilterProvider(): array + public static function inputFilterProvider(): array { $baseInputFilter = new BaseInputFilter(); @@ -330,7 +325,7 @@ public function inputFilterProvider(): array * 2: int * }> */ - public function countVsDataProvider(): array + public static function countVsDataProvider(): array { $data0 = []; $data1 = [['A' => 'a']]; @@ -356,7 +351,7 @@ public function countVsDataProvider(): array } /** @psalm-return array */ - public function isRequiredProvider(): array + public static function isRequiredProvider(): array { return [ 'enabled' => [true], @@ -446,7 +441,7 @@ public function testGetUnknownFieldIsUnknown(): void } /** @psalm-return array */ - public function invalidCollections(): array + public static function invalidCollections(): array { return [ 'null' => [[['this' => 'is valid'], null]], @@ -461,9 +456,7 @@ public function invalidCollections(): array ]; } - /** - * @dataProvider invalidCollections - */ + #[DataProvider('invalidCollections')] public function testSettingDataAsArrayWithInvalidCollectionsRaisesException(array $data): void { $collectionInputFilter = $this->inputFilter; @@ -473,9 +466,7 @@ public function testSettingDataAsArrayWithInvalidCollectionsRaisesException(arra $collectionInputFilter->setData($data); } - /** - * @dataProvider invalidCollections - */ + #[DataProvider('invalidCollections')] public function testSettingDataAsTraversableWithInvalidCollectionsRaisesException(array $data): void { $collectionInputFilter = $this->inputFilter; @@ -487,7 +478,7 @@ public function testSettingDataAsTraversableWithInvalidCollectionsRaisesExceptio } /** @psalm-return array */ - public function invalidDataType(): array + public static function invalidDataType(): array { return [ 'null' => [null], @@ -502,9 +493,7 @@ public function invalidDataType(): array ]; } - /** - * @dataProvider invalidDataType - */ + #[DataProvider('invalidDataType')] public function testSettingDataWithNonArrayNonTraversableRaisesException(mixed $data): void { $collectionInputFilter = $this->inputFilter; @@ -817,9 +806,7 @@ public static function contextProvider(): array ]; } - /** - * @dataProvider contextProvider - */ + #[DataProvider('contextProvider')] public function testValidationContext(array $data, ?array $customContext, ?array $expectedContext): void { $baseInputFilter = $this->createMock(BaseInputFilter::class); diff --git a/test/FactoryTest.php b/test/FactoryTest.php index c69ad654..d6d2dfde 100644 --- a/test/FactoryTest.php +++ b/test/FactoryTest.php @@ -19,15 +19,15 @@ use Laminas\ServiceManager; use Laminas\Validator; use LaminasTest\InputFilter\TestAsset\CustomInput; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use function sprintf; -/** - * @covers \Laminas\InputFilter\Factory - */ +#[CoversClass(Factory::class)] class FactoryTest extends TestCase { public function testCreateInputWithInvalidDataTypeThrowsInvalidArgumentException(): void @@ -184,7 +184,7 @@ public function testCreateInputWithValidatorsAsAnSpecificationWithMissingNameThr } /** @psalm-return array */ - public function inputTypeSpecificationProvider(): array + public static function inputTypeSpecificationProvider(): array { return [ // Description => [$specificationKey] @@ -194,9 +194,9 @@ public function inputTypeSpecificationProvider(): array } /** - * @dataProvider inputTypeSpecificationProvider * @psalm-param 'continue_if_empty'|'fallback_value' $specificationKey */ + #[DataProvider('inputTypeSpecificationProvider')] public function testCreateInputWithSpecificInputTypeSettingsThrowException(string $specificationKey): void { $factory = $this->createDefaultFactory(); @@ -851,9 +851,6 @@ public function testSetInputFilterManagerOnConstruct(): void self::assertSame($inputFilterManager, $factory->getInputFilterManager()); } - /** - * @covers \Laminas\InputFilter\Factory::createInput - */ public function testSetsBreakChainOnFailure(): void { $factory = $this->createDefaultFactory(); diff --git a/test/FileInput/HttpServerFileInputDecoratorTest.php b/test/FileInput/HttpServerFileInputDecoratorTest.php index 870d539a..348013c1 100644 --- a/test/FileInput/HttpServerFileInputDecoratorTest.php +++ b/test/FileInput/HttpServerFileInputDecoratorTest.php @@ -8,6 +8,7 @@ use Laminas\InputFilter\FileInput\HttpServerFileInputDecorator; use Laminas\Validator; use LaminasTest\InputFilter\InputTest; +use PHPUnit\Framework\Attributes\CoversClass; use Webmozart\Assert\Assert; use function json_encode; @@ -16,10 +17,8 @@ use const UPLOAD_ERR_NO_FILE; use const UPLOAD_ERR_OK; -/** - * @covers \Laminas\InputFilter\FileInput\HttpServerFileInputDecorator - * @covers \Laminas\InputFilter\FileInput - */ +#[CoversClass(HttpServerFileInputDecorator::class)] +#[CoversClass(FileInput::class)] class HttpServerFileInputDecoratorTest extends InputTest { /** @var HttpServerFileInputDecorator */ @@ -332,7 +331,7 @@ public function testFileInputMerge(): void ); } - public function isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(): iterable + public static function isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(): iterable { $dataSets = parent::isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(); Assert::isArrayAccessible($dataSets); @@ -345,7 +344,7 @@ public function isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(): iter return $dataSets; } - public function emptyValueProvider(): iterable + public static function emptyValueProvider(): iterable { return [ 'tmp_name' => [ @@ -383,7 +382,7 @@ public function emptyValueProvider(): iterable ]; } - public function mixedValueProvider(): array + public static function mixedValueProvider(): array { $fooUploadErrOk = [ 'tmp_name' => 'foo', diff --git a/test/FileInput/PsrFileInputDecoratorTest.php b/test/FileInput/PsrFileInputDecoratorTest.php index c3a7a60d..53825717 100644 --- a/test/FileInput/PsrFileInputDecoratorTest.php +++ b/test/FileInput/PsrFileInputDecoratorTest.php @@ -9,6 +9,8 @@ use Laminas\InputFilter\FileInput\PsrFileInputDecorator; use Laminas\Validator; use LaminasTest\InputFilter\InputTest; +use LaminasTest\InputFilter\TestAsset\UploadedFileInterfaceStub; +use PHPUnit\Framework\Attributes\CoversClass; use Psr\Http\Message\UploadedFileInterface; use function in_array; @@ -19,10 +21,8 @@ use const UPLOAD_ERR_NO_FILE; use const UPLOAD_ERR_OK; -/** - * @covers \Laminas\InputFilter\FileInput\PsrFileInputDecorator - * @covers \Laminas\InputFilter\FileInput - */ +#[CoversClass(PsrFileInputDecorator::class)] +#[CoversClass(FileInput::class)] class PsrFileInputDecoratorTest extends InputTest { /** @var PsrFileInputDecorator */ @@ -308,8 +308,7 @@ public function testPsrFileInputMerge(): void $return = $target->merge($source); self::assertSame($target, $return, 'merge() must return it self'); - self::assertEquals( - true, + self::assertTrue( $target->getAutoPrependUploadValidator(), 'getAutoPrependUploadValidator() value not match' ); @@ -326,7 +325,7 @@ public function testPsrFileInputMerge(): void * 6: string[] * }> */ - public function isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(): iterable + public static function isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(): iterable { $generator = parent::isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(); if ($generator instanceof Generator) { @@ -354,14 +353,10 @@ public function isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(): iter * filtered: UploadedFileInterface * }> */ - public function emptyValueProvider(): iterable + public static function emptyValueProvider(): iterable { foreach (['single', 'multi'] as $type) { - $raw = $this->createMock(UploadedFileInterface::class); - $raw->expects(self::atLeast(1)) - ->method('getError') - ->willReturn(UPLOAD_ERR_NO_FILE); - + $raw = new UploadedFileInterfaceStub(UPLOAD_ERR_NO_FILE); yield $type => [ 'raw' => $type === 'multi' ? [$raw] @@ -377,10 +372,9 @@ public function emptyValueProvider(): iterable * filtered: UploadedFileInterface * }> */ - public function mixedValueProvider(): array + public static function mixedValueProvider(): array { - $fooUploadErrOk = $this->createMock(UploadedFileInterface::class); - $fooUploadErrOk->method('getError')->willReturn(UPLOAD_ERR_OK); + $fooUploadErrOk = new UploadedFileInterfaceStub(UPLOAD_ERR_OK); return [ 'single' => [ diff --git a/test/InputFilterAbstractServiceFactoryTest.php b/test/InputFilterAbstractServiceFactoryTest.php index 1275bf96..8924ddb6 100644 --- a/test/InputFilterAbstractServiceFactoryTest.php +++ b/test/InputFilterAbstractServiceFactoryTest.php @@ -19,13 +19,13 @@ use Laminas\Validator\ValidatorInterface; use Laminas\Validator\ValidatorPluginManager; use LaminasTest\InputFilter\TestAsset\Foo; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Depends; use PHPUnit\Framework\TestCase; use function call_user_func_array; -/** - * @covers \Laminas\InputFilter\InputFilterAbstractServiceFactory - */ +#[CoversClass(InputFilterAbstractServiceFactory::class)] class InputFilterAbstractServiceFactoryTest extends TestCase { private ServiceManager $services; @@ -92,9 +92,7 @@ public function testCreatesInputFilterInstance(): void self::assertInstanceOf(InputFilterInterface::class, $filter); } - /** - * @depends testCreatesInputFilterInstance - */ + #[Depends('testCreatesInputFilterInstance')] public function testUsesConfiguredValidationAndFilterManagerServicesWhenCreatingInputFilter(): void { $filters = new FilterPluginManager($this->services); @@ -185,9 +183,7 @@ public function testRetrieveInputFilterFromInputFilterPluginManager(): void self::assertInstanceOf(InputFilterInterface::class, $inputFilter); } - /** - * @depends testCreatesInputFilterInstance - */ + #[Depends('testCreatesInputFilterInstance')] public function testInjectsInputFilterManagerFromServiceManager(): void { $this->services->setService('config', [ diff --git a/test/InputFilterAwareTraitTest.php b/test/InputFilterAwareTraitTest.php index f078d6da..961680d7 100644 --- a/test/InputFilterAwareTraitTest.php +++ b/test/InputFilterAwareTraitTest.php @@ -6,18 +6,17 @@ use Laminas\InputFilter\InputFilter; use Laminas\InputFilter\InputFilterAwareTrait; +use LaminasTest\InputFilter\TestAsset\InputFilterAware; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use ReflectionObject; -/** - * @requires PHP 5.4 - * @covers \Laminas\InputFilter\InputFilterAwareTrait - */ +#[CoversClass(InputFilterAwareTrait::class)] class InputFilterAwareTraitTest extends TestCase { public function testSetInputFilter(): void { - $object = $this->getObjectForTrait(InputFilterAwareTrait::class); + $object = new InputFilterAware(); $r = new ReflectionObject($object); $p = $r->getProperty('inputFilter'); @@ -32,7 +31,7 @@ public function testSetInputFilter(): void public function testGetInputFilter(): void { - $object = $this->getObjectForTrait(InputFilterAwareTrait::class); + $object = new InputFilterAware(); $this->assertNull($object->getInputFilter()); diff --git a/test/InputFilterPluginManagerFactoryTest.php b/test/InputFilterPluginManagerFactoryTest.php index 7e1221b1..978a3fcc 100644 --- a/test/InputFilterPluginManagerFactoryTest.php +++ b/test/InputFilterPluginManagerFactoryTest.php @@ -9,6 +9,8 @@ use Laminas\InputFilter\InputFilterPluginManagerFactory; use Laminas\InputFilter\InputInterface; use Laminas\ServiceManager\ServiceLocatorInterface; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Depends; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use ReflectionObject; @@ -29,7 +31,7 @@ public function testFactoryReturnsPluginManager(): void } /** @psalm-return array */ - public function pluginProvider(): array + public static function pluginProvider(): array { return [ 'input' => [InputInterface::class], @@ -38,10 +40,10 @@ public function pluginProvider(): array } /** - * @depends testFactoryReturnsPluginManager - * @dataProvider pluginProvider * @psalm-param class-string $pluginType */ + #[DataProvider('pluginProvider')] + #[Depends('testFactoryReturnsPluginManager')] public function testFactoryConfiguresPluginManagerUnderContainerInterop(string $pluginType): void { $container = $this->createMock(ContainerInterface::class); diff --git a/test/InputFilterPluginManagerTest.php b/test/InputFilterPluginManagerTest.php index ee7cf1c2..179a1f45 100644 --- a/test/InputFilterPluginManagerTest.php +++ b/test/InputFilterPluginManagerTest.php @@ -14,21 +14,22 @@ use Laminas\InputFilter\InputInterface; use Laminas\ServiceManager\AbstractPluginManager; use Laminas\ServiceManager\Exception\InvalidServiceException; -use Laminas\ServiceManager\ServiceLocatorInterface; use Laminas\ServiceManager\ServiceManager; use Laminas\Validator\ValidatorChain; use Laminas\Validator\ValidatorPluginManager; use LaminasTest\InputFilter\FileInput\TestAsset\InitializableInputFilterInterface; -use PHPUnit\Framework\MockObject\MockObject; +use LaminasTest\InputFilter\TestAsset\InputFilterInterfaceStub; +use LaminasTest\InputFilter\TestAsset\InputInterfaceStub; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use ReflectionObject; +use stdClass; use Throwable; use function method_exists; -/** - * @covers \Laminas\InputFilter\InputFilterPluginManager - */ +#[CoversClass(InputFilterPluginManager::class)] class InputFilterPluginManagerTest extends TestCase { private InputFilterPluginManager $manager; @@ -64,13 +65,13 @@ public function testRegisteringInvalidElementRaisesException(): void public function testLoadingInvalidElementRaisesException(): void { - $this->manager->setInvokableClass('test', self::class); + $this->manager->setInvokableClass('test', stdClass::class); $this->expectException($this->getServiceNotFoundException()); $this->manager->get('test'); } /** @psalm-return array}> */ - public function defaultInvokableClassesProvider(): array + public static function defaultInvokableClassesProvider(): array { return [ // Description => [$alias, $expectedInstance] @@ -80,9 +81,9 @@ public function defaultInvokableClassesProvider(): array } /** - * @dataProvider defaultInvokableClassesProvider * @psalm-param class-string $expectedInstance */ + #[DataProvider('defaultInvokableClassesProvider')] public function testDefaultInvokableClasses(string $alias, string $expectedInstance): void { /** @var object $service */ @@ -146,10 +147,10 @@ public function testInputFilterInvokableClassSMDependenciesArePopulatedWithServi * 2: class-string * }> */ - public function serviceProvider(): array + public static function serviceProvider(): array { - $inputFilterInterfaceMock = $this->createInputFilterInterfaceMock(); - $inputInterfaceMock = $this->createInputInterfaceMock(); + $inputFilterInterfaceMock = new InputFilterInterfaceStub(); + $inputInterfaceMock = new InputInterfaceStub('foo', true); // phpcs:disable Generic.Files.LineLength.TooLong return [ @@ -160,11 +161,8 @@ public function serviceProvider(): array // phpcs:enable } - /** - * @dataProvider serviceProvider - * @param InputInterface|InputFilterInterface $service - */ - public function testGet(string $serviceName, object $service): void + #[DataProvider('serviceProvider')] + public function testGet(string $serviceName, InputInterface|InputFilterInterface $service): void { $this->manager->setService($serviceName, $service); @@ -188,28 +186,6 @@ public function testPopulateFactoryCanAcceptInputFilterAsFirstArgumentAndWillUse self::assertSame($this->manager, $inputFilter->getFactory()->getInputFilterManager()); } - /** - * @return MockObject&InputFilterInterface - */ - protected function createInputFilterInterfaceMock() - { - /** @var InputFilterInterface&MockObject $inputFilter */ - $inputFilter = $this->createMock(InputFilterInterface::class); - - return $inputFilter; - } - - /** - * @return MockObject&InputInterface - */ - protected function createInputInterfaceMock() - { - /** @var InputInterface&MockObject $input */ - $input = $this->createMock(InputInterface::class); - - return $input; - } - /** @return class-string */ protected function getServiceNotFoundException(): string { diff --git a/test/InputFilterTest.php b/test/InputFilterTest.php index 39470486..b66fbc6b 100644 --- a/test/InputFilterTest.php +++ b/test/InputFilterTest.php @@ -8,14 +8,13 @@ use Laminas\InputFilter\Factory; use Laminas\InputFilter\Input; use Laminas\InputFilter\InputFilter; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\MockObject\MockObject; use Traversable; use function array_merge; -/** - * @covers \Laminas\InputFilter\InputFilter - */ +#[CoversClass(InputFilter::class)] class InputFilterTest extends BaseInputFilterTest { /** @var InputFilter */ @@ -46,7 +45,7 @@ public function testCanComposeAFactory(): void * 2: Input * }> */ - public function inputProvider(): array + public static function inputProvider(): array { $dataSets = parent::inputProvider(); diff --git a/test/InputTest.php b/test/InputTest.php index cecdce67..d8973e8d 100644 --- a/test/InputTest.php +++ b/test/InputTest.php @@ -11,6 +11,9 @@ use Laminas\Validator\Translator\TranslatorInterface; use Laminas\Validator\ValidatorChain; use Laminas\Validator\ValidatorInterface; +use LaminasTest\InputFilter\TestAsset\ValidatorStub; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use stdClass; @@ -136,9 +139,9 @@ public function testContinueIfEmptyFlagIsMutable(): void } /** - * @dataProvider setValueProvider * @param mixed $fallbackValue */ + #[DataProvider('setValueProvider')] public function testSetFallbackValue($fallbackValue): void { $input = $this->input; @@ -151,9 +154,9 @@ public function testSetFallbackValue($fallbackValue): void } /** - * @dataProvider setValueProvider * @param mixed $fallbackValue */ + #[DataProvider('setValueProvider')] public function testClearFallbackValue($fallbackValue): void { $input = $this->input; @@ -164,11 +167,11 @@ public function testClearFallbackValue($fallbackValue): void } /** - * @dataProvider fallbackValueVsIsValidProvider * @param string|string[] $fallbackValue * @param string|string[] $originalValue * @param string|string[] $expectedValue */ + #[DataProvider('fallbackValueVsIsValidProvider')] public function testFallbackValueVsIsValidRules( bool $required, $fallbackValue, @@ -195,9 +198,9 @@ public function testFallbackValueVsIsValidRules( } /** - * @dataProvider fallbackValueVsIsValidProvider * @param string|string[] $fallbackValue */ + #[DataProvider('fallbackValueVsIsValidProvider')] public function testFallbackValueVsIsValidRulesWhenValueNotSet(bool $required, $fallbackValue): void { $expectedValue = $fallbackValue; // Should always return the fallback value @@ -306,7 +309,7 @@ public function testNotRequiredWithoutFallbackAndValueNotSetThenIsValid(): void // Validator should not to be called $input->getValidatorChain() - ->attach($this->createValidatorMock(null, null)); + ->attach(self::createValidatorMock(null, null)); self::assertTrue( $input->isValid(), 'isValid() should be return always true when is not required, and no data is set. Detail: ' @@ -316,9 +319,9 @@ public function testNotRequiredWithoutFallbackAndValueNotSetThenIsValid(): void } /** - * @dataProvider emptyValueProvider * @param mixed $value */ + #[DataProvider('emptyValueProvider')] public function testNotEmptyValidatorNotInjectedIfContinueIfEmptyIsTrue($value): void { $input = $this->input; @@ -400,9 +403,9 @@ public function testBreakOnFailureFlagIsMutable(): void } /** - * @dataProvider emptyValueProvider * @param mixed $value */ + #[DataProvider('emptyValueProvider')] public function testNotEmptyValidatorAddedWhenIsValidIsCalled($value): void { self::assertTrue($this->input->isRequired()); @@ -421,9 +424,9 @@ public function testNotEmptyValidatorAddedWhenIsValidIsCalled($value): void } /** - * @dataProvider emptyValueProvider * @param mixed $value */ + #[DataProvider('emptyValueProvider')] public function testRequiredNotEmptyValidatorNotAddedWhenOneExists($value): void { $this->input->setRequired(true); @@ -441,10 +444,10 @@ public function testRequiredNotEmptyValidatorNotAddedWhenOneExists($value): void } /** - * @dataProvider emptyValueProvider * @param mixed $valueRaw * @param mixed $valueFiltered */ + #[DataProvider('emptyValueProvider')] public function testDoNotInjectNotEmptyValidatorIfAnywhereInChain($valueRaw, $valueFiltered): void { $filterChain = $this->createFilterChainMock([[$valueRaw, $valueFiltered]]); @@ -456,7 +459,7 @@ public function testDoNotInjectNotEmptyValidatorIfAnywhereInChain($valueRaw, $va $notEmptyMock = $this->createNonEmptyValidatorMock(false, $valueFiltered); - $validatorChain->attach($this->createValidatorMock(true)); + $validatorChain->attach(self::createValidatorMock(true)); $validatorChain->attach($notEmptyMock); self::assertFalse($this->input->isValid()); @@ -466,17 +469,14 @@ public function testDoNotInjectNotEmptyValidatorIfAnywhereInChain($valueRaw, $va self::assertEquals($notEmptyMock, $validators[1]['instance']); } - /** - * @group 7448 - * @dataProvider isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider - * @param mixed $value - */ + #[DataProvider('isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider')] + #[Group('7448')] public function testIsRequiredVsAllowEmptyVsContinueIfEmptyVsIsValid( bool $required, bool $allowEmpty, bool $continueIfEmpty, ValidatorInterface $validator, - $value, + mixed $value, bool $expectedIsValid, array $expectedMessages ): void { @@ -498,9 +498,9 @@ public function testIsRequiredVsAllowEmptyVsContinueIfEmptyVsIsValid( } /** - * @dataProvider setValueProvider * @param mixed $value */ + #[DataProvider('setValueProvider')] public function testSetValuePutInputInTheDesiredState($value): void { $input = $this->input; @@ -511,9 +511,9 @@ public function testSetValuePutInputInTheDesiredState($value): void } /** - * @dataProvider setValueProvider * @param mixed $value */ + #[DataProvider('setValueProvider')] public function testResetValueReturnsInputValueToDefaultValue($value): void { $input = $this->input; @@ -660,7 +660,7 @@ public function testNotEmptyMessageIsTranslated(): void * 4: string * }> */ - public function fallbackValueVsIsValidProvider(): array + public static function fallbackValueVsIsValidProvider(): array { $required = true; $isValid = true; @@ -685,10 +685,10 @@ public function fallbackValueVsIsValidProvider(): array * filtered: bool|int|float|string|list|object * }> */ - public function setValueProvider(): array + public static function setValueProvider(): array { - $emptyValues = $this->emptyValueProvider(); - $mixedValues = $this->mixedValueProvider(); + $emptyValues = static::emptyValueProvider(); + $mixedValues = static::mixedValueProvider(); $emptyValues = $emptyValues instanceof Iterator ? iterator_to_array($emptyValues) : $emptyValues; $mixedValues = $mixedValues instanceof Iterator ? iterator_to_array($mixedValues) : $mixedValues; @@ -710,11 +710,11 @@ public function setValueProvider(): array * 6: string[] * }> */ - public function isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(): iterable + public static function isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(): iterable { - $allValues = $this->setValueProvider(); + $allValues = static::setValueProvider(); - $emptyValues = $this->emptyValueProvider(); + $emptyValues = static::emptyValueProvider(); $emptyValues = $emptyValues instanceof Iterator ? iterator_to_array($emptyValues) : $emptyValues; Assert::isArray($emptyValues); @@ -729,12 +729,12 @@ public function isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(): iter $notEmptyMsg = ['isEmpty' => "Value is required and can't be empty"]; // phpcs:disable Generic.Formatting.MultipleStatementAlignment.NotSame - $validatorNotCall = fn($value, $context = null): ValidatorInterface => - $this->createValidatorMock(null, $value, $context); - $validatorInvalid = fn($value, $context = null): ValidatorInterface => - $this->createValidatorMock(false, $value, $context, $validatorMsg); - $validatorValid = fn($value, $context = null): ValidatorInterface => - $this->createValidatorMock(true, $value, $context); + $validatorNotCall = fn(mixed $value, array|null $context = null): ValidatorInterface => + self::createValidatorMock(null, $value, $context); + $validatorInvalid = fn(mixed $value, array|null $context = null): ValidatorInterface => + self::createValidatorMock(false, $value, $context, $validatorMsg); + $validatorValid = fn(mixed $value, array|null $context = null): ValidatorInterface => + self::createValidatorMock(true, $value, $context); // phpcs:disable Generic.Files.LineLength.TooLong,WebimpressCodingStandard.Arrays.DoubleArrow.SpacesBefore,WebimpressCodingStandard.Arrays.Format.SingleLineSpaceBefore,WebimpressCodingStandard.WhiteSpace.CommaSpacing.SpacingAfterComma,WebimpressCodingStandard.WhiteSpace.CommaSpacing.SpaceBeforeComma,WebimpressCodingStandard.Arrays.Format.BlankLine,Generic.Formatting.MultipleStatementAlignment.NotSame $dataTemplates = [ @@ -791,7 +791,7 @@ public function isRequiredVsAllowEmptyVsContinueIfEmptyVsIsValidProvider(): iter * filtered: null|string|array * }> */ - public function emptyValueProvider(): iterable + public static function emptyValueProvider(): iterable { return [ // Description => [$value] @@ -822,7 +822,7 @@ public function emptyValueProvider(): iterable * filtered: mixed, * }> */ - public function mixedValueProvider(): array + public static function mixedValueProvider(): array { return [ // Description => [$value] @@ -877,15 +877,9 @@ public function mixedValueProvider(): array ]; } - /** - * @return InputInterface&MockObject - */ - protected function createInputInterfaceMock() + protected function createInputInterfaceMock(): InputInterface&MockObject { - /** @var InputInterface&MockObject $source */ - $source = $this->createMock(InputInterface::class); - - return $source; + return $this->createMock(InputInterface::class); } /** @@ -928,53 +922,31 @@ protected function createValidatorChainMock(array $valueMap = [], $messages = [] return $validatorChain; } - /** - * @param null|bool $isValid - * @param mixed $value - * @param mixed $context - * @param string[] $messages - * @return ValidatorInterface&MockObject - */ - protected function createValidatorMock($isValid, $value = 'not-set', $context = null, $messages = []) - { - /** @var ValidatorInterface&MockObject $validator */ - $validator = $this->createMock(ValidatorInterface::class); - - if (($isValid === false) || ($isValid === true)) { - $isValidMethod = $validator->expects(self::once()) - ->method('isValid') - ->willReturn($isValid); - } else { - $isValidMethod = $validator->expects(self::never()) - ->method('isValid'); - } - if ($value !== 'not-set') { - $isValidMethod->with($value, $context); - } - - $validator->method('getMessages') - ->willReturn($messages); - - return $validator; + /** @param array $messages */ + protected static function createValidatorMock( + bool|null $isValid, + mixed $value = 'not-set', + array|null $context = null, + array $messages = [] + ): ValidatorInterface { + return new ValidatorStub($isValid, $value, $context, $messages); } - /** - * @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->getMockBuilder(NotEmptyValidator::class) - ->setMethods(['isValid']) - ->getMock(); - $notEmptyMock->expects($this->once()) + protected function createNonEmptyValidatorMock( + bool $isValid, + mixed $value, + mixed $context = null + ): NotEmptyValidator&MockObject { + $notEmptyMock = $this->createMock(NotEmptyValidator::class); + $notEmptyMock->expects(self::once()) ->method('isValid') ->with($value, $context) ->willReturn($isValid); + if ($isValid === false) { + $notEmptyMock->method('getMessages')->willReturn([]); + } + return $notEmptyMock; } diff --git a/test/OptionalInputFilterTest.php b/test/OptionalInputFilterTest.php index 16d3d2c3..269fc906 100644 --- a/test/OptionalInputFilterTest.php +++ b/test/OptionalInputFilterTest.php @@ -10,11 +10,10 @@ use Laminas\InputFilter\InputFilter; use Laminas\InputFilter\InputFilterInterface; use Laminas\InputFilter\OptionalInputFilter; +use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -/** - * @covers \Laminas\InputFilter\OptionalInputFilter - */ +#[CoversClass(OptionalInputFilter::class)] class OptionalInputFilterTest extends TestCase { public function testValidatesSuccessfullyWhenSetDataIsNeverCalled(): void diff --git a/test/TestAsset/InputFilterAware.php b/test/TestAsset/InputFilterAware.php new file mode 100644 index 00000000..9b232b9c --- /dev/null +++ b/test/TestAsset/InputFilterAware.php @@ -0,0 +1,12 @@ + $getRawValues + * @param array $getValues + * @param array> $getMessages + */ + public function __construct( + private readonly bool|null $isValid = null, + private readonly array $getRawValues = [], + private readonly array $getValues = [], + private readonly array $getMessages = [] + ) { + } + + /** @inheritDoc */ + public function isValid($context = null) + { + assertNotNull($this->isValid, 'isValid was not expected to be called'); + + return $this->isValid; + } + + public function getValues(): array + { + return $this->getValues; + } + + public function getRawValues(): array + { + return $this->getRawValues; + } + + /** @inheritDoc */ + public function getMessages(): array + { + return $this->getMessages; + } +} diff --git a/test/TestAsset/InputInterfaceStub.php b/test/TestAsset/InputInterfaceStub.php new file mode 100644 index 00000000..fc1de177 --- /dev/null +++ b/test/TestAsset/InputInterfaceStub.php @@ -0,0 +1,159 @@ + $getMessages */ + public function __construct( + private readonly string $name, + private readonly bool|null $isRequired, + private readonly bool|null $isValid = null, + private readonly array|string|null $context = null, + private readonly mixed $getRawValue = null, + private readonly mixed $getValue = null, + private readonly array $getMessages = [], + private readonly bool $breakOnFailure = false + ) { + } + + /** @inheritDoc */ + public function setAllowEmpty($allowEmpty) + { + return $this; + } + + /** @inheritDoc */ + public function setBreakOnFailure($breakOnFailure) + { + return $this; + } + + /** @inheritDoc */ + public function setErrorMessage($errorMessage) + { + return $this; + } + + /** @inheritDoc */ + public function setFilterChain(FilterChain $filterChain): never + { + throw new Exception('Not implemented'); + } + + /** @inheritDoc */ + public function setName($name): never + { + throw new Exception('Not implemented'); + } + + /** @inheritDoc */ + public function setRequired($required): never + { + throw new Exception('Not implemented'); + } + + /** @inheritDoc */ + public function setValidatorChain(ValidatorChain $validatorChain): never + { + throw new Exception('Not implemented'); + } + + /** @inheritDoc */ + public function setValue($value) + { + return $this; + } + + /** @inheritDoc */ + public function merge(InputInterface $input): never + { + throw new Exception('Not implemented'); + } + + /** @inheritDoc */ + public function allowEmpty(): never + { + throw new Exception('Not implemented'); + } + + /** @inheritDoc */ + public function breakOnFailure(): bool + { + return $this->breakOnFailure; + } + + /** @inheritDoc */ + public function getErrorMessage(): never + { + throw new Exception('Not implemented'); + } + + /** @inheritDoc */ + public function getFilterChain(): never + { + throw new Exception('Not implemented'); + } + + /** @inheritDoc */ + public function getName(): string + { + return $this->name; + } + + /** @inheritDoc */ + public function getRawValue(): mixed + { + return $this->getRawValue; + } + + /** @inheritDoc */ + public function isRequired(): bool + { + assertNotNull($this->isRequired, 'isRequired was not expected to be called'); + + return $this->isRequired; + } + + /** @inheritDoc */ + public function getValidatorChain(): never + { + throw new Exception('Not implemented'); + } + + /** @inheritDoc */ + public function getValue(): mixed + { + return $this->getValue; + } + + /** @inheritDoc */ + public function isValid(): bool + { + assertNotNull($this->isValid, 'isValid was not expected to be called'); + + if ($this->context !== null && func_num_args() > 0) { + assertEquals($this->context, func_get_arg(0), 'The given context does not match the expected context'); + } + + return $this->isValid; + } + + /** @return array */ + public function getMessages(): array + { + return $this->getMessages; + } +} diff --git a/test/TestAsset/UploadedFileInterfaceStub.php b/test/TestAsset/UploadedFileInterfaceStub.php new file mode 100644 index 00000000..b6a806df --- /dev/null +++ b/test/TestAsset/UploadedFileInterfaceStub.php @@ -0,0 +1,48 @@ +expectedErrorCode; + } + + public function getClientFilename(): never + { + throw new Exception('Not Implemented'); + } + + public function getClientMediaType(): never + { + throw new Exception('Not Implemented'); + } +} diff --git a/test/TestAsset/ValidatorStub.php b/test/TestAsset/ValidatorStub.php new file mode 100644 index 00000000..c415b170 --- /dev/null +++ b/test/TestAsset/ValidatorStub.php @@ -0,0 +1,51 @@ + $messages */ + public function __construct( + private readonly bool|null $isValid, + private readonly mixed $value = 'not-set', + private readonly array|null $context = null, + private readonly array $messages = [], + ) { + } + + public function isValid(mixed $value): bool + { + if ($this->value !== 'not-set') { + assertEquals($this->value, $value, 'isValid did not receive the expected value'); + } + + if (func_num_args() > 1 && $this->context !== null) { + /** @var mixed $givenContext */ + $givenContext = func_get_arg(1); + assertEquals( + $this->context, + $givenContext, + 'isValid received a context that did not match the expected context', + ); + } + + assertNotNull($this->isValid, 'isValid was not expected to be called for this instance'); + + return $this->isValid; + } + + /** @inheritDoc */ + public function getMessages(): array + { + return $this->messages; + } +} diff --git a/test/ValidationGroup/InputFilterCollectionsValidationGroupTest.php b/test/ValidationGroup/InputFilterCollectionsValidationGroupTest.php index 19e61793..cb110b55 100644 --- a/test/ValidationGroup/InputFilterCollectionsValidationGroupTest.php +++ b/test/ValidationGroup/InputFilterCollectionsValidationGroupTest.php @@ -8,6 +8,7 @@ use Laminas\InputFilter\Exception\RuntimeException; use Laminas\InputFilter\Input; use Laminas\InputFilter\InputFilter; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use function restore_error_handler; @@ -39,7 +40,7 @@ protected function setUp(): void } /** @return array */ - public function collectionCountProvider(): array + public static function collectionCountProvider(): array { return [ 'Collection Count: None' => [null], @@ -61,7 +62,7 @@ private function setCollectionCount(?int $count): void $collection->setCount($count); } - /** @dataProvider collectionCountProvider */ + #[DataProvider('collectionCountProvider')] public function testIncompleteDataFailsValidation(?int $count): void { $this->setCollectionCount($count); @@ -73,7 +74,7 @@ public function testIncompleteDataFailsValidation(?int $count): void self::assertFalse($this->inputFilter->isValid()); } - /** @dataProvider collectionCountProvider */ + #[DataProvider('collectionCountProvider')] public function testCompleteDataPassesValidation(?int $count): void { $this->setCollectionCount($count); @@ -89,7 +90,7 @@ public function testCompleteDataPassesValidation(?int $count): void self::assertTrue($this->inputFilter->isValid()); } - /** @dataProvider collectionCountProvider */ + #[DataProvider('collectionCountProvider')] public function testValidationFailsForCollectionItemValidity(?int $count): void { $this->setCollectionCount($count); @@ -105,7 +106,7 @@ public function testValidationFailsForCollectionItemValidity(?int $count): void self::assertFalse($this->inputFilter->isValid()); } - /** @dataProvider collectionCountProvider */ + #[DataProvider('collectionCountProvider')] public function testValidationGroupWithCollectionInputFilter(?int $count): void { $this->setCollectionCount($count); @@ -125,7 +126,7 @@ public function testValidationGroupWithCollectionInputFilter(?int $count): void self::assertTrue($this->inputFilter->isValid()); } - /** @dataProvider collectionCountProvider */ + #[DataProvider('collectionCountProvider')] public function testValidationGroupViaCollection(?int $count): void { $this->setCollectionCount($count); @@ -153,9 +154,8 @@ public function testValidationGroupViaCollection(?int $count): void /** * This test documents existing behaviour - the validation group must be set for elements 0 through 3 - * - * @dataProvider collectionCountProvider */ + #[DataProvider('collectionCountProvider')] public function testValidationGroupViaCollectionMustSpecifyAllKeys(?int $count): void { $this->setCollectionCount($count); @@ -190,7 +190,7 @@ public function testValidationGroupViaCollectionMustSpecifyAllKeys(?int $count): } } - /** @dataProvider collectionCountProvider */ + #[DataProvider('collectionCountProvider')] public function testValidationGroupViaTopLevelInputFilter(?int $count): void { $this->setCollectionCount($count);