-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented numerical range validation rule
- Loading branch information
Showing
6 changed files
with
272 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace HarmonyIO\Validation\Exception; | ||
|
||
class InvalidNumericValue extends Exception | ||
{ | ||
private const MESSAGE = 'Value (`%s`) must be a numeric value.'; | ||
|
||
/** | ||
* @param mixed $value | ||
*/ | ||
public function __construct($value) | ||
{ | ||
parent::__construct(sprintf(self::MESSAGE, $value)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace HarmonyIO\Validation\Exception; | ||
|
||
final class InvalidNumericalRange extends Exception | ||
{ | ||
private const MESSAGE_TEMPLATE = 'The minimum (`%s`) can not be greater than the maximum (`%s`).'; | ||
|
||
/** | ||
* @param mixed $minimum | ||
* @param mixed $maximum | ||
*/ | ||
public function __construct($minimum, $maximum) | ||
{ | ||
if (!is_numeric($minimum)) { | ||
throw new InvalidNumericValue($minimum); | ||
} | ||
|
||
if (!is_numeric($maximum)) { | ||
throw new InvalidNumericValue($maximum); | ||
} | ||
|
||
parent::__construct(sprintf(self::MESSAGE_TEMPLATE, $minimum, $maximum)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace HarmonyIO\Validation\Rule\Numeric; | ||
|
||
use Amp\Promise; | ||
use HarmonyIO\Validation\Exception\InvalidNumericalRange; | ||
use HarmonyIO\Validation\Exception\InvalidNumericValue; | ||
use HarmonyIO\Validation\Rule\Rule; | ||
use function Amp\call; | ||
|
||
final class Range implements Rule | ||
{ | ||
/** @var mixed */ | ||
private $minimumValue; | ||
|
||
/** @var mixed */ | ||
private $maximumValue; | ||
|
||
/** | ||
* @param mixed $minimumValue | ||
* @param mixed $maximumValue | ||
*/ | ||
public function __construct($minimumValue, $maximumValue) | ||
{ | ||
if (!is_numeric($minimumValue)) { | ||
throw new InvalidNumericValue($minimumValue); | ||
} | ||
|
||
if (!is_numeric($maximumValue)) { | ||
throw new InvalidNumericValue($maximumValue); | ||
} | ||
|
||
if ($minimumValue > $maximumValue) { | ||
throw new InvalidNumericalRange($minimumValue, $maximumValue); | ||
} | ||
|
||
$this->minimumValue = $minimumValue; | ||
$this->maximumValue = $maximumValue; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function validate($value): Promise | ||
{ | ||
return call(function () use ($value) { | ||
if (!yield (new NumericType())->validate($value)) { | ||
return false; | ||
} | ||
|
||
return $value >= $this->minimumValue && $value <= $this->maximumValue; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace HarmonyIO\ValidationTest\Unit\Exception; | ||
|
||
use HarmonyIO\PHPUnitExtension\TestCase; | ||
use HarmonyIO\Validation\Exception\InvalidNumericValue; | ||
|
||
class InvalidNumericValueTest extends TestCase | ||
{ | ||
public function testMessageIsFormattedCorrectly(): void | ||
{ | ||
$typeException = new InvalidNumericValue('randomstring'); | ||
|
||
$this->assertSame( | ||
'Value (`randomstring`) must be a numeric value.', | ||
$typeException->getMessage() | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace HarmonyIO\ValidationTest\Unit\Exception; | ||
|
||
use HarmonyIO\PHPUnitExtension\TestCase; | ||
use HarmonyIO\Validation\Exception\InvalidNumericalRange; | ||
use HarmonyIO\Validation\Exception\InvalidNumericValue; | ||
|
||
class InvalidNumericalRangeTest extends TestCase | ||
{ | ||
public function testConstructorThrowsUpWhenPassingANonNumericalMinimumValue(): void | ||
{ | ||
$this->expectException(InvalidNumericValue::class); | ||
$this->expectExceptionMessage('Value (`not a numerical value`) must be a numeric value.'); | ||
|
||
new InvalidNumericalRange('not a numerical value', 18); | ||
} | ||
|
||
public function testConstructorThrowsUpWhenPassingANonNumericalMaximumValue(): void | ||
{ | ||
$this->expectException(InvalidNumericValue::class); | ||
$this->expectExceptionMessage('Value (`not a numerical value`) must be a numeric value.'); | ||
|
||
new InvalidNumericalRange(18, 'not a numerical value'); | ||
} | ||
|
||
public function testMessageIsFormattedCorrectly(): void | ||
{ | ||
$typeException = new InvalidNumericalRange(21, 18); | ||
|
||
$this->assertSame( | ||
'The minimum (`21`) can not be greater than the maximum (`18`).', | ||
$typeException->getMessage() | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace HarmonyIO\ValidationTest\Unit\Rule\Numeric; | ||
|
||
use HarmonyIO\PHPUnitExtension\TestCase; | ||
use HarmonyIO\Validation\Exception\InvalidNumericalRange; | ||
use HarmonyIO\Validation\Exception\InvalidNumericValue; | ||
use HarmonyIO\Validation\Rule\Numeric\Range; | ||
use HarmonyIO\Validation\Rule\Rule; | ||
|
||
class RangeTest extends TestCase | ||
{ | ||
public function testConstructorThrowsOnNonNumericMinimumValue(): void | ||
{ | ||
$this->expectException(InvalidNumericValue::class); | ||
$this->expectExceptionMessage('Value (`one`) must be a numeric value.'); | ||
|
||
new Range('one', 2); | ||
} | ||
|
||
public function testConstructorThrowsOnNonNumericMaximumValue(): void | ||
{ | ||
$this->expectException(InvalidNumericValue::class); | ||
$this->expectExceptionMessage('Value (`two`) must be a numeric value.'); | ||
|
||
new Range(1, 'two'); | ||
} | ||
|
||
public function testConstructorThrowsWhenMinimumValueIsGreaterThanMaximumValue(): void | ||
{ | ||
$this->expectException(InvalidNumericalRange::class); | ||
$this->expectExceptionMessage('The minimum (`51`) can not be greater than the maximum (`50`).'); | ||
|
||
new Range(51, 50); | ||
} | ||
|
||
public function testRuleImplementsInterface(): void | ||
{ | ||
$this->assertInstanceOf(Rule::class, new Range(13, 16)); | ||
} | ||
|
||
public function testValidateReturnsTrueWhenPassingAnInteger(): void | ||
{ | ||
$this->assertTrue((new Range(13, 16))->validate(14)); | ||
} | ||
|
||
public function testValidateReturnsTrueWhenPassingAFloat(): void | ||
{ | ||
$this->assertTrue((new Range(13, 16))->validate(14.1)); | ||
} | ||
|
||
public function testValidateReturnsFalseWhenPassingABoolean(): void | ||
{ | ||
$this->assertFalse((new Range(13, 16))->validate(true)); | ||
} | ||
|
||
public function testValidateReturnsFalseWhenPassingAnArray(): void | ||
{ | ||
$this->assertFalse((new Range(13, 16))->validate([])); | ||
} | ||
|
||
public function testValidateReturnsFalseWhenPassingAnObject(): void | ||
{ | ||
$this->assertFalse((new Range(13, 16))->validate(new \DateTimeImmutable())); | ||
} | ||
|
||
public function testValidateReturnsFalseWhenPassingNull(): void | ||
{ | ||
$this->assertFalse((new Range(13, 16))->validate(null)); | ||
} | ||
|
||
public function testValidateReturnsFalseWhenPassingAResource(): void | ||
{ | ||
$resource = fopen('php://memory', 'r'); | ||
|
||
if ($resource === false) { | ||
$this->fail('Could not open the memory stream used for the test'); | ||
|
||
return; | ||
} | ||
|
||
$this->assertFalse((new Range(13, 16))->validate($resource)); | ||
|
||
fclose($resource); | ||
} | ||
|
||
public function testValidateReturnsFalseWhenPassingACallable(): void | ||
{ | ||
$this->assertFalse((new Range(13, 16))->validate(static function (): void { | ||
})); | ||
} | ||
|
||
public function testValidateReturnsTrueWhenPassingAnIntegerAsAString(): void | ||
{ | ||
$this->assertTrue((new Range(13, 16))->validate('14')); | ||
} | ||
|
||
public function testValidateReturnsTrueWhenPassingAFloatAsAString(): void | ||
{ | ||
$this->assertTrue((new Range(13, 16))->validate('14.1')); | ||
} | ||
|
||
public function testValidateReturnsFalseWhenPassingAFloatValueLessThanTheMinimumValue(): void | ||
{ | ||
$this->assertFalse((new Range(13, 16))->validate(12.9)); | ||
} | ||
|
||
public function testValidateReturnsFalseWhenPassingAFloatValueMoreThanTheMaximumValue(): void | ||
{ | ||
$this->assertFalse((new Range(13, 16))->validate(16.1)); | ||
} | ||
|
||
public function testValidateReturnsFalseWhenPassingAnIntegerValueLessThanTheMinimumValue(): void | ||
{ | ||
$this->assertFalse((new Range(13, 16))->validate(12)); | ||
} | ||
|
||
public function testValidateReturnsFalseWhenPassingAnIntegerValueMoreThanTheMaximumValue(): void | ||
{ | ||
$this->assertFalse((new Range(13, 16))->validate(17)); | ||
} | ||
} |