diff --git a/.gitignore b/.gitignore index 9787040..cd9e7b1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /vendor /build /.phpunit.result.cache +/.phpunit.cache tags diff --git a/src/Annotations/Validate.php b/src/Annotations/Validate.php index 3b2487f..45312b8 100644 --- a/src/Annotations/Validate.php +++ b/src/Annotations/Validate.php @@ -6,7 +6,6 @@ use Attribute; use BadMethodCallException; -use TheCodingMachine\GraphQLite\Annotations\MiddlewareAnnotationInterface; use TheCodingMachine\GraphQLite\Annotations\ParameterAnnotationInterface; use function is_string; use function ltrim; @@ -30,7 +29,7 @@ class Validate implements ParameterAnnotationInterface private $rule; /** - * @param array $values + * @param array|string $rule */ public function __construct($rule = []) { @@ -43,7 +42,7 @@ public function __construct($rule = []) $this->for = ltrim($values['for'], '$'); } } - if (! isset($values['rule'])) { + if (empty($this->rule)) { throw new BadMethodCallException('The @Validate annotation must be passed a rule. For instance: "#Validate("email")" in PHP 8+ or "@Validate(for="$email", rule="email")" in PHP 7+'); } } diff --git a/tests/Annotations/ValidateTest.php b/tests/Annotations/ValidateTest.php new file mode 100644 index 0000000..b85e0dc --- /dev/null +++ b/tests/Annotations/ValidateTest.php @@ -0,0 +1,38 @@ +assertEquals('any-rule', $validator->getRule()); + } + + public function testArrayArgument(): void + { + $validator = new Validate(['rule' => 'any-rule']); + $this->assertEquals('any-rule', $validator->getRule()); + } + + public function testArrayArgumentWithRuleAndForProperties(): void + { + $validator = new Validate([ + 'rule' => 'any-rule', + 'for' => 'any-for', + ]); + $this->assertEquals('any-rule', $validator->getRule()); + $this->assertEquals('any-for', $validator->getTarget()); + } + + public function testRuleShouldNotBeEmpty(): void + { + $this->expectException(BadMethodCallException::class); + $validator = new Validate(''); + } +} diff --git a/tests/Fixtures/App/Http/Controllers/TestController.php b/tests/Fixtures/App/Http/Controllers/TestController.php index a68f602..0b68627 100644 --- a/tests/Fixtures/App/Http/Controllers/TestController.php +++ b/tests/Fixtures/App/Http/Controllers/TestController.php @@ -55,4 +55,14 @@ public function testValidatorMultiple(string $foo): string { return 'success'; } + + /** @Query() */ + public function testValidatorForParameterPHP8( + #[Validate("required")] + string $foo, + #[Validate("sometimes")] + null|string $bar, + ): string { + return 'success'; + } } diff --git a/tests/Providers/GraphQLiteServiceProviderTest.php b/tests/Providers/GraphQLiteServiceProviderTest.php index 2c1e2a1..b8ca1f9 100644 --- a/tests/Providers/GraphQLiteServiceProviderTest.php +++ b/tests/Providers/GraphQLiteServiceProviderTest.php @@ -10,14 +10,11 @@ use TheCodingMachine\GraphQLite\Http\HttpCodeDeciderInterface; use TheCodingMachine\GraphQLite\Laravel\Listeners\CachePurger; use TheCodingMachine\GraphQLite\Schema; -use TheCodingMachine\TDBM\TDBMService; -use function json_decode; use Illuminate\Http\Request; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; use TheCodingMachine\GraphQLite\Laravel\Controllers\GraphQLiteController; use Symfony\Component\HttpFoundation\Request as SymfonyRequest; - class GraphQLiteServiceProviderTest extends TestCase { protected function getPackageProviders($app) @@ -168,6 +165,32 @@ public function testValidatorMultiple() $this->assertSame(200, $response->getStatusCode(), $response->getContent()); } + /** + * This test the 'Validate' Attribute. In older versions the 'rule' property + * of the Validate constructor was normalized but wrong value was checked. + * Now the Validate attribute should works properly if it's initialized + * with something like this: "#[Validate('some-rule')]". + */ + public function testValidatorForParameterPHP8() + { + $response = $this->json('POST', '/graphql', ['query' => '{ testValidatorForParameterPHP8(foo:"") }']); + $response->assertJson([ + 'errors' => [ + [ + 'extensions' => [ + 'argument' => 'foo', + ], + ], + ], + ]); + + $this->assertStringContainsString('The foo field is required.', $response->json('errors')[0]['message']); + $this->assertSame(400, $response->getStatusCode(), $response->getContent()); + + $response = $this->json('POST', '/graphql', ['query' => '{ testValidatorForParameterPHP8(foo:"not-empty") }']); + $this->assertSame(200, $response->getStatusCode(), $response->getContent()); + } + public function testCachePurger(): void { $cachePurger = $this->app->make(CachePurger::class);