Apply contribution guidelines to "Type" rule

Also add integration test for Type rule.

Signed-off-by: Paul Karikari <paulkarikari1@gmail.com>
Co-Authored-By: Henrique Moody <henriquemoody@gmail.com>
This commit is contained in:
paul karikari 2018-06-15 16:57:00 +00:00 committed by Henrique Moody
parent 8aa6426ab1
commit 5a326b6c97
No known key found for this signature in database
GPG key ID: 221E9281655813A6
5 changed files with 123 additions and 74 deletions

View file

@ -14,6 +14,7 @@ v::type('object')->validate(new stdClass()); // true
Version | Description Version | Description
--------|------------- --------|-------------
2.0.0 | Became case-sensitive
0.8.0 | Created 0.8.0 | Created
*** ***

View file

@ -13,8 +13,17 @@ declare(strict_types=1);
namespace Respect\Validation\Exceptions; namespace Respect\Validation\Exceptions;
class TypeException extends ValidationException /**
* Exceptions thrown by Type rule.
*
* @author Henrique Moody <henriquemoody@gmail.com>
* @author Paul Karikari <paulkarikari1@gmail.com>
*/
final class TypeException extends ValidationException
{ {
/**
* {@inheritdoc}
*/
public static $defaultTemplates = [ public static $defaultTemplates = [
self::MODE_DEFAULT => [ self::MODE_DEFAULT => [
self::STANDARD => '{{name}} must be {{type}}', self::STANDARD => '{{name}} must be {{type}}',

View file

@ -14,11 +14,27 @@ declare(strict_types=1);
namespace Respect\Validation\Rules; namespace Respect\Validation\Rules;
use Respect\Validation\Exceptions\ComponentException; use Respect\Validation\Exceptions\ComponentException;
use function array_keys;
use function gettype;
use function implode;
use function is_callable;
use function sprintf;
class Type extends AbstractRule /**
* Validates the type of input.
*
* @author Gabriel Caruso <carusogabriel34@gmail.com>
* @author Henrique Moody <henriquemoody@gmail.com>
* @author Paul Karikari<paulkarikari1@gmail.com>
*/
final class Type extends AbstractRule
{ {
public $type; /**
public $availableTypes = [ * Collection of available types for validation.
*
* @var array
*/
private const AVAILABLE_TYPES = [
'array' => 'array', 'array' => 'array',
'bool' => 'boolean', 'bool' => 'boolean',
'boolean' => 'boolean', 'boolean' => 'boolean',
@ -33,23 +49,44 @@ class Type extends AbstractRule
'string' => 'string', 'string' => 'string',
]; ];
public function __construct($type) /**
* Type to validate input against.
*
* @var string
*/
private $type;
/**
* Initializes the rule.
*
* @param string $type
*
* @throws ComponentException When $type is not a valid one
*/
public function __construct(string $type)
{ {
$lowerType = mb_strtolower($type); if (!isset(self::AVAILABLE_TYPES[$type])) {
if (!isset($this->availableTypes[$lowerType])) { throw new ComponentException(
throw new ComponentException(sprintf('"%s" is not a valid type', print_r($type, true))); sprintf(
'"%s" is not a valid type (Available: %s)',
$type,
implode(', ', array_keys(self::AVAILABLE_TYPES))
)
);
} }
$this->type = $type; $this->type = $type;
} }
/**
* {@inheritdoc}
*/
public function validate($input): bool public function validate($input): bool
{ {
$lowerType = mb_strtolower($this->type); if ('callable' === $this->type) {
if ('callable' === $lowerType) {
return is_callable($input); return is_callable($input);
} }
return $this->availableTypes[$lowerType] === gettype($input); return self::AVAILABLE_TYPES[$this->type] === gettype($input);
} }
} }

View file

@ -0,0 +1,37 @@
--FILE--
<?php
require 'vendor/autoload.php';
use Respect\Validation\Exceptions\NestedValidationException;
use Respect\Validation\Exceptions\TypeException;
use Respect\Validation\Validator as v;
try {
v::type('integer')->check('42');
} catch (TypeException $exception) {
echo $exception->getMessage().PHP_EOL;
}
try {
v::not(v::type('string'))->check('foo');
} catch (TypeException $exception) {
echo $exception->getMessage().PHP_EOL;
}
try {
v::type('double')->assert(20);
} catch (NestedValidationException $exception) {
echo $exception->getFullMessage().PHP_EOL;
}
try {
v::not(v::type('bool'))->assert(true);
} catch (NestedValidationException $exception) {
echo $exception->getFullMessage().PHP_EOL;
}
?>
--EXPECTF--
"42" must be "integer"
"foo" must not be "string"
- 20 must be "double"
- `TRUE` must not be "bool"

View file

@ -13,34 +13,23 @@ declare(strict_types=1);
namespace Respect\Validation\Rules; namespace Respect\Validation\Rules;
use PHPUnit\Framework\TestCase; use Respect\Validation\Test\RuleTestCase;
use stdClass; use stdClass;
use function tmpfile;
/** /**
* @group rule * @group rule
*
* @covers \Respect\Validation\Rules\Type * @covers \Respect\Validation\Rules\Type
* @covers \Respect\Validation\Exceptions\TypeException *
* @author Henrique Moody <henriquemoody@gmail.com>
* @author Paul Karikari <paulkarikari1@gmail.com>
*/ */
class TypeTest extends TestCase class TypeTest extends RuleTestCase
{ {
public function testShouldDefineTypeOnConstructor(): void
{
$type = 'int';
$rule = new Type($type);
self::assertSame($type, $rule->type);
}
public function testShouldNotBeCaseSensitive(): void
{
$rule = new Type('InTeGeR');
self::assertTrue($rule->validate(42));
}
/** /**
* @expectedException \Respect\Validation\Exceptions\ComponentException * @expectedException \Respect\Validation\Exceptions\ComponentException
* @expectedExceptionMessage "whatever" is not a valid type * @expectedExceptionMessage "whatever" is not a valid type (Available: array, bool, boolean, callable, double, float, int, integer, null, object, resource, string)
*/ */
public function testShouldThrowExceptionWhenTypeIsNotValid(): void public function testShouldThrowExceptionWhenTypeIsNotValid(): void
{ {
@ -48,59 +37,35 @@ class TypeTest extends TestCase
} }
/** /**
* @dataProvider providerForValidType * {@inheritdoc}
*/ */
public function testShouldValidateValidTypes($type, $input): void public function providerForValidInput(): array
{
$rule = new Type($type);
self::assertTrue($rule->validate($input));
}
/**
* @dataProvider providerForInvalidType
*/
public function testShouldNotValidateInvalidTypes($type, $input): void
{
$rule = new Type($type);
self::assertFalse($rule->validate($input));
}
/**
* @expectedException \Respect\Validation\Exceptions\TypeException
* @expectedExceptionMessage "Something" must be "integer"
*/
public function testShouldThrowTypeExceptionWhenCheckingAnInvalidInput(): void
{
$rule = new Type('integer');
$rule->check('Something');
}
public function providerForValidType()
{ {
return [ return [
['array', []], [new Type('array'), []],
['bool', true], [new Type('bool'), true],
['boolean', false], [new Type('boolean'), false],
['callable', function (): void { [new Type('callable'), function (): void {
}], }],
['double', 0.8], [new Type('double'), 0.8],
['float', 1.0], [new Type('float'), 1.0],
['int', 42], [new Type('int'), 42],
['integer', 13], [new Type('integer'), 13],
['null', null], [new Type('null'), null],
['object', new stdClass()], [new Type('object'), new stdClass()],
['resource', tmpfile()], [new Type('resource'), tmpfile()],
['string', 'Something'], [new Type('string'), 'Something'],
]; ];
} }
public function providerForInvalidType() /**
* {@inheritdoc}
*/
public function providerForInvalidInput(): array
{ {
return [ return [
['int', '1'], [new Type('int'), '1'],
['bool', '1'], [new Type('bool'), '1'],
]; ];
} }
} }