From 9b0cfdbf115554993a26954a64ce9fd17a143ed4 Mon Sep 17 00:00:00 2001 From: Adrien Crivelli Date: Thu, 28 Sep 2023 17:33:38 +0800 Subject: [PATCH] Not found entity will throw a `UserError`, not an `Error` This is because the error category "graphql" is reserved for errors produced by query parsing or validation. We should never have used it. So now the error will be of category "user". And it becomes easier to difference between broken GraphQL syntax and merley invalid values. --- src/Definition/EntityID.php | 4 ++-- tests/Definition/EntityIDTypeTest.php | 11 ++++++++--- tests/InputTypesTest.php | 3 ++- tests/OutputTypesTest.php | 15 ++++++++++----- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Definition/EntityID.php b/src/Definition/EntityID.php index eead2bd..27787ac 100644 --- a/src/Definition/EntityID.php +++ b/src/Definition/EntityID.php @@ -5,7 +5,7 @@ namespace GraphQL\Doctrine\Definition; use Doctrine\ORM\EntityManager; -use GraphQL\Error\Error; +use GraphQL\Error\UserError; /** * A object used to fetch the entity from DB on demand. @@ -47,7 +47,7 @@ public function getEntity(): object { $entity = $this->entityManager->getRepository($this->className)->find($this->id); if (!$entity) { - throw new Error('Entity not found for class `' . $this->className . '` and ID `' . $this->id . '`.'); + throw new UserError('Entity not found for class `' . $this->className . '` and ID `' . $this->id . '`.'); } return $entity; diff --git a/tests/Definition/EntityIDTypeTest.php b/tests/Definition/EntityIDTypeTest.php index b4f3e11..8d15119 100644 --- a/tests/Definition/EntityIDTypeTest.php +++ b/tests/Definition/EntityIDTypeTest.php @@ -6,6 +6,7 @@ use GraphQL\Doctrine\Definition\EntityIDType; use GraphQL\Error\Error; +use GraphQL\Error\UserError; use GraphQL\Language\AST\BooleanValueNode; use GraphQL\Language\AST\StringValueNode; use GraphQLTests\Doctrine\Blog\Model\User; @@ -72,15 +73,19 @@ public function testCanGetEntityFromRepositoryWhenReadingLiteral(): void public function testNonExistingEntityThrowErrorWhenReadingLiteral(): void { - $this->expectExceptionMessage('Entity not found for class `GraphQLTests\Doctrine\Blog\Model\User` and ID `non-existing-id`'); $ast = new StringValueNode(['value' => 'non-existing-id']); - $this->type->parseLiteral($ast)->getEntity(); + $value = $this->type->parseLiteral($ast); + + $this->expectException(UserError::class); + $this->expectExceptionMessage('Entity not found for class `GraphQLTests\Doctrine\Blog\Model\User` and ID `non-existing-id`'); + $value->getEntity(); } public function testWillThrowIfParsingInvalidLiteralValue(): void { - $this->expectException(Error::class); $ast = new BooleanValueNode(['value' => false]); + + $this->expectException(Error::class); $this->type->parseLiteral($ast); } diff --git a/tests/InputTypesTest.php b/tests/InputTypesTest.php index 35da3da..aa0ae6c 100644 --- a/tests/InputTypesTest.php +++ b/tests/InputTypesTest.php @@ -49,8 +49,9 @@ public function testNamespaceSupportInput(): void public function testInputWithoutTypeMustThrow(): void { - $this->expectExceptionMessage('Could not find type for parameter `$bar` for method `GraphQLTests\Doctrine\Blog\Model\Special\NoTypeInput::setFoo()`. Either type hint the parameter, or specify the type with `#[API\Input]` attribute.'); $type = $this->types->getInput(Blog\Model\Special\NoTypeInput::class); + + $this->expectExceptionMessage('Could not find type for parameter `$bar` for method `GraphQLTests\Doctrine\Blog\Model\Special\NoTypeInput::setFoo()`. Either type hint the parameter, or specify the type with `#[API\Input]` attribute.'); $type->getFields(); } } diff --git a/tests/OutputTypesTest.php b/tests/OutputTypesTest.php index 63c8902..a882cca 100644 --- a/tests/OutputTypesTest.php +++ b/tests/OutputTypesTest.php @@ -63,15 +63,17 @@ public function testNamespaceSupportOutput(): void public function testFieldWithoutTypeMustThrow(): void { - $this->expectExceptionMessage('Could not find type for method `GraphQLTests\Doctrine\Blog\Model\Special\NoType::getWithoutTypeHint()`. Either type hint the return value, or specify the type with `#[API\Field]` attribute.'); $type = $this->types->getOutput(Blog\Model\Special\NoType::class); + + $this->expectExceptionMessage('Could not find type for method `GraphQLTests\Doctrine\Blog\Model\Special\NoType::getWithoutTypeHint()`. Either type hint the return value, or specify the type with `#[API\Field]` attribute.'); $type->getFields(); } public function testFieldReturningCollectionWithoutTypeMustThrow(): void { - $this->expectExceptionMessage('The method `GraphQLTests\Doctrine\Blog\Model\Special\NoTypeCollection::getFoos()` is type hinted with a return type of `Doctrine\Common\Collections\Collection`, but the entity contained in that collection could not be automatically detected. Either fix the type hint, fix the doctrine mapping, or specify the type with `#[API\Field]` attribute.'); $type = $this->types->getOutput(Blog\Model\Special\NoTypeCollection::class); + + $this->expectExceptionMessage('The method `GraphQLTests\Doctrine\Blog\Model\Special\NoTypeCollection::getFoos()` is type hinted with a return type of `Doctrine\Common\Collections\Collection`, but the entity contained in that collection could not be automatically detected. Either fix the type hint, fix the doctrine mapping, or specify the type with `#[API\Field]` attribute.'); $type->getFields(); } @@ -83,22 +85,25 @@ public function testCannotGetInvalidType(): void public function testArgumentWithoutTypeMustThrow(): void { - $this->expectExceptionMessage('Could not find type for parameter `$bar` for method `GraphQLTests\Doctrine\Blog\Model\Special\NoTypeArgument::getFoo()`. Either type hint the parameter, or specify the type with `#[API\Argument]` attribute.'); $type = $this->types->getOutput(Blog\Model\Special\NoTypeArgument::class); + + $this->expectExceptionMessage('Could not find type for parameter `$bar` for method `GraphQLTests\Doctrine\Blog\Model\Special\NoTypeArgument::getFoo()`. Either type hint the parameter, or specify the type with `#[API\Argument]` attribute.'); $type->getFields(); } public function testFieldWithArrayArgumentMustThrow(): void { - $this->expectExceptionMessage('The parameter `$arg1` on method `GraphQLTests\Doctrine\Blog\Model\Special\ArrayArgument::getWithParams()` is type hinted as `array` and is not overridden via `#[API\Argument]` attribute. Either change the type hint or specify the type with `#[API\Argument]` attribute.'); $type = $this->types->getOutput(Blog\Model\Special\ArrayArgument::class); + + $this->expectExceptionMessage('The parameter `$arg1` on method `GraphQLTests\Doctrine\Blog\Model\Special\ArrayArgument::getWithParams()` is type hinted as `array` and is not overridden via `#[API\Argument]` attribute. Either change the type hint or specify the type with `#[API\Argument]` attribute.'); $type->getFields(); } public function testFieldWithObjectTypeArgumentMustThrow(): void { - $this->expectExceptionMessage('Type for parameter `$user` for method `GraphQLTests\Doctrine\Blog\Model\Special\ObjectTypeArgument::getWithParams()` must be an instance of `GraphQL\Type\Definition\InputType`, but was `GraphQL\Type\Definition\ObjectType`. Use `#[API\Argument]` attribute to specify a custom InputType.'); $type = $this->types->getOutput(Blog\Model\Special\ObjectTypeArgument::class); + + $this->expectExceptionMessage('Type for parameter `$user` for method `GraphQLTests\Doctrine\Blog\Model\Special\ObjectTypeArgument::getWithParams()` must be an instance of `GraphQL\Type\Definition\InputType`, but was `GraphQL\Type\Definition\ObjectType`. Use `#[API\Argument]` attribute to specify a custom InputType.'); $type->getFields(); }