From 984df7a1d088b2a18e5abcf6121327d55126ba3d Mon Sep 17 00:00:00 2001 From: Bastien Philippe Date: Sat, 27 Jan 2024 16:24:36 +0100 Subject: [PATCH] Fix validation for susbsituted backed enum in path --- src/Validation/RequestValidator.php | 4 +- tests/Fixtures/Enum.yml | 46 ++++++++++++++++++++ tests/RequestValidatorTest.php | 66 +++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 tests/Fixtures/Enum.yml diff --git a/src/Validation/RequestValidator.php b/src/Validation/RequestValidator.php index 8eb6dfe..5f78fb4 100644 --- a/src/Validation/RequestValidator.php +++ b/src/Validation/RequestValidator.php @@ -95,6 +95,8 @@ protected function validateParameters() $parameter_value = $route->parameters()[$parameter->name]; if ($parameter_value instanceof Model) { $parameter_value = $route->originalParameters()[$parameter->name]; + } elseif ($parameter_value instanceof \BackedEnum) { + $parameter_value = $route->originalParameters()[$parameter->name]; } } elseif ($parameter->in === 'query' && $this->hasQueryParam($parameter->name)) { $parameter_value = $this->getQueryParam($parameter->name); @@ -109,7 +111,7 @@ protected function validateParameters() } if ($parameter_value) { - if ($expected_parameter_schema->type && gettype($parameter_value) !== $expected_parameter_schema->type) { + if (isset($expected_parameter_schema->type) && gettype($parameter_value) !== $expected_parameter_schema->type) { $expected_type = $expected_parameter_schema->type; if ($expected_type === 'number') { diff --git a/tests/Fixtures/Enum.yml b/tests/Fixtures/Enum.yml new file mode 100644 index 0000000..a41ef23 --- /dev/null +++ b/tests/Fixtures/Enum.yml @@ -0,0 +1,46 @@ +openapi: 3.1.0 +info: + title: Enum + version: '1.0' +servers: + - url: 'http://localhost:3000' +paths: + /enum-in-path/{type}: + parameters: + - in: path + name: type + required: true + schema: + type: string + enum: + - name + - email + get: + summary: Request with enum in path + tags: [] + responses: + '204': + description: No Content + /enum-in-path-via-reference/{type}: + parameters: + - in: path + name: type + required: true + schema: + $refs: '#/components/schemas/TestEnum' + get: + summary: Request with enum in path via reference + tags: [] + responses: + '204': + description: No Content + +components: + schemas: + TestEnum: + type: string + enum: + - name + - email + + diff --git a/tests/RequestValidatorTest.php b/tests/RequestValidatorTest.php index 55207f6..685b41c 100644 --- a/tests/RequestValidatorTest.php +++ b/tests/RequestValidatorTest.php @@ -4,6 +4,8 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Http\UploadedFile; +use Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException; +use Illuminate\Routing\Middleware\SubstituteBindings; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Route; use Illuminate\Support\Str; @@ -786,8 +788,72 @@ public static function requiredReadOnlySchemaProvider(): array ], ]; } + + /** + * @dataProvider enumProvider + */ + public function test_enum_in_path(string $type, bool $isValid): void + { + Spectator::using('Enum.yml'); + + $this->withoutExceptionHandling([BackedEnumCaseNotFoundException::class]); + + Route::get('/enum-in-path/{type}', function (TestEnum $type) { + return response()->noContent(); + })->middleware([SubstituteBindings::class, Middleware::class]); + + if ($isValid) { + $this->getJson("/enum-in-path/{$type}") + ->assertValidRequest(); + } else { + $this->getJson("/enum-in-path/{$type}") + ->assertInvalidRequest(); + } + } + + /** + * @dataProvider enumProvider + */ + public function test_enum_in_path_via_reference(string $type, bool $isValid): void + { + Spectator::using('Enum.yml'); + + $this->withoutExceptionHandling([BackedEnumCaseNotFoundException::class]); + + Route::get('/enum-in-path-via-reference/{type}', function (TestEnum $type) { + return response()->noContent(); + })->middleware([SubstituteBindings::class, Middleware::class]); + + if ($isValid) { + $this->getJson("/enum-in-path-via-reference/{$type}") + ->assertValidRequest(); + } else { + $this->getJson("/enum-in-path-via-reference/{$type}") + ->assertInvalidRequest(); + } + } + + public static function enumProvider(): array + { + return [ + 'valid enum' => [ + 'name', + true, + ], + 'invalid enum' => [ + 'foo', + false, + ], + ]; + } } class TestUser extends Model { } + +enum TestEnum: string +{ + case name = 'name'; + case email = 'email'; +}