From 67ccd4ac88703e5b9121382ee70c2d422eaf8715 Mon Sep 17 00:00:00 2001 From: Maurizio Bonani Date: Thu, 3 Jan 2019 13:26:02 +0100 Subject: [PATCH] Initial commit --- .editorconfig | 15 ++ .gitattributes | 16 ++ .gitignore | 7 + .scrutinizer.yml | 31 +++ .styleci.yml | 1 + CONTRIBUTING.md | 32 +++ LICENSE.md | 22 ++ README.md | 100 ++++++++ composer.json | 51 ++++ phpunit.xml.dist | 28 ++ src/BigHugeThesaurusClient.php | 233 +++++++++++++++++ src/Exceptions/BigHugeThesaurusException.php | 12 + src/Exceptions/InactiveKeyException.php | 23 ++ src/Exceptions/MissingWordsException.php | 23 ++ src/Exceptions/NotFoundException.php | 21 ++ src/Exceptions/NotWhitelistedException.php | 23 ++ src/Exceptions/UsageExceededException.php | 23 ++ src/ThesaurusResponse.php | 240 +++++++++++++++++ tests/BigHugeThesaurusClientTest.php | 255 +++++++++++++++++++ tests/ThesaurusResponseTest.php | 119 +++++++++ tests/fixtures/flat.json | 2 + tests/fixtures/love.json | 1 + 22 files changed, 1278 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .scrutinizer.yml create mode 100644 .styleci.yml create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/BigHugeThesaurusClient.php create mode 100644 src/Exceptions/BigHugeThesaurusException.php create mode 100644 src/Exceptions/InactiveKeyException.php create mode 100644 src/Exceptions/MissingWordsException.php create mode 100644 src/Exceptions/NotFoundException.php create mode 100644 src/Exceptions/NotWhitelistedException.php create mode 100644 src/Exceptions/UsageExceededException.php create mode 100644 src/ThesaurusResponse.php create mode 100644 tests/BigHugeThesaurusClientTest.php create mode 100644 tests/ThesaurusResponseTest.php create mode 100644 tests/fixtures/flat.json create mode 100644 tests/fixtures/love.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9d49909 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0886945 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,16 @@ +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.editorconfig export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/.scrutinizer.yml export-ignore +/.styleci.yml export-ignore +/.travis.yml export-ignore +/PULL_REQUEST_TEMPLATE.md export-ignore +/ISSUE_TEMPLATE.md export-ignore +/phpcs.xml.dist export-ignore +/phpunit.xml.dist export-ignore +/tests export-ignore +/docs export-ignore \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7881653 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.idea +build +composer.lock +vendor +phpcs.xml +phpunit.xml +index.php \ No newline at end of file diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000..15dc0e3 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,31 @@ +build: + nodes: + analysis: + project_setup: + override: true + tests: + override: [php-scrutinizer-run] + +filter: + excluded_paths: [tests/*] + +checks: + php: + remove_extra_empty_lines: true + remove_php_closing_tag: true + remove_trailing_whitespace: true + fix_use_statements: + remove_unused: true + preserve_multiple: false + preserve_blanklines: true + order_alphabetically: true + fix_php_opening_tag: true + fix_linefeed: true + fix_line_ending: true + fix_identation_4spaces: true + fix_doc_comments: true + +tools: + external_code_coverage: + timeout: 600 + runs: 3 \ No newline at end of file diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000..b46b01d --- /dev/null +++ b/.styleci.yml @@ -0,0 +1 @@ +preset: psr2 \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3a8330e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,32 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +We accept contributions via Pull Requests on [Github](https://github.com/mettleworks/big-huge-thesaurus-client). + + +## Pull Requests + +- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - Check the code style with ``$ composer check-style`` and fix it with ``$ composer fix-style``. + +- **Add tests!** - Your patch won't be accepted if it doesn't have tests. + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. + +- **Create feature branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. + +- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. + + +## Running Tests + +``` bash +$ composer test +``` + + +**Happy coding**! diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..d775f58 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) 2019 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..822a484 --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +# BigHugetThesaurusClient + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Software License][ico-license]](LICENSE.md) +[![Total Downloads][ico-downloads]][link-downloads] + +PHP Wrapper for the [Big Huge Labs Thesaurus API](http://words.bighugelabs.com/). + +## Install + +Via Composer + +``` bash +$ composer require mettleworks/big-huge-thesaurus-client +``` + +## Usage + +``` php +$API_KEY = 'Get an api key @ https://words.bighugelabs.com/api.php'; + +$client = new Mettleworks\BigHugeThesaurusClient($API_KEY); +$response = $client->lookup('love'); +``` + +The response object is an instance of `ThesaurusResponse`, an object that wraps the original response and adds a few convenience methods. You can optionally pass an argument to each method to indicate if you want only nouns (`noun`), verbs (`verb`), adjectives (`adjective`) or adverbs (`adverb`) otherwise they will return all results combined. The signature of the methods is the following: + +```php +/** + * Get the synonyms from the response + */ +$response->getSynonyms($type = null): array + +/** + * Get the antonyms from the response + */ +public function getAntonyms($type = null): array + +/** + * Get the similar terms from the response + */ +public function getSimilarTerms($type = null): array + +/** + * Get related terms from the response + */ +public function getRelatedTerms($type = null): array + +/** + * Cast response to array (returns the original response) + */ +public function toArray(): array + +/** + * Cast response to JSON + */ +public function toJson() +``` + +The client throws specific exceptions when an error occurs. Those errors are documented on the [Big Huge Thesaurus Api Page](https://words.bighugelabs.com/api.php). + +```php +try { + $response = $client->lookup('love'); +} catch (NotFoundException $ex) { + // Not Found +} catch (UsageExceededException $ex) { + // Usage exceeded +} catch (InactiveKeyException $ex) { + // Key not active +} catch (MissingWordsException $ex) { + // No words provided +} catch (NotWhitelistedException $ex) { + // IP address blocked +} +``` + +Additionally if an error occurs outside the listed ones, the original Guzzle Exception is thrown. + +## Testing + +``` bash +$ composer test +``` + +## Contributing + +Please see [CONTRIBUTING](CONTRIBUTING.md) for details. + +## Security + +If you discover any security related issues, please email maurizio@mettle.io instead of using the issue tracker. + +## Credits + +- [Maurizio Bonani](https://github.com/mauricius) + +## License + +The MIT License (MIT). Please see [License File](LICENSE.md) for more information. \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..1bfe38a --- /dev/null +++ b/composer.json @@ -0,0 +1,51 @@ +{ + "name": "mettleworks/big-huge-thesaurus-client", + "type": "library", + "description": "PHP Client around Big Huge Thesaurus API", + "keywords": [ + "mettleworks", + "big-huge-thesaurus-client", + "big huge thesaurus" + ], + "homepage": "https://github.com/mettleworks/big-huge-thesaurus-client", + "license": "MIT", + "authors": [ + { + "name": "Maurizio Bonani", + "email": "maurizio@mettle.io", + "homepage": "https://mettle.io/", + "role": "Developer" + } + ], + "require": { + "php" : "~7.1", + "guzzlehttp/guzzle": "~6.0" + }, + "require-dev": { + "phpunit/phpunit" : ">=7.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "autoload": { + "psr-4": { + "Mettleworks\\BigHugeThesaurusClient\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Mettleworks\\BigHugeThesaurusClient\\": "tests" + } + }, + "scripts": { + "test": "phpunit", + "check-style": "phpcs src tests", + "fix-style": "phpcbf src tests" + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "config": { + "sort-packages": true + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..ec4f891 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,28 @@ + + + + + tests + + + + + src/ + + + + + + + + + \ No newline at end of file diff --git a/src/BigHugeThesaurusClient.php b/src/BigHugeThesaurusClient.php new file mode 100644 index 0000000..a4cb7e3 --- /dev/null +++ b/src/BigHugeThesaurusClient.php @@ -0,0 +1,233 @@ + InactiveKeyException::class, + MissingWordsException::REASON => MissingWordsException::class, + NotWhitelistedException::REASON => NotWhitelistedException::class, + UsageExceededException::REASON => UsageExceededException::class + ]; + + /** + * Create a new instance of the client + * + * @param string $key + */ + public function __construct(string $key) + { + $this->key = $key; + } + + /** + * Sets the client to be used for querying the API endpoints + * + * @param Client $client + * @return $this + */ + public function setHttpClient(Client $client = null) + { + if ($client === null) { + $client = new Client([ + 'base_uri' => $this->getBaseUri(), + 'http_errors' => true + ]); + } + + $this->client = $client; + + return $this; + } + + /** + * Returns either the instance of the Guzzle client that has been defined, or null + * @return Client|null + */ + public function getHttpClient() + { + return $this->client; + } + + /** + * Return the base uri of the API + * @return mixed + */ + public function getBaseUri() + { + return str_replace('{key}', $this->key, $this->base_uri); + } + + /** + * Lookup the word on Big Huge Thesaurus + * @param string $word + * @return ThesaurusResponse + * @throws NotFoundException + * @throws RemoteException + * @throws GuzzleException + * @see https://words.bighugelabs.com/api.php + */ + public function lookup(string $word) + { + try { + if (!$this->getHttpClient()) { + $this->setHttpClient(); + } + + $response = $this->client->request('GET', $word . '/json'); + + $this->rawResponse = $response->getBody()->getContents(); + + return $this->parseResponse($this->rawResponse); + } catch (ClientException $e) { + if ($e->getResponse()->getStatusCode() == 404) { + throw new NotFoundException(); + } + + throw $e; + } catch (ServerException $e) { + if ($e->getResponse()->getStatusCode() == 500 and in_array($e->getResponse()->getReasonPhrase(), array_keys($this->remoteExceptions))) { + throw new $this->remoteExceptions[$e->getResponse()->getReasonPhrase()](); + } + + throw $e; + } + } + + /** + * Get only synonyms of word + * + * @param string $word + * @throws NotFoundException + * @throws RemoteException + * @throws GuzzleException + * @return array + */ + public function synonymsOf(string $word): array + { + $response = $this->lookup($word); + + return $response->getSynonyms(); + } + + /** + * Get only antonyms of word + * + * @param string $word + * @throws NotFoundException + * @throws RemoteException + * @throws GuzzleException + * @return array + */ + public function antonymsOf(string $word): array + { + $response = $this->lookup($word); + + return $response->getAntonyms(); + } + + /** + * Get only similar terms of word + * + * @param string $word + * @throws NotFoundException + * @throws RemoteException + * @throws GuzzleException + * @return array + */ + public function similarTermsOf(string $word): array + { + $response = $this->lookup($word); + + return $response->getSimilarTerms(); + } + + /** + * Get only related terms of word + * + * @param string $word + * @throws NotFoundException + * @throws RemoteException + * @throws GuzzleException + * @return array + */ + public function relatedTermsOf(string $word): array + { + $response = $this->lookup($word); + + return $response->getRelatedTerms(); + } + + /** + * Get the raw response + * + * @return ThesaurusResponse + */ + public function getRawResponse() + { + return $this->rawResponse; + } + + /** + * Parse the response into a ThesaurusResponse + * + * @param string $response + * @return ThesaurusResponse + */ + protected function parseResponse($response) + { + $parsed = json_decode($response, true); + + return new ThesaurusResponse($parsed); + } +} diff --git a/src/Exceptions/BigHugeThesaurusException.php b/src/Exceptions/BigHugeThesaurusException.php new file mode 100644 index 0000000..02f5283 --- /dev/null +++ b/src/Exceptions/BigHugeThesaurusException.php @@ -0,0 +1,12 @@ +response = $response; + } + + /** + * Get the synonyms from the response, + * optionally filtered by type + * + * @param mixed $type + * @return array + */ + public function getSynonyms($type = null): array + { + return $this->getEntities('Synonyms', $type); + } + + /** + * Get the antonyms from the response, + * optionally filtered by type + * + * @param mixed $type + * @return array + */ + public function getAntonyms($type = null): array + { + return $this->getEntities('Antonyms', $type); + } + + /** + * Get the simila terms from the response, + * optionally filtered by type + * + * @param mixed $type + * @return array + */ + public function getSimilarTerms($type = null): array + { + return $this->getEntities('SimilarTerms', $type); + } + + /** + * Get related terms from the response, + * optionally filtered by type + * + * @param mixed $type + * @return array + */ + public function getRelatedTerms($type = null): array + { + return $this->getEntities('RelatedTerms', $type); + } + + /** + * Get entities from the response + * + * @param string $entity + * @param mixed $type + * @return array + */ + protected function getEntities($entity, $type = null): array + { + $entities = []; + + if ($nouns = $this->extractNouns()) { + $nounEntities = $this->{'extract' . $entity}($nouns); + + if ($type === 'noun') { + return $nounEntities; + } + + $entities = array_merge($entities, $nounEntities); + } + + if ($verbs = $this->extractVerbs()) { + $verbEntities = $this->{'extract' . $entity}($verbs); + + if ($type === 'verb') { + return $verbEntities; + } + + $entities = array_merge($entities, $verbEntities); + } + + if ($adjectives = $this->extractAdjectives()) { + $adjectiveEntities = $this->{'extract' . $entity}($adjectives); + + if ($type === 'adjective') { + return $adjectiveEntities; + } + + $entities = array_merge($entities, $adjectiveEntities); + } + + if ($adverbs = $this->extractAdverbs()) { + $adverbEntities = $this->{'extract' . $entity}($adverbs); + + if ($type === 'adverb') { + return $adverbEntities; + } + + $entities = array_merge($entities, $adverbEntities); + } + + return $entities; + } + + /** + * Extract only the nouns from the response + * + * @return mixed + */ + protected function extractNouns() + { + return $this->response['noun'] ?? null; + } + + /** + * Extract only the verbs from the response + * + * @return mixed + */ + protected function extractVerbs() + { + return $this->response['verb'] ?? null; + } + + /** + * Extract only the adjectives from the response + * + * @return mixed + */ + protected function extractAdjectives() + { + return $this->response['adjective'] ?? null; + } + + /** + * Extract only the adverbs from the response + * + * @return mixed + */ + protected function extractAdverbs() + { + return $this->response['adverb'] ?? null; + } + + /** + * Extract synonyms from the entry + * + * @param array $entry + * @return array + */ + protected function extractSynonyms(array $entry): array + { + return $entry['syn'] ?? []; + } + + /** + * Extract antonyms from the entry + * + * @param array $entry + * @return array + */ + protected function extractAntonyms(array $entry): array + { + return $entry['ant'] ?? []; + } + + /** + * Extract similar terms from the entry + * + * @param array $entry + * @return array + */ + protected function extractSimilarTerms(array $entry): array + { + return $entry['sim'] ?? []; + } + + /** + * Extract related terms from the entry + * + * @param array $entry + * @return array + */ + protected function extractRelatedTerms(array $entry): array + { + return $entry['rel'] ?? []; + } + + /** + * Extract user suggestions from the entry + * + * @param array $entry + * @return array + */ + protected function extractUserSuggestions(array $entry): array + { + return $entry['usr'] ?? []; + } + + /** + * Cast response to array + * + * @return array + */ + public function toArray(): array + { + return $this->response; + } + + /** + * Cast response to JSON + * + * @return string + */ + public function toJson() + { + return json_encode($this->response); + } +} diff --git a/tests/BigHugeThesaurusClientTest.php b/tests/BigHugeThesaurusClientTest.php new file mode 100644 index 0000000..c1c53d2 --- /dev/null +++ b/tests/BigHugeThesaurusClientTest.php @@ -0,0 +1,255 @@ +mockHandler = new MockHandler(); + + $this->httpClient = new Client([ + 'handler' => $this->mockHandler, + ]); + } + + /** @test */ + public function itShouldReturnTheBugHugeThesaurusApiBaseUrl() + { + $api_key = 'my_very_random_key'; + + $apiClient = $this->createClient($api_key); + + $this->assertEquals("https://words.bighugelabs.com/api/2/{$api_key}/", $apiClient->getBaseUri()); + } + + /** @test */ + public function itShouldAutomaticallySetAnInstanceOfGuzzleClientIfNotProvided() + { + $apiClient = new BigHugeThesaurusClient('123'); + $apiClient->setHttpClient(null); + + $this->assertInstanceOf(Client::class, $apiClient->getHttpClient()); + } + + /** @test */ + public function itShouldThrowASpecificExceptionIfTheProvidedWordIsNotFound() + { + $this->expectException(NotFoundException::class); + + $this->mockHandler->append($this->getClientException(404, 'Not Found')); + + $apiClient = $this->createClient('123'); + + $apiClient->lookup('love'); + } + + /** @test */ + public function itShouldThrowASpecificExceptionIfTheKeyIsEmpty() + { + $this->expectException(InactiveKeyException::class); + + $this->mockHandler->append($this->getServerException(500, InactiveKeyException::REASON)); + + $apiClient = $this->createClient(''); + + $apiClient->lookup('love'); + } + + /** @test */ + public function itShouldThrowASpecificExceptionIfTheUserExceedsTheUsage() + { + $this->expectException(UsageExceededException::class); + + $this->mockHandler->append($this->getServerException(500, UsageExceededException::REASON)); + + $apiClient = $this->createClient('123'); + + $apiClient->lookup('love'); + } + + /** @test */ + public function itShouldThrowASpecificExceptionIfTheUserSubmitsNoWords() + { + $this->expectException(MissingWordsException::class); + + $this->mockHandler->append($this->getServerException(500, MissingWordsException::REASON)); + + $apiClient = $this->createClient('123'); + + $apiClient->lookup(''); + } + + /** @test */ + public function itShouldThrowASpecificExceptionIfTheIpAddressOfTheUserIsBlocked() + { + $this->expectException(NotWhitelistedException::class); + + $this->mockHandler->append($this->getServerException(500, NotWhitelistedException::REASON)); + + $apiClient = $this->createClient('123'); + + $apiClient->lookup('love'); + } + + /** @test */ + public function itShouldThrowAGuzzleExceptionIfTheErrorIsGeneric() + { + $this->expectException(GuzzleException::class); + + $this->mockHandler->append($this->getServerException(500, 'Generic error')); + + $apiClient = $this->createClient('123'); + + $apiClient->lookup('love'); + } + + /** @test */ + public function itShouldProvideTheThesaurusResponseIfTheLookupSucceeds() + { + $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__ . '/fixtures/love.json'))); + + $apiClient = $this->createClient('123'); + + $response = $apiClient->lookup('love'); + + $this->assertInstanceOf(ThesaurusResponse::class, $response); + } + + /** @test */ + public function itShouldReturnTheRawResponseFromTheClient() + { + $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__ . '/fixtures/love.json'))); + + $apiClient = $this->createClient('123'); + + $apiClient->lookup('love'); + + $this->assertIsString($apiClient->getRawResponse()); + } + + /** @test */ + public function itShouldReturnOnlyTheSynonymsOfWord() + { + $source = file_get_contents(__DIR__ . '/fixtures/love.json'); + + $this->mockHandler->append(new Response(200, [], $source)); + + $apiClient = $this->createClient('123'); + + $synonyms = $apiClient->synonymsOf('love'); + + $decoded = json_decode($source, true); + + $this->assertIsArray($synonyms); + $this->assertEquals(array_merge($decoded['noun']['syn'], $decoded['verb']['syn']), $synonyms); + } + + /** @test */ + public function itShouldReturnOnlyTheAntonymsOfWord() + { + $source = file_get_contents(__DIR__ . '/fixtures/love.json'); + + $this->mockHandler->append(new Response(200, [], $source)); + + $apiClient = $this->createClient('123'); + + $antonyms = $apiClient->antonymsOf('love'); + + $decoded = json_decode($source, true); + + $this->assertIsArray($antonyms); + $this->assertEquals(array_merge($decoded['noun']['ant'], $decoded['verb']['ant']), $antonyms); + } + + /** @test */ + public function itShouldReturnOnlyTheSimilarTermsOfWord() + { + $source = file_get_contents(__DIR__ . '/fixtures/love.json'); + + $this->mockHandler->append(new Response(200, [], $source)); + + $apiClient = $this->createClient('123'); + + $similarTerms = $apiClient->similarTermsOf('love'); + + $this->assertIsArray($similarTerms); + $this->assertEmpty($similarTerms); + } + + /** @test */ + public function itShouldReturnOnlyTheRelatedTermsOfWord() + { + $source = file_get_contents(__DIR__ . '/fixtures/love.json'); + + $this->mockHandler->append(new Response(200, [], $source)); + + $apiClient = $this->createClient('123'); + + $relatedTerms = $apiClient->relatedTermsOf('love'); + + $this->assertIsArray($relatedTerms); + $this->assertEmpty($relatedTerms); + } + + /** + * Create the BigHugeThesaurusClient instance + * @param string $key + * @return BigHugeThesaurusClient + */ + protected function createClient(string $key) + { + $apiClient = new BigHugeThesaurusClient($key); + $apiClient->setHttpClient($this->httpClient); + + return $apiClient; + } + + /** + * Provide a Guzzle ClientException + * @param $code + * @param string $reason + * @return ClientException + */ + protected function getClientException($code, string $reason) + { + return new ClientException( + $reason, + new Request('GET', '/'), + new Response($code, [], null, '1.1', $reason) + ); + } + + /** + * Provide a Guzzle ServerException + * @param $code + * @param string $reason + * @return ServerException + */ + protected function getServerException($code, string $reason) + { + return new ServerException( + $reason, + new Request('GET', '/'), + new Response($code, [], null, '1.1', $reason) + ); + } +} diff --git a/tests/ThesaurusResponseTest.php b/tests/ThesaurusResponseTest.php new file mode 100644 index 0000000..690b0ac --- /dev/null +++ b/tests/ThesaurusResponseTest.php @@ -0,0 +1,119 @@ +assertEquals(array_merge($rawResponse['noun']['syn'], $rawResponse['verb']['syn']), $response->getSynonyms()); + } + + /** @test */ + public function itShouldReturnOnlyTheNounSynonymsFromTheResponse() + { + $rawResponse = json_decode(file_get_contents(__DIR__ . '/fixtures/love.json'), true); + + $response = new ThesaurusResponse($rawResponse); + + $this->assertEquals($rawResponse['noun']['syn'], $response->getSynonyms('noun')); + } + + /** @test */ + public function itShouldReturnOnlyTheVerbSynonymsFromTheResponse() + { + $rawResponse = json_decode(file_get_contents(__DIR__ . '/fixtures/love.json'), true); + + $response = new ThesaurusResponse($rawResponse); + + $this->assertEquals($rawResponse['verb']['syn'], $response->getSynonyms('verb')); + } + + /** @test */ + public function itShouldReturnOnlyTheAntonymsFromTheResponse() + { + $rawResponse = json_decode(file_get_contents(__DIR__ . '/fixtures/love.json'), true); + + $response = new ThesaurusResponse($rawResponse); + + $this->assertEquals(array_merge($rawResponse['noun']['ant'], $rawResponse['verb']['ant']), $response->getAntonyms()); + } + + /** @test */ + public function itShouldReturnOnlyTheNounAntonymsFromTheResponse() + { + $rawResponse = json_decode(file_get_contents(__DIR__ . '/fixtures/love.json'), true); + + $response = new ThesaurusResponse($rawResponse); + + $this->assertEquals($rawResponse['noun']['ant'], $response->getAntonyms('noun')); + } + + /** @test */ + public function itShouldReturnOnlyTheVerbAntonymsFromTheResponse() + { + $rawResponse = json_decode(file_get_contents(__DIR__ . '/fixtures/love.json'), true); + + $response = new ThesaurusResponse($rawResponse); + + $this->assertEquals($rawResponse['verb']['ant'], $response->getAntonyms('verb')); + } + + /** @test */ + public function itShouldReturnOnlyTheSimilarTermsFromTheResponse() + { + $rawResponse = json_decode(file_get_contents(__DIR__ . '/fixtures/flat.json'), true); + + $response = new ThesaurusResponse($rawResponse); + + $this->assertEquals($rawResponse['adjective']['sim'], $response->getSimilarTerms('adjective')); + } + + /** @test */ + public function itShouldReturnOnlyTheUserSuggestedTermsFromTheResponse() + { + $rawResponse = json_decode(file_get_contents(__DIR__ . '/fixtures/flat.json'), true); + + $response = new ThesaurusResponse($rawResponse); + + $this->assertEmpty($response->getRelatedTerms()); + } + + /** @test */ + public function itShouldReturnOnlyTheRelatedTermsFromTheResponse() + { + $rawResponse = json_decode(file_get_contents(__DIR__ . '/fixtures/love.json'), true); + + $response = new ThesaurusResponse($rawResponse); + + $this->assertEmpty($response->getRelatedTerms()); + } + + /** @test */ + public function itShouldReturnTheRawResponseWhenConvertingToArray() + { + $rawResponse = json_decode(file_get_contents(__DIR__ . '/fixtures/love.json'), true); + + $response = new ThesaurusResponse($rawResponse); + + $this->assertIsArray($response->toArray()); + $this->assertEquals($rawResponse, $response->toArray()); + } + + /** @test */ + public function itShouldConvertTheResponseBackToJson() + { + $rawResponse = json_decode(file_get_contents(__DIR__ . '/fixtures/love.json'), true); + + $response = new ThesaurusResponse($rawResponse); + + $this->assertJson($response->toJson()); + } +} diff --git a/tests/fixtures/flat.json b/tests/fixtures/flat.json new file mode 100644 index 0000000..0963441 --- /dev/null +++ b/tests/fixtures/flat.json @@ -0,0 +1,2 @@ + +{"adjective":{"syn":["level","plane","categoric","categorical","unconditional","prostrate","compressed","bland","flavorless","flavourless","insipid","savorless","savourless","vapid","monotone","monotonic","monotonous","two-dimensional","2-dimensional","mat","matt","matte","matted","fixed"],"ant":["contrasty","natural","sharp"],"sim":["two-dimensional","deflated","dull","even","horizontal","inactive","multidimensional","noneffervescent","planar","regressive","tasteless","thin","underdeveloped","unerect","unexciting","unmodulated","unqualified","unstimulating"]},"adverb":{"syn":["directly","straight"],"ant":["indirectly"]},"noun":{"syn":["flatcar","flatbed","flat tire","apartment","box","champaign","field","freight car","housing","living accommodations","lodging","musical notation","plain","pneumatic tire","pneumatic tyre","scene","scenery"]}} \ No newline at end of file diff --git a/tests/fixtures/love.json b/tests/fixtures/love.json new file mode 100644 index 0000000..d0529a2 --- /dev/null +++ b/tests/fixtures/love.json @@ -0,0 +1 @@ +{"noun":{"syn":["passion","beloved","dear","dearest","honey","sexual love","erotic love","lovemaking","making love","love life","concupiscence","emotion","eros","loved one","lover","object","physical attraction","score","sex","sex activity","sexual activity","sexual desire","sexual practice"],"ant":["hate"],"usr":["amour"]},"verb":{"syn":["love","enjoy","roll in the hay","make out","make love","sleep with","get laid","have sex","know","do it","be intimate","have intercourse","have it away","have it off","screw","jazz","eff","hump","lie with","bed","have a go at it","bang","get it on","bonk","copulate","couple","like","mate","pair"],"ant":["hate"]}} \ No newline at end of file