Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/Validators/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,18 @@ public function evaluate(mixed $input): Result
private function getPropertyValue(object $object, string $propertyName): mixed
{
$reflection = new ReflectionObject($object);
$value = null;
while ($reflection instanceof ReflectionClass) {
if ($reflection->hasProperty($propertyName)) {
$property = $reflection->getProperty($propertyName);

return $property->isInitialized($object) ? $property->getValue($object) : null;
$value = $property->isInitialized($object) ? $property->getValue($object) : null;
break;
}

$reflection = $reflection->getParentClass();
}

return null;
return $value;
}
}
8 changes: 6 additions & 2 deletions tests/src/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

namespace Respect\Validation\Test;

use ArrayAccess;
use ArrayObject;
use PHPUnit\Framework\TestCase as PHPUnitTestCase;
use Respect\Validation\Test\Stubs\WithProperties;
use Respect\Validation\Test\Stubs\WithStaticProperties;
Expand Down Expand Up @@ -194,21 +196,23 @@ public static function providerForNonResourceType(): DataProvider
return self::providerForAnyValues()->without('resourceType');
}

/** @return array<string, array{string|int, array<mixed>}> */
/** @return array<string, array{string|int, array<mixed>|ArrayAccess<int, mixed>}> */
public static function providerForArrayWithMissingKeys(): array
{
return [
'missing key on an ArrayAccess object' => [1, new ArrayObject([])],
'integer key, non-empty input' => [0, [1 => true, 2 => true]],
'string key, non-empty input' => ['foo', ['bar' => true, 'baz' => true]],
'integer key, empty input' => [0, []],
'string key, empty input' => ['foo', []],
];
}

/** @return array<string, array{string|int, array<mixed>}> */
/** @return array<string, array{string|int, array<mixed>|ArrayAccess<int, mixed>}> */
public static function providerForArrayWithExistingKeys(): array
{
return [
'key on an ArrayAccess object' => [1, new ArrayObject([1 => true])],
'integer key with a single value array' => [1, [1 => true]],
'integer key with a multiple value array' => [2, [1 => true, 2 => true]],
'string key with a single value array' => ['foo', ['foo' => true, 'bar' => true]],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

namespace Respect\Validation;

use InvalidArgumentException;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DoesNotPerformAssertions;
use PHPUnit\Framework\Attributes\Test;
Expand All @@ -23,10 +24,11 @@
use Respect\Validation\Test\TestCase;
use Respect\Validation\Test\Validators\Stub;

use function sprintf;
use function uniqid;

#[CoversClass(ValidatorBuilder::class)]
final class ValidatorTest extends TestCase
final class ValidatorBuilderTest extends TestCase
{
#[Test]
public function invalidRuleClassShouldThrowComponentException(): void
Expand Down Expand Up @@ -165,4 +167,26 @@ public function itShouldEvaluateAndReturnResultWhenSingleFailingRuleIsAdded(): v

self::assertFalse($result->hasPassed);
}

#[Test]
public function itShouldThrowCustomExceptionWhenPassedToAssertMethod(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Custom exception message');

ValidatorBuilder::init(Stub::fail(1))
->assert('whatever', new InvalidArgumentException('Custom exception message'));
}

#[Test]
public function itShouldThrowCustomExceptionWhenCallableUsedInAssertMethod(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Got: "whatever"');

ValidatorBuilder::init(Stub::fail(1))
->assert('whatever', static fn($e) => new InvalidArgumentException(
sprintf('Got: %s', $e->getMessage()),
));
}
}
9 changes: 5 additions & 4 deletions tests/unit/Validators/KeyExistsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

namespace Respect\Validation\Validators;

use ArrayAccess;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
Expand All @@ -27,20 +28,20 @@ public function itShouldAlwaysInvalidateNonArrayValues(mixed $input): void
self::assertInvalidInput($validator, $input);
}

/** @param array<mixed> $input */
/** @param array<mixed>|ArrayAccess<int|string, mixed> $input */
#[Test]
#[DataProvider('providerForArrayWithMissingKeys')]
public function itShouldInvalidateMissingKeys(int|string $key, array $input): void
public function itShouldInvalidateMissingKeys(int|string $key, array|ArrayAccess $input): void
{
$validator = new KeyExists($key);

self::assertInvalidInput($validator, $input);
}

/** @param array<mixed> $input */
/** @param array<mixed>|ArrayAccess<int|string, mixed> $input */
#[Test]
#[DataProvider('providerForArrayWithExistingKeys')]
public function itShouldValidateExistingKeys(int|string $key, array $input): void
public function itShouldValidateExistingKeys(int|string $key, array|ArrayAccess $input): void
{
$validator = new KeyExists($key);

Expand Down
9 changes: 5 additions & 4 deletions tests/unit/Validators/KeyOptionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

namespace Respect\Validation\Validators;

use ArrayAccess;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
Expand All @@ -30,20 +31,20 @@ public function itShouldAlwaysValidateNonArrayValues(mixed $input): void
self::assertValidInput($validator, $input);
}

/** @param array<mixed> $input */
/** @param array<mixed>|ArrayAccess<int|string, mixed> $input */
#[Test]
#[DataProvider('providerForArrayWithMissingKeys')]
public function itShouldAlwaysValidateMissingKeys(int|string $key, array $input): void
public function itShouldAlwaysValidateMissingKeys(int|string $key, array|ArrayAccess $input): void
{
$validator = new KeyOptional($key, Stub::daze());

self::assertValidInput($validator, $input);
}

/** @param array<mixed> $input */
/** @param array<mixed>|ArrayAccess<int|string, mixed> $input */
#[Test]
#[DataProvider('providerForArrayWithExistingKeys')]
public function itShouldValidateExistingKeysWithWrappedRule(int|string $key, array $input): void
public function itShouldValidateExistingKeysWithWrappedRule(int|string $key, array|ArrayAccess $input): void
{
$wrapped = Stub::pass(1);

Expand Down
9 changes: 5 additions & 4 deletions tests/unit/Validators/KeyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace Respect\Validation\Validators;

use ArrayAccess;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
Expand All @@ -33,20 +34,20 @@ public function itShouldAlwaysInvalidateNonArrayValues(mixed $input): void
self::assertInvalidInput($validator, $input);
}

/** @param array<mixed> $input */
/** @param array<mixed>|ArrayAccess<int|string, mixed> $input */
#[Test]
#[DataProvider('providerForArrayWithMissingKeys')]
public function itShouldInvalidateMissingKeys(int|string $key, array $input): void
public function itShouldInvalidateMissingKeys(int|string $key, array|ArrayAccess $input): void
{
$validator = new Key($key, Stub::daze());

self::assertInvalidInput($validator, $input);
}

/** @param array<mixed> $input */
/** @param array<mixed>|ArrayAccess<int|string, mixed> $input */
#[Test]
#[DataProvider('providerForArrayWithExistingKeys')]
public function itShouldValidateExistingKeysWithWrappedRule(int|string $key, array $input): void
public function itShouldValidateExistingKeysWithWrappedRule(int|string $key, array|ArrayAccess $input): void
{
$wrapped = Stub::pass(1);

Expand Down