From d6ce9de50c69731a81c565c74c1c0ea989de4589 Mon Sep 17 00:00:00 2001 From: Laviron Xavier Date: Thu, 3 Nov 2022 17:11:40 +0100 Subject: [PATCH 1/2] feat: use openapi array to validate filter parameters The filter validators were only using the 'swagger' entry from the filter description. It should also use the 'openapi' entry, as swagger is deprecated. --- .../Validator/ArrayItems.php | 12 ++++--- .../Validator/Bounds.php | 12 ++++--- .../CheckFilterDeprecationsTrait.php | 31 +++++++++++++++++++ .../Validator/Enum.php | 6 +++- .../Validator/Length.php | 8 +++-- .../Validator/MultipleOf.php | 6 +++- .../Validator/Pattern.php | 6 +++- .../Validator/Required.php | 6 +++- .../Validator/ArrayItemsTest.php | 2 ++ .../Validator/BoundsTest.php | 2 ++ .../Validator/EnumTest.php | 2 ++ .../Validator/LengthTest.php | 2 ++ .../Validator/MultipleOfTest.php | 2 ++ .../Validator/PatternTest.php | 2 ++ .../Validator/RequiredTest.php | 2 ++ 15 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 src/Api/QueryParameterValidator/Validator/CheckFilterDeprecationsTrait.php diff --git a/src/Api/QueryParameterValidator/Validator/ArrayItems.php b/src/Api/QueryParameterValidator/Validator/ArrayItems.php index d9e15e1c217..8cc5b50c92c 100644 --- a/src/Api/QueryParameterValidator/Validator/ArrayItems.php +++ b/src/Api/QueryParameterValidator/Validator/ArrayItems.php @@ -15,6 +15,8 @@ final class ArrayItems implements ValidatorInterface { + use CheckFilterDeprecationsTrait; + /** * {@inheritdoc} */ @@ -24,9 +26,11 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } - $maxItems = $filterDescription['swagger']['maxItems'] ?? null; - $minItems = $filterDescription['swagger']['minItems'] ?? null; - $uniqueItems = $filterDescription['swagger']['uniqueItems'] ?? false; + $this->checkFilterDeprecations($filterDescription); + + $maxItems = $filterDescription['openapi']['maxItems'] ?? $filterDescription['swagger']['maxItems'] ?? null; + $minItems = $filterDescription['openapi']['minItems'] ?? $filterDescription['swagger']['minItems'] ?? null; + $uniqueItems = $filterDescription['openapi']['uniqueItems'] ?? $filterDescription['swagger']['uniqueItems'] ?? false; $errorList = []; @@ -60,7 +64,7 @@ private function getValue(string $name, array $filterDescription, array $queryPa return $value; } - $collectionFormat = $filterDescription['swagger']['collectionFormat'] ?? 'csv'; + $collectionFormat = $filterDescription['openapi']['collectionFormat'] ?? $filterDescription['swagger']['collectionFormat'] ?? 'csv'; return explode(self::getSeparator($collectionFormat), (string) $value) ?: []; // @phpstan-ignore-line } diff --git a/src/Api/QueryParameterValidator/Validator/Bounds.php b/src/Api/QueryParameterValidator/Validator/Bounds.php index eebc40b3eca..9ebf3285380 100644 --- a/src/Api/QueryParameterValidator/Validator/Bounds.php +++ b/src/Api/QueryParameterValidator/Validator/Bounds.php @@ -15,6 +15,8 @@ final class Bounds implements ValidatorInterface { + use CheckFilterDeprecationsTrait; + /** * {@inheritdoc} */ @@ -25,13 +27,15 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } - $maximum = $filterDescription['swagger']['maximum'] ?? null; - $minimum = $filterDescription['swagger']['minimum'] ?? null; + $this->checkFilterDeprecations($filterDescription); + + $maximum = $filterDescription['openapi']['maximum'] ?? $filterDescription['swagger']['maximum'] ?? null; + $minimum = $filterDescription['openapi']['minimum'] ?? $filterDescription['swagger']['minimum'] ?? null; $errorList = []; if (null !== $maximum) { - if (($filterDescription['swagger']['exclusiveMaximum'] ?? false) && $value >= $maximum) { + if (($filterDescription['openapi']['exclusiveMaximum'] ?? $filterDescription['swagger']['exclusiveMaximum'] ?? false) && $value >= $maximum) { $errorList[] = sprintf('Query parameter "%s" must be less than %s', $name, $maximum); } elseif ($value > $maximum) { $errorList[] = sprintf('Query parameter "%s" must be less than or equal to %s', $name, $maximum); @@ -39,7 +43,7 @@ public function validate(string $name, array $filterDescription, array $queryPar } if (null !== $minimum) { - if (($filterDescription['swagger']['exclusiveMinimum'] ?? false) && $value <= $minimum) { + if (($filterDescription['openapi']['exclusiveMinimum'] ?? $filterDescription['swagger']['exclusiveMinimum'] ?? false) && $value <= $minimum) { $errorList[] = sprintf('Query parameter "%s" must be greater than %s', $name, $minimum); } elseif ($value < $minimum) { $errorList[] = sprintf('Query parameter "%s" must be greater than or equal to %s', $name, $minimum); diff --git a/src/Api/QueryParameterValidator/Validator/CheckFilterDeprecationsTrait.php b/src/Api/QueryParameterValidator/Validator/CheckFilterDeprecationsTrait.php new file mode 100644 index 00000000000..a72f79ed102 --- /dev/null +++ b/src/Api/QueryParameterValidator/Validator/CheckFilterDeprecationsTrait.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Api\QueryParameterValidator\Validator; + +/** + * @internal + */ +trait CheckFilterDeprecationsTrait +{ + protected function checkFilterDeprecations(array $filterDescription): void + { + if (\array_key_exists('swagger', $filterDescription)) { + trigger_deprecation( + 'api-platform/core', + '3.0', + 'Using the "swagger" key in filters description is deprecated, use "openapi" instead.' + ); + } + } +} diff --git a/src/Api/QueryParameterValidator/Validator/Enum.php b/src/Api/QueryParameterValidator/Validator/Enum.php index 2e0bf5c277b..d8f44634039 100644 --- a/src/Api/QueryParameterValidator/Validator/Enum.php +++ b/src/Api/QueryParameterValidator/Validator/Enum.php @@ -15,6 +15,8 @@ final class Enum implements ValidatorInterface { + use CheckFilterDeprecationsTrait; + /** * {@inheritdoc} */ @@ -25,7 +27,9 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } - $enum = $filterDescription['swagger']['enum'] ?? null; + $this->checkFilterDeprecations($filterDescription); + + $enum = $filterDescription['openapi']['enum'] ?? $filterDescription['swagger']['enum'] ?? null; if (null !== $enum && !\in_array($value, $enum, true)) { return [ diff --git a/src/Api/QueryParameterValidator/Validator/Length.php b/src/Api/QueryParameterValidator/Validator/Length.php index 0b0c67e5595..c96f86511c2 100644 --- a/src/Api/QueryParameterValidator/Validator/Length.php +++ b/src/Api/QueryParameterValidator/Validator/Length.php @@ -15,6 +15,8 @@ final class Length implements ValidatorInterface { + use CheckFilterDeprecationsTrait; + /** * {@inheritdoc} */ @@ -25,8 +27,10 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } - $maxLength = $filterDescription['swagger']['maxLength'] ?? null; - $minLength = $filterDescription['swagger']['minLength'] ?? null; + $this->checkFilterDeprecations($filterDescription); + + $maxLength = $filterDescription['openapi']['maxLength'] ?? $filterDescription['swagger']['maxLength'] ?? null; + $minLength = $filterDescription['openapi']['minLength'] ?? $filterDescription['swagger']['minLength'] ?? null; $errorList = []; diff --git a/src/Api/QueryParameterValidator/Validator/MultipleOf.php b/src/Api/QueryParameterValidator/Validator/MultipleOf.php index 6da33972688..5d792a3ba50 100644 --- a/src/Api/QueryParameterValidator/Validator/MultipleOf.php +++ b/src/Api/QueryParameterValidator/Validator/MultipleOf.php @@ -15,6 +15,8 @@ final class MultipleOf implements ValidatorInterface { + use CheckFilterDeprecationsTrait; + /** * {@inheritdoc} */ @@ -25,7 +27,9 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } - $multipleOf = $filterDescription['swagger']['multipleOf'] ?? null; + $this->checkFilterDeprecations($filterDescription); + + $multipleOf = $filterDescription['openapi']['multipleOf'] ?? $filterDescription['swagger']['multipleOf'] ?? null; if (null !== $multipleOf && 0 !== ($value % $multipleOf)) { return [ diff --git a/src/Api/QueryParameterValidator/Validator/Pattern.php b/src/Api/QueryParameterValidator/Validator/Pattern.php index a585fd8b321..8ad2fadbc30 100644 --- a/src/Api/QueryParameterValidator/Validator/Pattern.php +++ b/src/Api/QueryParameterValidator/Validator/Pattern.php @@ -15,6 +15,8 @@ final class Pattern implements ValidatorInterface { + use CheckFilterDeprecationsTrait; + /** * {@inheritdoc} */ @@ -25,7 +27,9 @@ public function validate(string $name, array $filterDescription, array $queryPar return []; } - $pattern = $filterDescription['swagger']['pattern'] ?? null; + $this->checkFilterDeprecations($filterDescription); + + $pattern = $filterDescription['openapi']['pattern'] ?? $filterDescription['swagger']['pattern'] ?? null; if (null !== $pattern && !preg_match($pattern, $value)) { return [ diff --git a/src/Api/QueryParameterValidator/Validator/Required.php b/src/Api/QueryParameterValidator/Validator/Required.php index 0045b0513b4..9b230876f04 100644 --- a/src/Api/QueryParameterValidator/Validator/Required.php +++ b/src/Api/QueryParameterValidator/Validator/Required.php @@ -17,6 +17,8 @@ final class Required implements ValidatorInterface { + use CheckFilterDeprecationsTrait; + /** * {@inheritdoc} */ @@ -34,8 +36,10 @@ public function validate(string $name, array $filterDescription, array $queryPar ]; } + $this->checkFilterDeprecations($filterDescription); + // if query param is empty and the configuration does not allow it - if (!($filterDescription['swagger']['allowEmptyValue'] ?? false) && empty($this->requestGetQueryParameter($queryParameters, $name))) { + if (!($filterDescription['openapi']['allowEmptyValue'] ?? $filterDescription['swagger']['allowEmptyValue'] ?? false) && empty($this->requestGetQueryParameter($queryParameters, $name))) { return [ sprintf('Query parameter "%s" does not allow empty value', $name), ]; diff --git a/tests/Api/QueryParameterValidator/Validator/ArrayItemsTest.php b/tests/Api/QueryParameterValidator/Validator/ArrayItemsTest.php index b3ce00c8b23..dbf8674df18 100644 --- a/tests/Api/QueryParameterValidator/Validator/ArrayItemsTest.php +++ b/tests/Api/QueryParameterValidator/Validator/ArrayItemsTest.php @@ -18,6 +18,8 @@ /** * @author Julien Deniau + * + * @group legacy */ class ArrayItemsTest extends TestCase { diff --git a/tests/Api/QueryParameterValidator/Validator/BoundsTest.php b/tests/Api/QueryParameterValidator/Validator/BoundsTest.php index 5157374d9dc..933f555ca82 100644 --- a/tests/Api/QueryParameterValidator/Validator/BoundsTest.php +++ b/tests/Api/QueryParameterValidator/Validator/BoundsTest.php @@ -18,6 +18,8 @@ /** * @author Julien Deniau + * + * @group legacy */ class BoundsTest extends TestCase { diff --git a/tests/Api/QueryParameterValidator/Validator/EnumTest.php b/tests/Api/QueryParameterValidator/Validator/EnumTest.php index acee9b5dfcf..9d29b039fd7 100644 --- a/tests/Api/QueryParameterValidator/Validator/EnumTest.php +++ b/tests/Api/QueryParameterValidator/Validator/EnumTest.php @@ -18,6 +18,8 @@ /** * @author Julien Deniau + * + * @group legacy */ class EnumTest extends TestCase { diff --git a/tests/Api/QueryParameterValidator/Validator/LengthTest.php b/tests/Api/QueryParameterValidator/Validator/LengthTest.php index 097f0de0cac..d66626c9fcc 100644 --- a/tests/Api/QueryParameterValidator/Validator/LengthTest.php +++ b/tests/Api/QueryParameterValidator/Validator/LengthTest.php @@ -18,6 +18,8 @@ /** * @author Julien Deniau + * + * @group legacy */ class LengthTest extends TestCase { diff --git a/tests/Api/QueryParameterValidator/Validator/MultipleOfTest.php b/tests/Api/QueryParameterValidator/Validator/MultipleOfTest.php index b5d8f11e344..7738c4227ea 100644 --- a/tests/Api/QueryParameterValidator/Validator/MultipleOfTest.php +++ b/tests/Api/QueryParameterValidator/Validator/MultipleOfTest.php @@ -18,6 +18,8 @@ /** * @author Julien Deniau + * + * @group legacy */ class MultipleOfTest extends TestCase { diff --git a/tests/Api/QueryParameterValidator/Validator/PatternTest.php b/tests/Api/QueryParameterValidator/Validator/PatternTest.php index c97ae786c8e..0ffed0bbf57 100644 --- a/tests/Api/QueryParameterValidator/Validator/PatternTest.php +++ b/tests/Api/QueryParameterValidator/Validator/PatternTest.php @@ -18,6 +18,8 @@ /** * @author Julien Deniau + * + * @group legacy */ class PatternTest extends TestCase { diff --git a/tests/Api/QueryParameterValidator/Validator/RequiredTest.php b/tests/Api/QueryParameterValidator/Validator/RequiredTest.php index 753e6cc075a..6e08e1ee437 100644 --- a/tests/Api/QueryParameterValidator/Validator/RequiredTest.php +++ b/tests/Api/QueryParameterValidator/Validator/RequiredTest.php @@ -20,6 +20,8 @@ * Class RequiredTest. * * @author Julien Deniau + * + * @group legacy */ class RequiredTest extends TestCase { From 2dc753698d05898a4d5dec840c4c72e9f0e21ca6 Mon Sep 17 00:00:00 2001 From: Laviron Xavier Date: Mon, 7 Nov 2022 16:07:32 +0100 Subject: [PATCH 2/2] test(filters): test using openapi for query parameters validation --- .../Validator/ArrayItemsTest.php | 175 +++++++++++++++++- .../Validator/BoundsTest.php | 150 ++++++++++++++- .../Validator/EnumTest.php | 39 +++- .../Validator/LengthTest.php | 112 ++++++++++- .../Validator/MultipleOfTest.php | 41 +++- .../Validator/PatternTest.php | 82 +++++++- .../Validator/RequiredTest.php | 52 +++++- 7 files changed, 637 insertions(+), 14 deletions(-) diff --git a/tests/Api/QueryParameterValidator/Validator/ArrayItemsTest.php b/tests/Api/QueryParameterValidator/Validator/ArrayItemsTest.php index dbf8674df18..e5a97b3daba 100644 --- a/tests/Api/QueryParameterValidator/Validator/ArrayItemsTest.php +++ b/tests/Api/QueryParameterValidator/Validator/ArrayItemsTest.php @@ -18,8 +18,6 @@ /** * @author Julien Deniau - * - * @group legacy */ class ArrayItemsTest extends TestCase { @@ -43,6 +41,9 @@ public function testEmptyQueryParameter(): void ); } + /** + * @group legacy + */ public function testNonMatchingParameter(): void { $filter = new ArrayItems(); @@ -67,6 +68,33 @@ public function testNonMatchingParameter(): void ); } + public function testNonMatchingParameterOpenApi(): void + { + $filter = new ArrayItems(); + + $filterDefinition = [ + 'openapi' => [ + 'maxItems' => 3, + 'minItems' => 2, + ], + ]; + + $request = ['some_filter' => ['foo', 'bar', 'bar', 'foo']]; + $this->assertEquals( + ['Query parameter "some_filter" must contain less than 3 values'], + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $request = ['some_filter' => ['foo']]; + $this->assertEquals( + ['Query parameter "some_filter" must contain more than 2 values'], + $filter->validate('some_filter', $filterDefinition, $request) + ); + } + + /** + * @group legacy + */ public function testMatchingParameter(): void { $filter = new ArrayItems(); @@ -89,6 +117,31 @@ public function testMatchingParameter(): void ); } + public function testMatchingParameterOpenApi(): void + { + $filter = new ArrayItems(); + + $filterDefinition = [ + 'openapi' => [ + 'maxItems' => 3, + 'minItems' => 2, + ], + ]; + + $request = ['some_filter' => ['foo', 'bar']]; + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $request = ['some_filter' => ['foo', 'bar', 'baz']]; + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, $request) + ); + } + + /** + * @group legacy + */ public function testNonMatchingUniqueItems(): void { $filter = new ArrayItems(); @@ -106,6 +159,26 @@ public function testNonMatchingUniqueItems(): void ); } + public function testNonMatchingUniqueItemsOpenApi(): void + { + $filter = new ArrayItems(); + + $filterDefinition = [ + 'openapi' => [ + 'uniqueItems' => true, + ], + ]; + + $request = ['some_filter' => ['foo', 'bar', 'bar', 'foo']]; + $this->assertEquals( + ['Query parameter "some_filter" must contain unique values'], + $filter->validate('some_filter', $filterDefinition, $request) + ); + } + + /** + * @group legacy + */ public function testMatchingUniqueItems(): void { $filter = new ArrayItems(); @@ -122,6 +195,25 @@ public function testMatchingUniqueItems(): void ); } + public function testMatchingUniqueItemsOpenApi(): void + { + $filter = new ArrayItems(); + + $filterDefinition = [ + 'openapi' => [ + 'uniqueItems' => true, + ], + ]; + + $request = ['some_filter' => ['foo', 'bar', 'baz']]; + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, $request) + ); + } + + /** + * @group legacy + */ public function testSeparators(): void { $filter = new ArrayItems(); @@ -179,6 +271,66 @@ public function testSeparators(): void ); } + public function testSeparatorsOpenApi(): void + { + $filter = new ArrayItems(); + + $filterDefinition = [ + 'openapi' => [ + 'maxItems' => 2, + 'uniqueItems' => true, + 'collectionFormat' => 'csv', + ], + ]; + + $request = ['some_filter' => 'foo,bar,bar']; + $this->assertEquals( + [ + 'Query parameter "some_filter" must contain less than 2 values', + 'Query parameter "some_filter" must contain unique values', + ], + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $filterDefinition['openapi']['collectionFormat'] = 'ssv'; + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $filterDefinition['openapi']['collectionFormat'] = 'ssv'; + $request = ['some_filter' => 'foo bar bar']; + $this->assertEquals( + [ + 'Query parameter "some_filter" must contain less than 2 values', + 'Query parameter "some_filter" must contain unique values', + ], + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $filterDefinition['openapi']['collectionFormat'] = 'tsv'; + $request = ['some_filter' => 'foo\tbar\tbar']; + $this->assertEquals( + [ + 'Query parameter "some_filter" must contain less than 2 values', + 'Query parameter "some_filter" must contain unique values', + ], + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $filterDefinition['openapi']['collectionFormat'] = 'pipes'; + $request = ['some_filter' => 'foo|bar|bar']; + $this->assertEquals( + [ + 'Query parameter "some_filter" must contain less than 2 values', + 'Query parameter "some_filter" must contain unique values', + ], + $filter->validate('some_filter', $filterDefinition, $request) + ); + } + + /** + * @group legacy + */ public function testSeparatorsUnknownSeparator(): void { $filter = new ArrayItems(); @@ -197,4 +349,23 @@ public function testSeparatorsUnknownSeparator(): void $filter->validate('some_filter', $filterDefinition, $request); } + + public function testSeparatorsUnknownSeparatorOpenApi(): void + { + $filter = new ArrayItems(); + + $filterDefinition = [ + 'openapi' => [ + 'maxItems' => 2, + 'uniqueItems' => true, + 'collectionFormat' => 'unknownFormat', + ], + ]; + $request = ['some_filter' => 'foo,bar,bar']; + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Unknown collection format unknownFormat'); + + $filter->validate('some_filter', $filterDefinition, $request); + } } diff --git a/tests/Api/QueryParameterValidator/Validator/BoundsTest.php b/tests/Api/QueryParameterValidator/Validator/BoundsTest.php index 933f555ca82..3bc91ca9926 100644 --- a/tests/Api/QueryParameterValidator/Validator/BoundsTest.php +++ b/tests/Api/QueryParameterValidator/Validator/BoundsTest.php @@ -18,8 +18,6 @@ /** * @author Julien Deniau - * - * @group legacy */ class BoundsTest extends TestCase { @@ -41,6 +39,9 @@ public function testEmptyQueryParameter(): void ); } + /** + * @group legacy + */ public function testNonMatchingMinimum(): void { $request = ['some_filter' => '9']; @@ -82,6 +83,50 @@ public function testNonMatchingMinimum(): void ); } + public function testNonMatchingMinimumOpenApi(): void + { + $request = ['some_filter' => '9']; + $filter = new Bounds(); + + $filterDefinition = [ + 'openapi' => [ + 'minimum' => 10, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" must be greater than or equal to 10'], + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $filterDefinition = [ + 'openapi' => [ + 'minimum' => 10, + 'exclusiveMinimum' => false, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" must be greater than or equal to 10'], + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $filterDefinition = [ + 'openapi' => [ + 'minimum' => 9, + 'exclusiveMinimum' => true, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" must be greater than 9'], + $filter->validate('some_filter', $filterDefinition, $request) + ); + } + + /** + * @group legacy + */ public function testMatchingMinimum(): void { $request = ['some_filter' => '10']; @@ -109,6 +154,36 @@ public function testMatchingMinimum(): void ); } + public function testMatchingMinimumOpenApi(): void + { + $request = ['some_filter' => '10']; + $filter = new Bounds(); + + $filterDefinition = [ + 'openapi' => [ + 'minimum' => 10, + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $filterDefinition = [ + 'openapi' => [ + 'minimum' => 9, + 'exclusiveMinimum' => false, + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, $request) + ); + } + + /** + * @group legacy + */ public function testNonMatchingMaximum(): void { $request = ['some_filter' => '11']; @@ -150,6 +225,50 @@ public function testNonMatchingMaximum(): void ); } + public function testNonMatchingMaximumOpenApi(): void + { + $request = ['some_filter' => '11']; + $filter = new Bounds(); + + $filterDefinition = [ + 'openapi' => [ + 'maximum' => 10, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" must be less than or equal to 10'], + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $filterDefinition = [ + 'openapi' => [ + 'maximum' => 10, + 'exclusiveMaximum' => false, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" must be less than or equal to 10'], + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $filterDefinition = [ + 'openapi' => [ + 'maximum' => 9, + 'exclusiveMaximum' => true, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" must be less than 9'], + $filter->validate('some_filter', $filterDefinition, $request) + ); + } + + /** + * @group legacy + */ public function testMatchingMaximum(): void { $request = ['some_filter' => '10']; @@ -176,4 +295,31 @@ public function testMatchingMaximum(): void $filter->validate('some_filter', $filterDefinition, $request) ); } + + public function testMatchingMaximumOpenApi(): void + { + $request = ['some_filter' => '10']; + $filter = new Bounds(); + + $filterDefinition = [ + 'openapi' => [ + 'maximum' => 10, + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, $request) + ); + + $filterDefinition = [ + 'openapi' => [ + 'maximum' => 10, + 'exclusiveMaximum' => false, + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, $request) + ); + } } diff --git a/tests/Api/QueryParameterValidator/Validator/EnumTest.php b/tests/Api/QueryParameterValidator/Validator/EnumTest.php index 9d29b039fd7..e2389cfb763 100644 --- a/tests/Api/QueryParameterValidator/Validator/EnumTest.php +++ b/tests/Api/QueryParameterValidator/Validator/EnumTest.php @@ -18,8 +18,6 @@ /** * @author Julien Deniau - * - * @group legacy */ class EnumTest extends TestCase { @@ -41,6 +39,9 @@ public function testEmptyQueryParameter(): void ); } + /** + * @group legacy + */ public function testNonMatchingParameter(): void { $filter = new Enum(); @@ -57,6 +58,25 @@ public function testNonMatchingParameter(): void ); } + public function testNonMatchingParameterOpenApi(): void + { + $filter = new Enum(); + + $filterDefinition = [ + 'openapi' => [ + 'enum' => ['foo', 'bar'], + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" must be one of "foo, bar"'], + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'foobar']) + ); + } + + /** + * @group legacy + */ public function testMatchingParameter(): void { $filter = new Enum(); @@ -71,4 +91,19 @@ public function testMatchingParameter(): void $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'foo']) ); } + + public function testMatchingParameterOpenApi(): void + { + $filter = new Enum(); + + $filterDefinition = [ + 'openapi' => [ + 'enum' => ['foo', 'bar'], + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'foo']) + ); + } } diff --git a/tests/Api/QueryParameterValidator/Validator/LengthTest.php b/tests/Api/QueryParameterValidator/Validator/LengthTest.php index d66626c9fcc..09ab8557214 100644 --- a/tests/Api/QueryParameterValidator/Validator/LengthTest.php +++ b/tests/Api/QueryParameterValidator/Validator/LengthTest.php @@ -18,8 +18,6 @@ /** * @author Julien Deniau - * - * @group legacy */ class LengthTest extends TestCase { @@ -41,6 +39,9 @@ public function testEmptyQueryParameter(): void ); } + /** + * @group legacy + */ public function testNonMatchingParameter(): void { $filter = new Length(); @@ -63,6 +64,31 @@ public function testNonMatchingParameter(): void ); } + public function testNonMatchingParameterOpenApi(): void + { + $filter = new Length(); + + $filterDefinition = [ + 'openapi' => [ + 'minLength' => 3, + 'maxLength' => 5, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" length must be greater than or equal to 3'], + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'ab']) + ); + + $this->assertEquals( + ['Query parameter "some_filter" length must be lower than or equal to 5'], + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'abcdef']) + ); + } + + /** + * @group legacy + */ public function testNonMatchingParameterWithOnlyOneDefinition(): void { $filter = new Length(); @@ -90,6 +116,36 @@ public function testNonMatchingParameterWithOnlyOneDefinition(): void ); } + public function testNonMatchingParameterWithOnlyOneDefinitionOpenApi(): void + { + $filter = new Length(); + + $filterDefinition = [ + 'openapi' => [ + 'minLength' => 3, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" length must be greater than or equal to 3'], + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'ab']) + ); + + $filterDefinition = [ + 'openapi' => [ + 'maxLength' => 5, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" length must be lower than or equal to 5'], + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'abcdef']) + ); + } + + /** + * @group legacy + */ public function testMatchingParameter(): void { $filter = new Length(); @@ -114,6 +170,33 @@ public function testMatchingParameter(): void ); } + public function testMatchingParameterOpenApi(): void + { + $filter = new Length(); + + $filterDefinition = [ + 'openapi' => [ + 'minLength' => 3, + 'maxLength' => 5, + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'abc']) + ); + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'abcd']) + ); + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'abcde']) + ); + } + + /** + * @group legacy + */ public function testMatchingParameterWithOneDefinition(): void { $filter = new Length(); @@ -138,4 +221,29 @@ public function testMatchingParameterWithOneDefinition(): void $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'abcde']) ); } + + public function testMatchingParameterWithOneDefinitionOpenApi(): void + { + $filter = new Length(); + + $filterDefinition = [ + 'openapi' => [ + 'minLength' => 3, + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'abc']) + ); + + $filterDefinition = [ + 'openapi' => [ + 'maxLength' => 5, + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, ['some_filter' => 'abcde']) + ); + } } diff --git a/tests/Api/QueryParameterValidator/Validator/MultipleOfTest.php b/tests/Api/QueryParameterValidator/Validator/MultipleOfTest.php index 7738c4227ea..783e73f338d 100644 --- a/tests/Api/QueryParameterValidator/Validator/MultipleOfTest.php +++ b/tests/Api/QueryParameterValidator/Validator/MultipleOfTest.php @@ -18,8 +18,6 @@ /** * @author Julien Deniau - * - * @group legacy */ class MultipleOfTest extends TestCase { @@ -42,6 +40,9 @@ public function testEmptyQueryParameter(): void ); } + /** + * @group legacy + */ public function testNonMatchingParameter(): void { $request = ['some_filter' => '8']; @@ -59,6 +60,26 @@ public function testNonMatchingParameter(): void ); } + public function testNonMatchingParameterOpenApi(): void + { + $request = ['some_filter' => '8']; + $filter = new MultipleOf(); + + $filterDefinition = [ + 'openapi' => [ + 'multipleOf' => 3, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" must multiple of 3'], + $filter->validate('some_filter', $filterDefinition, $request) + ); + } + + /** + * @group legacy + */ public function testMatchingParameter(): void { $request = ['some_filter' => '8']; @@ -74,4 +95,20 @@ public function testMatchingParameter(): void $filter->validate('some_filter', $filterDefinition, $request) ); } + + public function testMatchingParameterOpenApi(): void + { + $request = ['some_filter' => '8']; + $filter = new MultipleOf(); + + $filterDefinition = [ + 'openapi' => [ + 'multipleOf' => 4, + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $filterDefinition, $request) + ); + } } diff --git a/tests/Api/QueryParameterValidator/Validator/PatternTest.php b/tests/Api/QueryParameterValidator/Validator/PatternTest.php index 0ffed0bbf57..9c9dcd9ac3a 100644 --- a/tests/Api/QueryParameterValidator/Validator/PatternTest.php +++ b/tests/Api/QueryParameterValidator/Validator/PatternTest.php @@ -18,8 +18,6 @@ /** * @author Julien Deniau - * - * @group legacy */ class PatternTest extends TestCase { @@ -32,6 +30,9 @@ public function testNonDefinedFilter(): void ); } + /** + * @group legacy + */ public function testFilterWithEmptyValue(): void { $filter = new Pattern(); @@ -53,6 +54,30 @@ public function testFilterWithEmptyValue(): void ); } + public function testFilterWithEmptyValueOpenApi(): void + { + $filter = new Pattern(); + + $explicitFilterDefinition = [ + 'openapi' => [ + 'pattern' => '/foo/', + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $explicitFilterDefinition, ['some_filter' => '']) + ); + + $weirdParameter = new \stdClass(); + $weirdParameter->foo = 'non string value should not exists'; + $this->assertEmpty( + $filter->validate('some_filter', $explicitFilterDefinition, ['some_filter' => $weirdParameter]) + ); + } + + /** + * @group legacy + */ public function testFilterWithZeroAsParameter(): void { $filter = new Pattern(); @@ -69,6 +94,25 @@ public function testFilterWithZeroAsParameter(): void ); } + public function testFilterWithZeroAsParameterOpenApi(): void + { + $filter = new Pattern(); + + $explicitFilterDefinition = [ + 'openapi' => [ + 'pattern' => '/foo/', + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" must match pattern /foo/'], + $filter->validate('some_filter', $explicitFilterDefinition, ['some_filter' => '0']) + ); + } + + /** + * @group legacy + */ public function testFilterWithNonMatchingValue(): void { $filter = new Pattern(); @@ -85,6 +129,25 @@ public function testFilterWithNonMatchingValue(): void ); } + public function testFilterWithNonMatchingValueOpenApi(): void + { + $filter = new Pattern(); + + $explicitFilterDefinition = [ + 'openapi' => [ + 'pattern' => '/foo/', + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" must match pattern /foo/'], + $filter->validate('some_filter', $explicitFilterDefinition, ['some_filter' => 'bar']) + ); + } + + /** + * @group legacy + */ public function testFilterWithNonchingValue(): void { $filter = new Pattern(); @@ -99,4 +162,19 @@ public function testFilterWithNonchingValue(): void $filter->validate('some_filter', $explicitFilterDefinition, ['some_filter' => 'this is a foo '.random_int(0, 10).' and it should match']) ); } + + public function testFilterWithNonchingValueOpenApi(): void + { + $filter = new Pattern(); + + $explicitFilterDefinition = [ + 'openapi' => [ + 'pattern' => '/foo \d+/', + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $explicitFilterDefinition, ['some_filter' => 'this is a foo '.random_int(0, 10).' and it should match']) + ); + } } diff --git a/tests/Api/QueryParameterValidator/Validator/RequiredTest.php b/tests/Api/QueryParameterValidator/Validator/RequiredTest.php index 6e08e1ee437..bca7b404ab1 100644 --- a/tests/Api/QueryParameterValidator/Validator/RequiredTest.php +++ b/tests/Api/QueryParameterValidator/Validator/RequiredTest.php @@ -20,8 +20,6 @@ * Class RequiredTest. * * @author Julien Deniau - * - * @group legacy */ class RequiredTest extends TestCase { @@ -60,6 +58,9 @@ public function testRequiredFilterIsPresent(): void ); } + /** + * @group legacy + */ public function testEmptyValueNotAllowed(): void { $request = ['some_filter' => '']; @@ -87,6 +88,36 @@ public function testEmptyValueNotAllowed(): void ); } + public function testEmptyValueNotAllowedOpenApi(): void + { + $request = ['some_filter' => '']; + $filter = new Required(); + + $explicitFilterDefinition = [ + 'required' => true, + 'openapi' => [ + 'allowEmptyValue' => false, + ], + ]; + + $this->assertEquals( + ['Query parameter "some_filter" does not allow empty value'], + $filter->validate('some_filter', $explicitFilterDefinition, $request) + ); + + $implicitFilterDefinition = [ + 'required' => true, + ]; + + $this->assertEquals( + ['Query parameter "some_filter" does not allow empty value'], + $filter->validate('some_filter', $implicitFilterDefinition, $request) + ); + } + + /** + * @group legacy + */ public function testEmptyValueAllowed(): void { $request = ['some_filter' => '']; @@ -104,6 +135,23 @@ public function testEmptyValueAllowed(): void ); } + public function testEmptyValueAllowedOpenApi(): void + { + $request = ['some_filter' => '']; + $filter = new Required(); + + $explicitFilterDefinition = [ + 'required' => true, + 'openapi' => [ + 'allowEmptyValue' => true, + ], + ]; + + $this->assertEmpty( + $filter->validate('some_filter', $explicitFilterDefinition, $request) + ); + } + public function testBracketNotation(): void { $filter = new Required();