diff --git a/src/Controller.php b/src/Controller.php index c4008769b..e677b39dd 100644 --- a/src/Controller.php +++ b/src/Controller.php @@ -7,6 +7,8 @@ use SilverStripe\Control\HTTPResponse; use SilverStripe\Core\Injector\Injector; use SilverStripe\Core\Config\Config; +use SilverStripe\Control\Director; +use Exception; class Controller extends BaseController { @@ -37,9 +39,25 @@ public function index(HTTPRequest $request) } $manager = $this->getManager(); - $response = $manager->query($query, $variables); - return (new HTTPResponse(json_encode($response))) + try { + $result = $manager->query($query, $variables); + } catch (Exception $exception) { + $error = ['message' => $exception->getMessage()]; + + if(Director::isDev()) { + $error['code'] = $exception->getCode(); + $error['file'] = $exception->getFile(); + $error['line'] = $exception->getLine(); + $error['trace'] = $exception->getTrace(); + } + + $result = [ + 'errors' => [$error] + ]; + } + + return (new HTTPResponse(json_encode($result))) ->addHeader('Content-Type', 'application/json'); } diff --git a/tests/ControllerTest.php b/tests/ControllerTest.php index 4d6c0079f..91eb9b6a9 100644 --- a/tests/ControllerTest.php +++ b/tests/ControllerTest.php @@ -9,7 +9,10 @@ use Chillu\GraphQL\Tests\Fake\TypeCreatorFake; use Chillu\GraphQL\Tests\Fake\QueryCreatorFake; use SilverStripe\Core\Config\Config; +use GraphQL\Schema; +use GraphQL\Type\Definition\ObjectType; use ReflectionClass; +use Exception; class ControllerTest extends SapphireTest { @@ -43,6 +46,62 @@ public function testGetGetManagerPopulatesFromConfig() ); } + public function testIndexWithException() + { + Config::inst()->update('SilverStripe\\Control\\Director', 'environment_type', 'live'); + + $controller = new Controller(); + $managerMock = $this->getMockBuilder(Schema::class) + ->setMethods(['query']) + ->setConstructorArgs([ + ['query' => new ObjectType([ + 'name' => 'Query', + 'fields' => [] + ])] + ]) + ->getMock(); + + $managerMock->method('query') + ->will($this->throwException(new Exception('Failed'))); + + $controller->setManager($managerMock); + $response = $controller->index(new HTTPRequest('GET', '')); + $this->assertFalse($response->isError()); + $responseObj = json_decode($response->getBody(), true); + $this->assertNotNull($responseObj); + $this->assertArrayHasKey('errors', $responseObj); + $this->assertEquals('Failed', $responseObj['errors'][0]['message']); + $this->assertArrayNotHasKey('trace', $responseObj['errors'][0]); + } + + public function testIndexWithExceptionIncludesTraceInDevMode() + { + Config::inst()->update('SilverStripe\\Control\\Director', 'environment_type', 'dev'); + + $controller = new Controller(); + $managerMock = $this->getMockBuilder(Schema::class) + ->setMethods(['query']) + ->setConstructorArgs([ + ['query' => new ObjectType([ + 'name' => 'Query', + 'fields' => [] + ])] + ]) + ->getMock(); + + $managerMock->method('query') + ->will($this->throwException(new Exception('Failed'))); + + $controller->setManager($managerMock); + $response = $controller->index(new HTTPRequest('GET', '')); + $this->assertFalse($response->isError()); + $responseObj = json_decode($response->getBody(), true); + $this->assertNotNull($responseObj); + $this->assertArrayHasKey('errors', $responseObj); + $this->assertEquals('Failed', $responseObj['errors'][0]['message']); + $this->assertArrayHasKey('trace', $responseObj['errors'][0]); + } + protected function getType(Manager $manager) { return (new TypeCreatorFake($manager))->toType(); diff --git a/tests/Resolver/DataObjectLowerCamelResolverTest.php b/tests/Resolver/DataObjectLowerCamelResolverTest.php deleted file mode 100644 index 0968448f0..000000000 --- a/tests/Resolver/DataObjectLowerCamelResolverTest.php +++ /dev/null @@ -1,56 +0,0 @@ - 99 - ]); - $resolver = new DataObjectLowerCamelResolver(); - $info = new ResolveInfo([ - 'fieldName' => 'ID' - ]); - $this->assertEquals(99, $resolver->resolve($fake, [], [], $info)); - } - - public function testResolvesDifferentCasing() - { - $fake = new DataObjectFake([ - 'ID' => 99 - ]); - $resolver = new DataObjectLowerCamelResolver(); - $info = new ResolveInfo([ - 'fieldName' => 'id' // lowercase - ]); - $this->assertEquals(99, $resolver->resolve($fake, [], [], $info)); - } - - public function testResolvesCustomGetter() - { - $fake = new DataObjectFake([]); - $resolver = new DataObjectLowerCamelResolver(); - $info = new ResolveInfo([ - 'fieldName' => 'customGetter' - ]); - $this->assertEquals('customGetterValue', $resolver->resolve($fake, [], [], $info)); - } - - public function testResolvesMethod() - { - $fake = new DataObjectFake([]); - $resolver = new DataObjectLowerCamelResolver(); - $info = new ResolveInfo([ - 'fieldName' => 'customMethod' - ]); - $this->assertEquals('customMethodValue', $resolver->resolve($fake, [], [], $info)); - } -}