Skip to content

Commit

Permalink
Allow to validate ArrayObject in key-related values
Browse files Browse the repository at this point in the history
Because of that, I also updated some data providers to distinguish
between "values" and "types", similar to some of the rules we already
have.

Signed-off-by: Henrique Moody <[email protected]>
  • Loading branch information
henriquemoody committed Mar 8, 2024
1 parent 7ded68c commit fe68eab
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 37 deletions.
11 changes: 10 additions & 1 deletion library/Rules/KeyExists.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace Respect\Validation\Rules;

use ArrayAccess;
use Respect\Validation\Message\Template;
use Respect\Validation\Result;
use Respect\Validation\Rules\Core\Standard;
Expand All @@ -34,6 +35,14 @@ public function evaluate(mixed $input): Result

private function hasKey(mixed $input): bool
{
return is_array($input) && array_key_exists($this->key, $input);
if (is_array($input)) {
return array_key_exists($this->key, $input);
}

if ($input instanceof ArrayAccess) {
return $input->offsetExists($this->key);
}

return false;
}
}
61 changes: 35 additions & 26 deletions tests/library/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,25 @@ public static function assertInvalidInput(Validatable $rule, mixed $input): void
public static function providerForAnyValues(): array
{
return array_merge(
self::providerForStringValues(),
self::providerForStringTypes(),
self::providerForNonScalarValues(),
self::providerForEmptyIterableValues(),
self::providerForNonEmptyIterableValues(),
self::providerForNonIterableValues(),
self::providerForIntegerValues(),
self::providerForBooleanValues(),
self::providerForFloatValues(),
self::providerForNonIterableTypes(),
self::providerForIntegerTypes(),
self::providerForBooleanTypes(),
self::providerForFloatTypes(),
);
}

/** @return array<array{scalar}> */
public static function providerForScalarValues(): array
{
return array_merge(
self::providerForStringValues(),
self::providerForIntegerValues(),
self::providerForBooleanValues(),
self::providerForFloatValues(),
self::providerForStringTypes(),
self::providerForIntegerTypes(),
self::providerForBooleanTypes(),
self::providerForFloatTypes(),
);
}

Expand All @@ -119,7 +119,7 @@ public static function providerForNonScalarValues(): array
}

/** @return array<array{mixed}> */
public static function providerForNonIterableValues(): array
public static function providerForNonIterableTypes(): array
{
return array_merge(
self::providerForScalarValues(),
Expand All @@ -133,7 +133,7 @@ public static function providerForNonIterableValues(): array
}

/** @return array<array{iterable<mixed>}> */
public static function providerForIterableValues(): array
public static function providerForIterableTypes(): array
{
return array_merge(
self::providerForNonEmptyIterableValues(),
Expand Down Expand Up @@ -162,7 +162,7 @@ public static function providerForEmptyIterableValues(): array
}

/** @return array<array{string}> */
public static function providerForStringValues(): array
public static function providerForStringTypes(): array
{
return [
'string' => ['string'],
Expand All @@ -174,27 +174,27 @@ public static function providerForStringValues(): array
}

/** @return array<array{string}> */
public static function providerForNonEmptyStringValues(): array
public static function providerForNonEmptyStringTypes(): array
{
$dataProvider = self::providerForStringValues();
$dataProvider = self::providerForStringTypes();
unset($dataProvider['empty string']);

return $dataProvider;
}

/** @return array<array{mixed}> */
public static function providerForNonStringValues(): array
public static function providerForNonStringTypes(): array
{
return array_merge(
self::providerForNonScalarValues(),
self::providerForIntegerValues(),
self::providerForBooleanValues(),
self::providerForFloatValues(),
self::providerForIntegerTypes(),
self::providerForBooleanTypes(),
self::providerForFloatTypes(),
);
}

/** @return array<array{int}> */
public static function providerForIntegerValues(): array
public static function providerForIntegerTypes(): array
{
return [
'zero integer' => [0],
Expand All @@ -204,7 +204,7 @@ public static function providerForIntegerValues(): array
}

/** @return array<array{bool}> */
public static function providerForBooleanValues(): array
public static function providerForBooleanTypes(): array
{
return [
'true' => [true],
Expand All @@ -213,7 +213,7 @@ public static function providerForBooleanValues(): array
}

/** @return array<array{float}> */
public static function providerForFloatValues(): array
public static function providerForFloatTypes(): array
{
return [
'zero float' => [0.0],
Expand All @@ -223,20 +223,29 @@ public static function providerForFloatValues(): array
}

/** @return array<array{mixed}> */
public static function providerForNonArrayValues(): array
public static function providerForNonArrayTypes(): array
{
$scalarValues = self::providerForNonScalarValues();
unset($scalarValues['array']);

return array_merge(
self::providerForIntegerValues(),
self::providerForBooleanValues(),
self::providerForFloatValues(),
self::providerForStringValues(),
self::providerForIntegerTypes(),
self::providerForBooleanTypes(),
self::providerForFloatTypes(),
self::providerForStringTypes(),
$scalarValues,
);
}

/** @return array<array{mixed}> */
public static function providerForNonArrayValues(): array
{
$arrayTypes = self::providerForNonArrayTypes();
unset($arrayTypes['ArrayObject']);

return $arrayTypes;
}

/** @return array<string, array{string|int, array<mixed>}> */
public static function providerForArrayWithMissingKeys(): array
{
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/Message/Parameter/StringifyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ final class StringifyTest extends TestCase
public const DEFAULT_NAME = 'not_name';

#[Test]
#[DataProvider('providerForStringValues')]
#[DataProvider('providerForStringTypes')]
public function itShouldNotStringifyValueWhenNameIsNameAndValueIsString(string $value): void
{
$stringify = new Stringify();
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/Message/Parameter/TransTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ final class TransTest extends TestCase
public const DEFAULT_NAME = 'foo';

#[Test]
#[DataProvider('providerForStringValues')]
#[DataProvider('providerForStringTypes')]
public function itShouldReturnTranslatedValueWhenModifierIsTransAndInputIsString(string $value): void
{
$translation = 'translated';
Expand All @@ -33,7 +33,7 @@ public function itShouldReturnTranslatedValueWhenModifierIsTransAndInputIsString
}

#[Test]
#[DataProvider('providerForNonStringValues')]
#[DataProvider('providerForNonStringTypes')]
public function itShouldUseNextProcessorWhenModifierIsTransButInputIsNotString(mixed $value): void
{
$next = new TestingProcessor();
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/Rules/Core/FilteredNonEmptyArrayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
final class FilteredNonEmptyArrayTest extends TestCase
{
#[Test]
#[DataProvider('providerForNonIterableValues')]
#[DataProvider('providerForNonIterableTypes')]
public function itShouldInvalidateNonIterableValues(mixed $input): void
{
$sut = new ConcreteFilteredNonEmptyArray(Stub::daze());
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/Rules/Core/FilteredStringTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public function itShouldPassExtraTemplateAndNonEmptyParametersWhenInputIsAnEmpty
}

#[Test]
#[DataProvider('providerForNonEmptyStringValues')]
#[DataProvider('providerForNonEmptyStringTypes')]
public function itShouldFilterNothingWhenHasNoAdditionalCharacters(string $input): void
{
$rule = new ConcreteFilteredString();
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/Rules/DomainTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function itShouldValidateDomainsWithRealTopLevelDomain(string $input): vo
}

#[Test]
#[DataProvider('providerForNonStringValues')]
#[DataProvider('providerForNonStringTypes')]
public function itShouldInvalidWhenInputIsNotString(mixed $input): void
{
self::assertInvalidInput(new Domain(), $input);
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/Rules/IterableTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ final class IterableTypeTest extends TestCase
{
/** @param iterable<mixed> $input */
#[Test]
#[DataProvider('providerForIterableValues')]
#[DataProvider('providerForIterableTypes')]
public function itShouldValidateIterableTypes(iterable $input): void
{
$rule = new IterableType();
Expand All @@ -30,7 +30,7 @@ public function itShouldValidateIterableTypes(iterable $input): void
}

#[Test]
#[DataProvider('providerForNonIterableValues')]
#[DataProvider('providerForNonIterableTypes')]
public function itShouldInvalidateNonIterableTypes(mixed $input): void
{
$rule = new IterableType();
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/Rules/MaxTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
final class MaxTest extends TestCase
{
#[Test]
#[DataProvider('providerForNonIterableValues')]
#[DataProvider('providerForNonIterableTypes')]
public function itShouldInvalidateNonIterableValues(mixed $input): void
{
$rule = new Max(Stub::daze());
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/Rules/MinTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
final class MinTest extends TestCase
{
#[Test]
#[DataProvider('providerForNonIterableValues')]
#[DataProvider('providerForNonIterableTypes')]
public function itShouldInvalidateNonIterableValues(mixed $input): void
{
$rule = new Min(Stub::daze());
Expand Down

0 comments on commit fe68eab

Please sign in to comment.