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
--------|-------------
2.0.0 | Became case-sensitive
0.8.0 | Created
***

View file

@ -13,8 +13,17 @@ declare(strict_types=1);
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 = [
self::MODE_DEFAULT => [
self::STANDARD => '{{name}} must be {{type}}',

View file

@ -14,11 +14,27 @@ declare(strict_types=1);
namespace Respect\Validation\Rules;
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',
'bool' => 'boolean',
'boolean' => 'boolean',
@ -33,23 +49,44 @@ class Type extends AbstractRule
'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($this->availableTypes[$lowerType])) {
throw new ComponentException(sprintf('"%s" is not a valid type', print_r($type, true)));
if (!isset(self::AVAILABLE_TYPES[$type])) {
throw new ComponentException(
sprintf(
'"%s" is not a valid type (Available: %s)',
$type,
implode(', ', array_keys(self::AVAILABLE_TYPES))
)
);
}
$this->type = $type;
}
/**
* {@inheritdoc}
*/
public function validate($input): bool
{
$lowerType = mb_strtolower($this->type);
if ('callable' === $lowerType) {
if ('callable' === $this->type) {
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;
use PHPUnit\Framework\TestCase;
use Respect\Validation\Test\RuleTestCase;
use stdClass;
use function tmpfile;
/**
* @group rule
*
* @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
* @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
{
@ -48,59 +37,35 @@ class TypeTest extends TestCase
}
/**
* @dataProvider providerForValidType
* {@inheritdoc}
*/
public function testShouldValidateValidTypes($type, $input): void
{
$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()
public function providerForValidInput(): array
{
return [
['array', []],
['bool', true],
['boolean', false],
['callable', function (): void {
[new Type('array'), []],
[new Type('bool'), true],
[new Type('boolean'), false],
[new Type('callable'), function (): void {
}],
['double', 0.8],
['float', 1.0],
['int', 42],
['integer', 13],
['null', null],
['object', new stdClass()],
['resource', tmpfile()],
['string', 'Something'],
[new Type('double'), 0.8],
[new Type('float'), 1.0],
[new Type('int'), 42],
[new Type('integer'), 13],
[new Type('null'), null],
[new Type('object'), new stdClass()],
[new Type('resource'), tmpfile()],
[new Type('string'), 'Something'],
];
}
public function providerForInvalidType()
/**
* {@inheritdoc}
*/
public function providerForInvalidInput(): array
{
return [
['int', '1'],
['bool', '1'],
[new Type('int'), '1'],
[new Type('bool'), '1'],
];
}
}