diff --git a/src/Schema/Field/Str.php b/src/Schema/Field/Str.php index 36f848b..866d400 100644 --- a/src/Schema/Field/Str.php +++ b/src/Schema/Field/Str.php @@ -8,6 +8,7 @@ class Str extends Attribute public ?int $maxLength = null; public ?string $pattern = null; public ?string $format = null; + public ?array $enum = null; public function __construct(string $name) { @@ -21,6 +22,11 @@ public function __construct(string $name) return; } + if ($this->enum !== null && !in_array($value, $this->enum, true)) { + $enum = array_map(fn ($value) => '"' . $value . '"', $this->enum); + $fail(sprintf('must be one of %s', implode(', ', $enum))); + } + if (strlen($value) < $this->minLength) { $fail(sprintf('must be at least %d characters', $this->minLength)); } @@ -66,6 +72,13 @@ public function format(?string $format): static return $this; } + public function enum(?array $enum): static + { + $this->enum = $enum; + + return $this; + } + public function getSchema(): array { return parent::getSchema() + [ @@ -74,6 +87,7 @@ public function getSchema(): array 'maxLength' => $this->maxLength, 'pattern' => $this->pattern, 'format' => $this->format, + 'enum' => $this->enum, ]; } } diff --git a/tests/feature/StrTest.php b/tests/feature/StrTest.php index 0019549..f4f3d1c 100644 --- a/tests/feature/StrTest.php +++ b/tests/feature/StrTest.php @@ -57,4 +57,46 @@ public function test_validates_string() ]), ); } + + public function test_invalid_enum() + { + $this->api->resource( + new MockResource( + 'users', + endpoints: [Create::make()], + fields: [Str::make('type')->writable()->enum(['A', 'B'])], + ), + ); + + $this->expectException(UnprocessableEntityException::class); + + $this->api->handle( + $this->buildRequest('POST', '/users')->withParsedBody([ + 'data' => ['type' => 'users', 'attributes' => ['type' => 'C']], + ]), + ); + } + + public function test_valid_enum() + { + $this->api->resource( + new MockResource( + 'users', + endpoints: [Create::make()], + fields: [Str::make('type')->writable()->enum(['A', 'B'])], + ), + ); + + $response = $this->api->handle( + $this->buildRequest('POST', '/users')->withParsedBody([ + 'data' => ['type' => 'users', 'attributes' => ['type' => 'A']], + ]), + ); + + $this->assertJsonApiDocumentSubset( + ['data' => ['attributes' => ['type' => 'A']]], + $response->getBody(), + true, + ); + } }