From bbb0bbc5d9bd4b064d4ab59d7248a821b37c768b Mon Sep 17 00:00:00 2001 From: Carl Knowles Date: Tue, 18 Oct 2016 14:23:42 +0100 Subject: [PATCH] Base package complete with guzzle and response wrapper! --- composer.json | 12 ++- composer.lock | 2 +- phpunit.xml | 21 ++++ src/Client.php | 116 ++++++++++++++++++++ src/Exceptions/GraphQLError.php | 8 ++ src/Exceptions/GraphQLInvalidResponse.php | 8 ++ src/Exceptions/GraphQLMissingData.php | 8 ++ src/Response.php | 100 ++++++++++++++++++ tests/ClientTest.php | 122 ++++++++++++++++++++++ tests/ResponseTest.php | 120 +++++++++++++++++++++ 10 files changed, 515 insertions(+), 2 deletions(-) create mode 100644 phpunit.xml create mode 100644 src/Client.php create mode 100644 src/Exceptions/GraphQLError.php create mode 100644 src/Exceptions/GraphQLInvalidResponse.php create mode 100644 src/Exceptions/GraphQLMissingData.php create mode 100644 src/Response.php create mode 100644 tests/ClientTest.php create mode 100644 tests/ResponseTest.php diff --git a/composer.json b/composer.json index 7609513..6fb767b 100644 --- a/composer.json +++ b/composer.json @@ -22,5 +22,15 @@ "mockery/mockery": "~0.9" }, "minimum-stability": "dev", - "prefer-stable": true + "prefer-stable": true, + "autoload": { + "psr-4": { + "EUAutomation\\GraphQL\\": "src/" + } + }, + "autoload-dev":{ + "psr-4":{ + "Tests\\": "tests/" + } + } } diff --git a/composer.lock b/composer.lock index 62aa5af..b791bea 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "be7cf29ae02111a1f0b67803ecf363eb", + "hash": "cccae7288cea192fb59b802d3d3baa90", "content-hash": "d610fd5ac9bd315dfe12dc4d291d2717", "packages": [ { diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..0d83524 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,21 @@ + + + + + ./tests + + + + + ./src + + + \ No newline at end of file diff --git a/src/Client.php b/src/Client.php new file mode 100644 index 0000000..281df82 --- /dev/null +++ b/src/Client.php @@ -0,0 +1,116 @@ +url = $url; + $this->guzzle = new \GuzzleHttp\Client(); + } + + /** + * Set the URL to query against + * + * @param string $url + */ + public function setUrl($url) + { + $this->url = $url; + } + + /** + * Set an instance of guzzle to use + * + * @param \GuzzleHttp\Client $guzzle + */ + public function setGuzzle(\GuzzleHttp\Client $guzzle) + { + $this->guzzle = $guzzle; + } + + /** + * Make a GraphQL Request and get the raw guzzle response. + * + * @param string $query + * @param array $variables + * @param array $headers + * + * @return mixed|\Psr\Http\Message\ResponseInterface + */ + public function raw($query, $variables = [], $headers = []) + { + return $this->guzzle->request('POST', $this->url, [ + 'json' => [ + 'query' => $query, + 'variables' => $variables + ], + 'headers' => $headers + ]); + } + + /** + * Make a GraphQL Request and get the response body in JSON form. + * + * @param string $query + * @param array $variables + * @param array $headers + * @param bool $assoc + * + * @return mixed + * + * @throws GraphQLInvalidResponse + * @throws GraphQLMissingData + */ + public function json($query, $variables = [], $headers = [], $assoc = false) + { + $response = $this->raw($query, $variables, $headers); + + $responseJson = json_decode($response->getBody()->getContents(), $assoc); + + if ($responseJson === null) { + throw new GraphQLInvalidResponse('GraphQL did not provide a valid JSON response. Please make sure you are pointing at the correct URL.'); + } else if (!isset($responseJson->data)) { + throw new GraphQLMissingData('There was an error with the GraphQL response, no data key was found.'); + } + + return $responseJson; + } + + /** + * Make a GraphQL Request and get the guzzle response . + * + * @param string $query + * @param array $variables + * @param array $headers + * + * @return Response + * + * @throws \Exception + */ + public function response($query, $variables = [], $headers = []) + { + $response = $this->json($query, $variables, $headers); + + return new Response($response); + } +} \ No newline at end of file diff --git a/src/Exceptions/GraphQLError.php b/src/Exceptions/GraphQLError.php new file mode 100644 index 0000000..fd9fdcf --- /dev/null +++ b/src/Exceptions/GraphQLError.php @@ -0,0 +1,8 @@ +data = $response->data; + + if (isset($response->errors)) { + $this->errors = $response->errors; + } + } + + /** + * Return all the data + * + * @return mixed + */ + public function all() + { + return $this->data; + } + + /** + * Get errors returned from query + * + * @return array + */ + public function errors() + { + return $this->errors; + } + + /** + * Check if there are any errors + * + * @return bool + */ + public function hasErrors() + { + return (bool)count($this->errors()); + } + + /** + * Return the data as a JSON string + * + * @return string + */ + public function toJson() + { + return json_encode($this->data); + } + + /** + * @param string $name + * + * @return mixed + */ + public function __get($name) + { + return $this->data->{$name}; + } + + /** + * @param string $name + * @param mixed $value + */ + public function __set($name, $value) + { + $this->data->{$name} = $value; + } + + /** + * @param string $name + * + * @return mixed + */ + public function __isset($name) + { + return $this->data->{$name}; + } +} \ No newline at end of file diff --git a/tests/ClientTest.php b/tests/ClientTest.php new file mode 100644 index 0000000..4d4f280 --- /dev/null +++ b/tests/ClientTest.php @@ -0,0 +1,122 @@ +shouldReceive('getContents')->andReturn($data); + + $responseMessage = \Mockery::mock(\Psr\Http\Message\ResponseInterface::class); + $responseMessage->shouldReceive('getBody')->andReturn($stream); + + $guzzleClient = \Mockery::mock(\GuzzleHttp\Client::class); + $guzzleClient->shouldReceive('request')->andReturn($responseMessage); + + $client = new Client('SomeWebsite'); + $client->setGuzzle($guzzleClient); + $client->setUrl(''); + $response = $client->raw('')->getBody()->getContents(); + + static::assertEquals($data, $response); + } + + public function testClientReturnsJson() + { + $data = '{"data":{"One":{"id":"1","name":"One Name","translations":[{"id":"1","code":"sv","name":"Ett Namn"},' . + '{"id":"2","code":"fr","name":"Un Nom"}]},"Two":{"id":"2","name":"Two Name"}}}'; + + $stream = \Mockery::mock(\Psr\Http\Message\StreamInterface::class); + $stream->shouldReceive('getContents')->andReturn($data); + + $responseMessage = \Mockery::mock(\Psr\Http\Message\ResponseInterface::class); + $responseMessage->shouldReceive('getBody')->andReturn($stream); + + $guzzleClient = \Mockery::mock(\GuzzleHttp\Client::class); + $guzzleClient->shouldReceive('request')->andReturn($responseMessage); + + $client = new Client('SomeWebsite'); + $client->setGuzzle($guzzleClient); + $response = $client->json(''); + + static::assertEquals(json_decode($data), $response); + } + + public function testClientReturnsInvalidJsonException() + { + $data = '{"data":{"On'; + + $stream = \Mockery::mock(\Psr\Http\Message\StreamInterface::class); + $stream->shouldReceive('getContents')->andReturn($data); + + $responseMessage = \Mockery::mock(\Psr\Http\Message\ResponseInterface::class); + $responseMessage->shouldReceive('getBody')->andReturn($stream); + + $guzzleClient = \Mockery::mock(\GuzzleHttp\Client::class); + $guzzleClient->shouldReceive('request')->andReturn($responseMessage); + + $client = new Client('SomeWebsite'); + $client->setGuzzle($guzzleClient); + + static::expectException(GraphQLInvalidResponse::class); + $response = $client->json(''); + + static::assertEquals(json_decode($data), $response); + } + + public function testClientReturnsJsonMissingDataException() + { + $data = '{}'; + + $stream = \Mockery::mock(\Psr\Http\Message\StreamInterface::class); + $stream->shouldReceive('getContents')->andReturn($data); + + $responseMessage = \Mockery::mock(\Psr\Http\Message\ResponseInterface::class); + $responseMessage->shouldReceive('getBody')->andReturn($stream); + + $guzzleClient = \Mockery::mock(\GuzzleHttp\Client::class); + $guzzleClient->shouldReceive('request')->andReturn($responseMessage); + + $client = new Client('SomeWebsite'); + $client->setGuzzle($guzzleClient); + + static::expectException(GraphQLMissingData::class); + $response = $client->json(''); + + static::assertEquals(json_decode($data), $response); + } + + public function testClientReturnsResponse() + { + $data = '{"data":{"One":{"id":"1","name":"One Name","translations":[{"id":"1","code":"sv","name":"Ett Namn"},' . + '{"id":"2","code":"fr","name":"Un Nom"}]},"Two":{"id":"2","name":"Two Name"}}}'; + + $json = json_decode($data); + + $stream = \Mockery::mock(\Psr\Http\Message\StreamInterface::class); + $stream->shouldReceive('getContents')->andReturn($data); + + $responseMessage = \Mockery::mock(\Psr\Http\Message\ResponseInterface::class); + $responseMessage->shouldReceive('getBody')->andReturn($stream); + + $guzzleClient = \Mockery::mock(\GuzzleHttp\Client::class); + $guzzleClient->shouldReceive('request')->andReturn($responseMessage); + + $client = new Client('SomeWebsite'); + $client->setGuzzle($guzzleClient); + $response = $client->response(''); + + static::assertInstanceOf(Response::class, $response); + } +} \ No newline at end of file diff --git a/tests/ResponseTest.php b/tests/ResponseTest.php new file mode 100644 index 0000000..de991be --- /dev/null +++ b/tests/ResponseTest.php @@ -0,0 +1,120 @@ +data, $response->all()); + } + + public function testResponseHasErrors() + { + $data = '{"data":{"One":{"id":"1","name":"One Name","translations":[{"id":"1","code":"sv","name":"Ett Namn"},' . + '{"id":"2","code":"fr","name":"Un Nom"}]},"Two":{"id":"2","name":"Two Name"}},"errors":[{"message":"Error",' . + '"locations":[{"line":1,"column":28}]},{"message":"Error","locations":[{"line":1,"column":28}]}]}'; + + $jsonObj = json_decode($data); + + $response = new Response($jsonObj); + + static::assertTrue($response->hasErrors()); + } + + public function testResponseHasNoErrors() + { + $data = '{"data":{"One":{"id":"1","name":"One Name","translations":[{"id":"1","code":"sv","name":"Ett Namn"},' . + '{"id":"2","code":"fr","name":"Un Nom"}]},"Two":{"id":"2","name":"Two Name"}}}'; + + $jsonObj = json_decode($data); + + $response = new Response($jsonObj); + + static::assertNotTrue($response->hasErrors()); + } + + public function testResponseReturnsErrors() + { + $data = '{"data":{"One":{"id":"1","name":"One Name","translations":[{"id":"1","code":"sv","name":"Ett Namn"},' . + '{"id":"2","code":"fr","name":"Un Nom"}]},"Two":{"id":"2","name":"Two Name"}},"errors":[{"message":"Error",' . + '"locations":[{"line":1,"column":28}]},{"message":"Error","locations":[{"line":1,"column":28}]}]}'; + + $jsonObj = json_decode($data); + + $response = new Response($jsonObj); + + static::assertEquals($jsonObj->errors, $response->errors()); + } + + + public function testResponseReturnsNoErrors() + { + $data = '{"data":{"One":{"id":"1","name":"One Name","translations":[{"id":"1","code":"sv","name":"Ett Namn"},' . + '{"id":"2","code":"fr","name":"Un Nom"}]},"Two":{"id":"2","name":"Two Name"}}}'; + + $jsonObj = json_decode($data); + + $response = new Response($jsonObj); + + static::assertEquals([], $response->errors()); + } + + public function testResponseReturnsJson() + { + $data = '{"data":{"One":{"id":"1","name":"One Name","translations":[{"id":"1","code":"sv","name":"Ett Namn"},' . + '{"id":"2","code":"fr","name":"Un Nom"}]},"Two":{"id":"2","name":"Two Name"}},"errors":[{"message":"Error",' . + '"locations":[{"line":1,"column":28}]},{"message":"Error","locations":[{"line":1,"column":28}]}]}'; + + $jsonObj = json_decode($data); + + $response = new Response($jsonObj); + + static::assertEquals(json_encode($jsonObj->data), $response->toJson()); + } + + public function testCanGetValueFromResponse() + { + $data = '{"data":{"One":{"id":"1","name":"One Name","translations":[{"id":"1","code":"sv","name":"Ett Namn"},' . + '{"id":"2","code":"fr","name":"Un Nom"}]},"Two":{"id":"2","name":"Two Name"}},"errors":[{"message":"Error",' . + '"locations":[{"line":1,"column":28}]},{"message":"Error","locations":[{"line":1,"column":28}]}]}'; + + $jsonObj = json_decode($data); + + $response = new Response($jsonObj); + + static::assertEquals('sv', $response->One->translations[0]->code); + static::assertEquals('Two Name', $response->Two->name); + } + + public function testIssetReturnsCorrectly() + { + $data = '{"data":{"One":{"id":"1","name":"One Name","translations":[{"id":"1","code":"sv","name":"Ett Namn"},' . + '{"id":"2","code":"fr","name":"Un Nom"}]},"Two":{"id":"2","name":"Two Name"}},"errors":[{"message":"Error",' . + '"locations":[{"line":1,"column":28}]},{"message":"Error","locations":[{"line":1,"column":28}]}]}'; + + $jsonObj = json_decode($data); + + $response = new Response($jsonObj); + + static::assertTrue(isset($response->One->translations[0]->code)); + static::assertNotTrue(isset($response->Two->translations[0]->code)); + } +} \ No newline at end of file