From 444e745139876e1df695214a09f313140f70cc90 Mon Sep 17 00:00:00 2001 From: "maurin.stutz" Date: Wed, 16 Sep 2026 15:49:35 +0200 Subject: [PATCH 1/5] Add validation trait method for numeric range --- CHANGELOG.md | 1 + docs/Usage.md | 1 + src/Traits/DataValidationTestTrait.php | 47 +++++++++++++++++++ .../Model/Table/ValidationTestTable.php | 3 +- .../Traits/DataValidationTestTraitTest.php | 21 +++++++++ tests/bootstrap.php | 3 +- 6 files changed, 74 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c23ea4..2a4802b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased](https://github.com/orca-services/cakephp-data-validation-testing) ### Added +- Add validation trait method for numeric range ### Changed diff --git a/docs/Usage.md b/docs/Usage.md index 3558e43..07028bc 100644 --- a/docs/Usage.md +++ b/docs/Usage.md @@ -80,6 +80,7 @@ Each helper builds an entity, runs the validator, and asserts the expected error - `testDataValidationMaxLength($table, $fieldName, $maxLength)` - `testDataValidationMinLength($table, $fieldName, $minLength, $expected)` - `testDataValidationLengthBetween($table, $fieldName, $minLength, $maxLength)` +- `testDataValidationRange($table, $fieldName, $lowerBound, $upperBound)` - rejects numeric values outside of given range ### Generic helpers diff --git a/src/Traits/DataValidationTestTrait.php b/src/Traits/DataValidationTestTrait.php index 8f128c2..06a0c9b 100644 --- a/src/Traits/DataValidationTestTrait.php +++ b/src/Traits/DataValidationTestTrait.php @@ -792,6 +792,53 @@ protected function testDataValidationLengthBetween( $this->testDataValidation($table, $fieldName, $dataset, $expected, $options); } + /** + * Validate the range data validation of a field for a given table + * + * @param Table $table The table to test. + * @param string $fieldName The field to check the range. + * @param int $lowerBound The lower bound of the field + * @param int $upperBound The upper bound of the field + * @param array|null $expected The expected data validation errors. + * @param ?array $options Additional options for newEntity. + * @return void + * @see \Cake\Validation\Validator::range() + */ + protected function testDataValidationRange( + Table $table, + string $fieldName, + int $lowerBound, + int $upperBound, + ?array $expected = null, + ?array $options = [], + ): void { + // Too short + $tooShortFieldContent = $lowerBound - 1; + $dataset = [$fieldName => $tooShortFieldContent]; + + $expected ??= [ + 'range' => sprintf( + 'The provided value must be between `%s` and `%s`, inclusively', + $lowerBound, + $upperBound, + ), + ]; + $this->testDataValidation($table, $fieldName, $dataset, $expected, $options); + + // Too long + $tooLongFieldContent = $upperBound + 1; + $dataset = [$fieldName => $tooLongFieldContent]; + + $expected ??= [ + 'lengthBetween' => sprintf( + 'The provided value must be between `%s` and `%s`, inclusively', + $lowerBound, + $upperBound, + ), + ]; + $this->testDataValidation($table, $fieldName, $dataset, $expected, $options); + } + /** * Validate that a given field is validated as a natural number (positive integers only) * diff --git a/tests/TestApp/Model/Table/ValidationTestTable.php b/tests/TestApp/Model/Table/ValidationTestTable.php index 49e18dd..9864e52 100644 --- a/tests/TestApp/Model/Table/ValidationTestTable.php +++ b/tests/TestApp/Model/Table/ValidationTestTable.php @@ -65,7 +65,8 @@ public function validationDefault(Validator $validator): Validator ->allowEmptyString('parent_id') ->integer('parent_id') ->email('email_field') - ->uuid('uuid_field'); + ->uuid('uuid_field') + ->range('range_field', [-30, 30]); return $validator; } diff --git a/tests/TestCase/Traits/DataValidationTestTraitTest.php b/tests/TestCase/Traits/DataValidationTestTraitTest.php index e415bef..b63a0fd 100644 --- a/tests/TestCase/Traits/DataValidationTestTraitTest.php +++ b/tests/TestCase/Traits/DataValidationTestTraitTest.php @@ -431,6 +431,27 @@ public function testTestDataValidationLengthBetween(): void $this->testDataValidationLengthBetween($this->table, $field, $minLength, $maxLength); } + /** + * Test that testDataValidationRange passes when the field is between the lower and upper bound. + * + * @return void + * @covers ::testDataValidationRange + */ + public function testTestDataValidationRange(): void + { + // Ensure data validation of the field works as expected first + $lowerBound = -30; + $upperBound = 30; + $field = 'range_field'; + $expectedErrors = ['range' => 'The provided value must be between `-30` and `30`, inclusively']; + $dataSet = [$field => $lowerBound - 1]; + $this->testDataValidation($this->table, $field, $dataSet, $expectedErrors); + $dataSet = [$field => $upperBound + 1]; + $this->testDataValidation($this->table, $field, $dataSet, $expectedErrors); + + $this->testDataValidationRange($this->table, $field, $lowerBound, $upperBound); + } + /** * Test that testDataValidationNaturalNumber passes when the field is a natural number. * diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 8dfa39f..223cea7 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -82,7 +82,8 @@ natural_number_field INTEGER, unique_field VARCHAR(255) UNIQUE, email_field VARCHAR(255), - uuid VARCHAR(36) + uuid VARCHAR(36), + range_field INT ) '); From 3bd385acdf75668c81ab5a89647935d3b0b8c135 Mon Sep 17 00:00:00 2001 From: "maurin.stutz" Date: Thu, 17 Sep 2026 11:27:00 +0200 Subject: [PATCH 2/5] Improve wording --- docs/Usage.md | 2 +- src/Traits/DataValidationTestTrait.php | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/Usage.md b/docs/Usage.md index 07028bc..cb79994 100644 --- a/docs/Usage.md +++ b/docs/Usage.md @@ -80,7 +80,7 @@ Each helper builds an entity, runs the validator, and asserts the expected error - `testDataValidationMaxLength($table, $fieldName, $maxLength)` - `testDataValidationMinLength($table, $fieldName, $minLength, $expected)` - `testDataValidationLengthBetween($table, $fieldName, $minLength, $maxLength)` -- `testDataValidationRange($table, $fieldName, $lowerBound, $upperBound)` - rejects numeric values outside of given range +- `testDataValidationRange($table, $fieldName, $lowerBound, $upperBound)` ### Generic helpers diff --git a/src/Traits/DataValidationTestTrait.php b/src/Traits/DataValidationTestTrait.php index 06a0c9b..c46495d 100644 --- a/src/Traits/DataValidationTestTrait.php +++ b/src/Traits/DataValidationTestTrait.php @@ -797,8 +797,8 @@ protected function testDataValidationLengthBetween( * * @param Table $table The table to test. * @param string $fieldName The field to check the range. - * @param int $lowerBound The lower bound of the field - * @param int $upperBound The upper bound of the field + * @param int $lowerBound The lower bound to check with. + * @param int $upperBound The upper bound to check with. * @param array|null $expected The expected data validation errors. * @param ?array $options Additional options for newEntity. * @return void @@ -812,9 +812,9 @@ protected function testDataValidationRange( ?array $expected = null, ?array $options = [], ): void { - // Too short - $tooShortFieldContent = $lowerBound - 1; - $dataset = [$fieldName => $tooShortFieldContent]; + // Too low + $tooLowFieldContent = $lowerBound - 1; + $dataset = [$fieldName => $tooLowFieldContent]; $expected ??= [ 'range' => sprintf( @@ -825,9 +825,9 @@ protected function testDataValidationRange( ]; $this->testDataValidation($table, $fieldName, $dataset, $expected, $options); - // Too long - $tooLongFieldContent = $upperBound + 1; - $dataset = [$fieldName => $tooLongFieldContent]; + // Too high + $tooHighFieldContent = $upperBound + 1; + $dataset = [$fieldName => $tooHighFieldContent]; $expected ??= [ 'lengthBetween' => sprintf( From a2d58346a56804a4dd51f3a83873e7a5ddfa15c4 Mon Sep 17 00:00:00 2001 From: "maurin.stutz" Date: Thu, 17 Sep 2026 11:48:06 +0200 Subject: [PATCH 3/5] Improve range validation test trait - Use in list for error cases - Add valid cases using in list - Allow floats as datatype - Test with float as datatype --- src/Traits/DataValidationTestTrait.php | 36 ++++++++++--------- .../Model/Table/ValidationTestTable.php | 2 +- .../Traits/DataValidationTestTraitTest.php | 6 ++-- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/Traits/DataValidationTestTrait.php b/src/Traits/DataValidationTestTrait.php index c46495d..f9d71e5 100644 --- a/src/Traits/DataValidationTestTrait.php +++ b/src/Traits/DataValidationTestTrait.php @@ -797,8 +797,8 @@ protected function testDataValidationLengthBetween( * * @param Table $table The table to test. * @param string $fieldName The field to check the range. - * @param int $lowerBound The lower bound to check with. - * @param int $upperBound The upper bound to check with. + * @param float|int $lowerBound The lower bound to check with. + * @param float|int $upperBound The upper bound to check with. * @param array|null $expected The expected data validation errors. * @param ?array $options Additional options for newEntity. * @return void @@ -807,14 +807,20 @@ protected function testDataValidationLengthBetween( protected function testDataValidationRange( Table $table, string $fieldName, - int $lowerBound, - int $upperBound, + int|float $lowerBound, + int|float $upperBound, ?array $expected = null, ?array $options = [], ): void { + // Too high + $tooHighFieldContent = $upperBound + 1; // Too low $tooLowFieldContent = $lowerBound - 1; - $dataset = [$fieldName => $tooLowFieldContent]; + + $list = [ + $tooHighFieldContent, + $tooLowFieldContent, + ]; $expected ??= [ 'range' => sprintf( @@ -823,20 +829,16 @@ protected function testDataValidationRange( $upperBound, ), ]; - $this->testDataValidation($table, $fieldName, $dataset, $expected, $options); - - // Too high - $tooHighFieldContent = $upperBound + 1; - $dataset = [$fieldName => $tooHighFieldContent]; + $this->testDataValidationInList($table, $list, $fieldName, $expected, $options); - $expected ??= [ - 'lengthBetween' => sprintf( - 'The provided value must be between `%s` and `%s`, inclusively', - $lowerBound, - $upperBound, - ), + // Valid + $list = [ + $upperBound, + $lowerBound, ]; - $this->testDataValidation($table, $fieldName, $dataset, $expected, $options); + + // Expect no errors + $this->testDataValidationInList($table, $list, $fieldName, [], $options); } /** diff --git a/tests/TestApp/Model/Table/ValidationTestTable.php b/tests/TestApp/Model/Table/ValidationTestTable.php index 9864e52..e904c8a 100644 --- a/tests/TestApp/Model/Table/ValidationTestTable.php +++ b/tests/TestApp/Model/Table/ValidationTestTable.php @@ -66,7 +66,7 @@ public function validationDefault(Validator $validator): Validator ->integer('parent_id') ->email('email_field') ->uuid('uuid_field') - ->range('range_field', [-30, 30]); + ->range('range_field', [-30.5, 30.5]); return $validator; } diff --git a/tests/TestCase/Traits/DataValidationTestTraitTest.php b/tests/TestCase/Traits/DataValidationTestTraitTest.php index b63a0fd..102c608 100644 --- a/tests/TestCase/Traits/DataValidationTestTraitTest.php +++ b/tests/TestCase/Traits/DataValidationTestTraitTest.php @@ -440,10 +440,10 @@ public function testTestDataValidationLengthBetween(): void public function testTestDataValidationRange(): void { // Ensure data validation of the field works as expected first - $lowerBound = -30; - $upperBound = 30; + $lowerBound = -30.5; + $upperBound = 30.5; $field = 'range_field'; - $expectedErrors = ['range' => 'The provided value must be between `-30` and `30`, inclusively']; + $expectedErrors = ['range' => 'The provided value must be between `-30.5` and `30.5`, inclusively']; $dataSet = [$field => $lowerBound - 1]; $this->testDataValidation($this->table, $field, $dataSet, $expectedErrors); $dataSet = [$field => $upperBound + 1]; From 4c166a2ab2ce13d3588c27002dc37245913bb920 Mon Sep 17 00:00:00 2001 From: "marc.wuerth" Date: Thu, 17 Sep 2026 13:58:11 +0200 Subject: [PATCH 4/5] CS --- src/Traits/DataValidationTestTrait.php | 28 +++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Traits/DataValidationTestTrait.php b/src/Traits/DataValidationTestTrait.php index f9d71e5..e23ef4d 100644 --- a/src/Traits/DataValidationTestTrait.php +++ b/src/Traits/DataValidationTestTrait.php @@ -352,16 +352,24 @@ protected function testDataValidationContains( $errors = $entity->getError($fieldName); foreach ($expected as $rule => $message) { - static::assertArrayHasKey($rule, $errors, sprintf( - 'Field `%s` does not have expected validation error `%s`.', - $fieldName, + static::assertArrayHasKey( $rule, - )); - static::assertSame($message, $errors[$rule], sprintf( - 'Validation error message for field `%s` and rule `%s` does not match expected.', - $fieldName, - $rule, - )); + $errors, + sprintf( + 'Field `%s` does not have expected validation error `%s`.', + $fieldName, + $rule, + ), + ); + static::assertSame( + $message, + $errors[$rule], + sprintf( + 'Validation error message for field `%s` and rule `%s` does not match expected.', + $fieldName, + $rule, + ), + ); } } @@ -819,6 +827,8 @@ protected function testDataValidationRange( $list = [ $tooHighFieldContent, + $tooHighFieldContent, + $tooLowFieldContent, $tooLowFieldContent, ]; From 3833e7a6536a93b356445a4acbc64f11853229f5 Mon Sep 17 00:00:00 2001 From: "marc.wuerth" Date: Thu, 17 Sep 2026 14:18:06 +0200 Subject: [PATCH 5/5] Test against int & float #42 --- src/Traits/DataValidationTestTrait.php | 27 +++++++++++-------- .../Model/Table/ValidationTestTable.php | 2 +- .../Traits/DataValidationTestTraitTest.php | 8 +++--- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/Traits/DataValidationTestTrait.php b/src/Traits/DataValidationTestTrait.php index e23ef4d..3b469ab 100644 --- a/src/Traits/DataValidationTestTrait.php +++ b/src/Traits/DataValidationTestTrait.php @@ -820,16 +820,19 @@ protected function testDataValidationRange( ?array $expected = null, ?array $options = [], ): void { - // Too high - $tooHighFieldContent = $upperBound + 1; // Too low - $tooLowFieldContent = $lowerBound - 1; + $tooLowFloat = $lowerBound - 0.1; + $tooLowInt = $lowerBound - 1; + + // Too high + $tooHighFloat = $upperBound + 0.1; + $tooHighInt = $upperBound + 1; $list = [ - $tooHighFieldContent, - $tooHighFieldContent, - $tooLowFieldContent, - $tooLowFieldContent, + $tooLowFloat, + $tooLowInt, + $tooHighFloat, + $tooHighInt, ]; $expected ??= [ @@ -843,12 +846,14 @@ protected function testDataValidationRange( // Valid $list = [ - $upperBound, - $lowerBound, + (float)$lowerBound, + (int)$lowerBound, + (float)$upperBound, + (int)$upperBound, ]; - // Expect no errors - $this->testDataValidationInList($table, $list, $fieldName, [], $options); + $expected = []; + $this->testDataValidationInList($table, $list, $fieldName, $expected, $options); } /** diff --git a/tests/TestApp/Model/Table/ValidationTestTable.php b/tests/TestApp/Model/Table/ValidationTestTable.php index e904c8a..4941b6b 100644 --- a/tests/TestApp/Model/Table/ValidationTestTable.php +++ b/tests/TestApp/Model/Table/ValidationTestTable.php @@ -66,7 +66,7 @@ public function validationDefault(Validator $validator): Validator ->integer('parent_id') ->email('email_field') ->uuid('uuid_field') - ->range('range_field', [-30.5, 30.5]); + ->range('range_field', [-30.0, 30.0]); return $validator; } diff --git a/tests/TestCase/Traits/DataValidationTestTraitTest.php b/tests/TestCase/Traits/DataValidationTestTraitTest.php index 102c608..b2fd9c8 100644 --- a/tests/TestCase/Traits/DataValidationTestTraitTest.php +++ b/tests/TestCase/Traits/DataValidationTestTraitTest.php @@ -440,12 +440,14 @@ public function testTestDataValidationLengthBetween(): void public function testTestDataValidationRange(): void { // Ensure data validation of the field works as expected first - $lowerBound = -30.5; - $upperBound = 30.5; + $lowerBound = -30.0; + $upperBound = 30.0; $field = 'range_field'; - $expectedErrors = ['range' => 'The provided value must be between `-30.5` and `30.5`, inclusively']; + $expectedErrors = ['range' => 'The provided value must be between `-30` and `30`, inclusively']; + $dataSet = [$field => $lowerBound - 1]; $this->testDataValidation($this->table, $field, $dataSet, $expectedErrors); + $dataSet = [$field => $upperBound + 1]; $this->testDataValidation($this->table, $field, $dataSet, $expectedErrors);