Skip to content

Commit 2181ec8

Browse files
authored
fix(validation): enum request validation (#1130)
1 parent 04143ea commit 2181ec8

File tree

12 files changed

+99
-15
lines changed

12 files changed

+99
-15
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
"phpstan/phpstan": "^2.0",
5252
"phpunit/phpunit": "^11.5.17",
5353
"rector/rector": "^2.0-rc2",
54-
"spatie/phpunit-snapshot-assertions": "^5.1.6",
54+
"spatie/phpunit-snapshot-assertions": "^5.1.8",
5555
"spaze/phpstan-disallowed-calls": "^4.0",
5656
"symplify/monorepo-builder": "^11.2",
5757
"tempest/blade": "^0.1.0",

src/Tempest/Console/src/Middleware/InvalidCommandMiddleware.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
use Tempest\Console\Initializers\Invocation;
1515
use Tempest\Console\Input\ConsoleInputArgument;
1616
use Tempest\Core\Priority;
17-
use Tempest\Validation\Rules\Enum;
1817
use Tempest\Validation\Rules\IsBoolean;
18+
use Tempest\Validation\Rules\IsEnum;
1919
use Tempest\Validation\Rules\NotEmpty;
2020
use Tempest\Validation\Rules\Numeric;
2121

@@ -69,7 +69,7 @@ private function retry(Invocation $invocation, InvalidCommandException $exceptio
6969
},
7070
validation: array_filter([
7171
$isEnum
72-
? new Enum($argument->type)
72+
? new IsEnum($argument->type)
7373
: new NotEmpty(),
7474
match ($argument->type) {
7575
'bool' => new IsBoolean(),

src/Tempest/Support/src/JavaScript/DependencyInstaller.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use Symfony\Component\Process\Process;
88
use Tempest\Console\Console;
9-
use Tempest\Validation\Rules\Enum;
9+
use Tempest\Validation\Rules\IsEnum;
1010

1111
use function Tempest\Support\Arr\wrap;
1212

@@ -31,7 +31,7 @@ public function installDependencies(string $cwd, string|array $dependencies, boo
3131
options: PackageManager::class,
3232
default: PackageManager::BUN,
3333
validation: [
34-
new Enum(PackageManager::class),
34+
new IsEnum(PackageManager::class),
3535
],
3636
);
3737

src/Tempest/Validation/src/Rules/Enum.php renamed to src/Tempest/Validation/src/Rules/IsEnum.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use UnitEnum;
1111

1212
#[Attribute]
13-
final readonly class Enum implements Rule
13+
final readonly class IsEnum implements Rule
1414
{
1515
public function __construct(
1616
private string $enum,

src/Tempest/Validation/src/Validator.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Tempest\Reflection\PropertyReflector;
1010
use Tempest\Validation\Exceptions\ValidationException;
1111
use Tempest\Validation\Rules\IsBoolean;
12+
use Tempest\Validation\Rules\IsEnum;
1213
use Tempest\Validation\Rules\IsFloat;
1314
use Tempest\Validation\Rules\IsInteger;
1415
use Tempest\Validation\Rules\IsString;
@@ -73,7 +74,7 @@ public function validateValuesForClass(ClassReflector|string $class, ?array $val
7374
continue;
7475
}
7576

76-
if ($property->getType()->isClass()) {
77+
if ($property->getType()->isClass() && ! $property->getType()->isEnum()) {
7778
$failingRules = [
7879
...$failingRules,
7980
...$this->validateValuesForClass(
@@ -105,6 +106,10 @@ public function validateValueForProperty(PropertyReflector $property, mixed $val
105106
$rules[] = new NotNull();
106107
}
107108

109+
if ($property->getType()->isEnum()) {
110+
$rules[] = new IsEnum($property->getType()->getName());
111+
}
112+
108113
return $this->validateValue($value, $rules);
109114
}
110115

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Tempest\Validation\Tests\Fixtures;
4+
5+
enum EnumForProp: string
6+
{
7+
case FOO = 'foo';
8+
case BAR = 'bar';
9+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tempest\Validation\Tests\Fixtures;
6+
7+
final class ObjectWithEnumProp
8+
{
9+
public EnumForProp $prop;
10+
}

src/Tempest/Validation/tests/Rules/EnumTest.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace Tempest\Validation\Tests\Rules;
66

77
use PHPUnit\Framework\TestCase;
8-
use Tempest\Validation\Rules\Enum;
8+
use Tempest\Validation\Rules\IsEnum;
99
use Tempest\Validation\Tests\Rules\Fixtures\SomeBackedEnum;
1010
use Tempest\Validation\Tests\Rules\Fixtures\SomeEnum;
1111
use UnexpectedValueException;
@@ -17,7 +17,7 @@ final class EnumTest extends TestCase
1717
{
1818
public function test_validating_enums(): void
1919
{
20-
$rule = new Enum(SomeEnum::class);
20+
$rule = new IsEnum(SomeEnum::class);
2121

2222
$this->assertSame(
2323
sprintf(
@@ -35,7 +35,7 @@ public function test_validating_enums(): void
3535

3636
public function test_validating_backed_enums(): void
3737
{
38-
$rule = new Enum(SomeBackedEnum::class);
38+
$rule = new IsEnum(SomeBackedEnum::class);
3939

4040
$this->assertSame(
4141
sprintf(
@@ -60,34 +60,34 @@ public function test_enum_has_to_exist(): void
6060
),
6161
));
6262

63-
new Enum('Bob');
63+
new IsEnum('Bob');
6464
}
6565

6666
public function test_validating_only_enums(): void
6767
{
68-
$rule = new Enum(SomeEnum::class);
68+
$rule = new IsEnum(SomeEnum::class);
6969
$this->assertTrue($rule->only(SomeEnum::VALUE_1)->isValid('VALUE_1'));
7070
$this->assertFalse($rule->only(SomeEnum::VALUE_2)->isValid('VALUE_1'));
7171
}
7272

7373
public function test_validating_except_enums(): void
7474
{
75-
$rule = new Enum(SomeEnum::class);
75+
$rule = new IsEnum(SomeEnum::class);
7676
$this->assertTrue($rule->except(SomeEnum::VALUE_2)->isValid('VALUE_1'));
7777
$this->assertFalse($rule->except(SomeEnum::VALUE_1)->isValid('VALUE_1'));
7878
}
7979

8080
public function test_validating_only_backed_enums(): void
8181
{
82-
$rule = new Enum(SomeBackedEnum::class);
82+
$rule = new IsEnum(SomeBackedEnum::class);
8383
$this->assertTrue($rule->only(SomeBackedEnum::Test, SomeBackedEnum::Test2)->isValid('one'));
8484
$this->assertTrue($rule->only(SomeBackedEnum::Test)->only(SomeBackedEnum::Test2)->isValid('one'));
8585
$this->assertFalse($rule->only(SomeBackedEnum::Test2)->isValid('one'));
8686
}
8787

8888
public function test_validating_except_backed_enums(): void
8989
{
90-
$rule = new Enum(SomeBackedEnum::class);
90+
$rule = new IsEnum(SomeBackedEnum::class);
9191
$this->assertTrue($rule->except(SomeBackedEnum::Test2)->isValid('one'));
9292
$this->assertFalse($rule->except(SomeBackedEnum::Test)->isValid('one'));
9393
}

src/Tempest/Validation/tests/ValidatorTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
use Tempest\Validation\Exceptions\ValidationException;
1010
use Tempest\Validation\Rules\Email;
1111
use Tempest\Validation\Rules\IsBoolean;
12+
use Tempest\Validation\Rules\IsEnum;
1213
use Tempest\Validation\Rules\IsFloat;
1314
use Tempest\Validation\Rules\IsInteger;
1415
use Tempest\Validation\Rules\IsString;
1516
use Tempest\Validation\Rules\NotNull;
1617
use Tempest\Validation\Tests\Fixtures\ObjectToBeValidated;
1718
use Tempest\Validation\Tests\Fixtures\ObjectWithBoolProp;
19+
use Tempest\Validation\Tests\Fixtures\ObjectWithEnumProp;
1820
use Tempest\Validation\Tests\Fixtures\ObjectWithFloatProp;
1921
use Tempest\Validation\Tests\Fixtures\ObjectWithIntProp;
2022
use Tempest\Validation\Tests\Fixtures\ObjectWithObjectProperty;
@@ -206,6 +208,14 @@ public function test_validation_infers_bool_rule_from_property_type(): void
206208
$this->assertInstanceOf(IsBoolean::class, $failingRules['prop'][0]);
207209
}
208210

211+
public function test_validation_infers_enum_rule_from_property_type(): void
212+
{
213+
$failingRules = new Validator()->validateValuesForClass(ObjectWithEnumProp::class, ['prop' => 'a']);
214+
215+
$this->assertCount(1, $failingRules['prop']);
216+
$this->assertInstanceOf(IsEnum::class, $failingRules['prop'][0]);
217+
}
218+
209219
public function test_validation_infers_not_null_from_scalar_property_type(): void
210220
{
211221
$failingRules = new Validator()->validateValuesForClass(ObjectWithStringProperty::class, ['prop' => null]);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Tests\Tempest\Integration\Route\Fixtures;
4+
5+
enum EnumForRequest: string
6+
{
7+
case FOO = 'foo';
8+
case BAR = 'bar';
9+
}

0 commit comments

Comments
 (0)