diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c43e68f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,21 @@ +dist: xenial +language: php + +matrix: + fast_finish: true + include: + - php: 7.1 + - php: 7.2 + - php: 7.3 + +cache: + directories: + - $HOME/.composer/cache + +before_install: + - travis_retry composer self-update + +install: + - travis_retry composer update --prefer-dist --no-interaction --prefer-stable --no-suggest + +script: vendor/bin/phpunit diff --git a/README.md b/README.md index ee044da..2bd562a 100644 --- a/README.md +++ b/README.md @@ -24,20 +24,20 @@ Note: for Laravel 4 use version `0.3.0` Register the service provider. Inside your `app.php` config file add: -``` -'providers' => array( +```php +'providers' => [ ... 'Lodge\Postcode\PostcodeServiceProvider', -) +] ``` A facade is also provided, so in order to register it add the following to your `app.php` config file: -``` -'aliases' => array( +```php +'aliases' => [ ... 'Postcode' => 'Lodge\Postcode\Facades\Postcode', -); +]; ``` Publish the configuration file. @@ -51,85 +51,124 @@ Set your Google API key inside `config/postcode.php` file. From within your controller you can call: -``` - $postcode = Postcode::lookup('SW3 4SZ'); - - print_r($postcode); - - // Outputs - array( - 'postcode' => 'SW34SZ', - 'street_number' => '', - 'street' => '', - 'sublocality' => '', - 'town' => 'London', - 'county' => 'Greater London', - 'country' => 'United Kingdom', - 'latitude' => 51.489117499999999, - 'longitude' => -0.1579016 - ); +```php +$address = Postcode::lookup('SW3 4SZ'); + +// Usage +$address->getPostcode(); +$address->getStreetNumber(); +$address->getStreet(); +$address->getTown(); // -> London +$address->getCounty(); // -> Greater London +$address->getCountry(); // -> United Kingdom +$address->getCoordinates()->getLatitude(); // -> 51.489117499999999 +$address->getCoordinates()->getLongitude(); // -> -0.1579016 + +// $address->toArray(); +// Outputs +[ + 'postcode' => 'SW34SZ', + 'street_number' => '', + 'street' => '', + 'sublocality' => '', + 'town' => 'London', + 'county' => 'Greater London', + 'country' => 'United Kingdom', + 'latitude' => 51.489117499999999, + 'longitude' => -0.1579016 +] ``` #### Get the Latitude and Longitude of an address -``` - $coordinates = Postcode::getCoordinates($address); - - print_r($coordinates); +```php +$coordinates = Postcode::getCoordinates($address); - // Outputs - array( - 'latitude' => 1.521231 - 'longitude' => -23.012123 - ) +// Usage +$coordinates->getLatitude(); +$coordinates->getLongitude(); +// Output +// 51.489117499999999 +// -0.1579016 ``` ## Usage outside of Laravel -``` - // First of all you need to instantiate the class - // And assuming that you have required the composer - // autoload.php file - require 'vendor/autoload.php'; - - $googleApiKey = 'your-google-api-key'; - $postcode = new Lodge\Postcode\Postcode($googleApiKey); - $results = $postcode->lookup('SW3 4SZ'); - - print_r($results); - - // Outputs - array( - 'postcode' => 'SW34SZ', - 'street_number' => '', - 'street' => '', - 'sublocality' => '', - 'town' => 'London', - 'county' => 'Greater London', - 'country' => 'United Kingdom', - 'latitude' => 51.489117499999999, - 'longitude' => -0.1579016 - ) +```php +// First of all you need to instantiate the class +// And assuming that you have required the composer +// autoload.php file +require 'vendor/autoload.php'; + +$googleApiKey = 'your-google-api-key'; +$postcode = new Lodge\Postcode\Postcode($googleApiKey); +$address = $postcode->lookup('SW3 4SZ'); + +// Usage +$address->getPostcode(); +$address->getStreetNumber(); +$address->getStreet(); +$address->getTown(); // -> London +$address->getCounty(); // -> Greater London +$address->getCountry(); // -> United Kingdom +$address->getCoordinates()->getLatitude(); // -> 51.489117499999999 +$address->getCoordinates()->getLongitude(); // -> -0.1579016 + +// $address->toArray(); +// Outputs +[ + 'postcode' => 'SW34SZ', + 'street_number' => '', + 'street' => '', + 'sublocality' => '', + 'town' => 'London', + 'county' => 'Greater London', + 'country' => 'United Kingdom', + 'latitude' => 51.489117499999999, + 'longitude' => -0.1579016 +] ``` If you need to get just the latitude and longitude for an address you can use: -``` - $googleApiKey = 'your-google-api-key'; - $postcode = new Lodge\Postcode\Postcode($googleApiKey); - $results = $postcode->getCoordinates('SW3 4SZ'); +```php +$googleApiKey = 'your-google-api-key'; +$postcode = new Lodge\Postcode\Postcode(new Lodge\Postocde\Gateways\GoogleApi($googleApiKey)); +$coordinates = $postcode->getCoordinates('SW3 4SZ'); + +// Usage +$coordinates->getLatitude(); +$coordinates->getLongitude(); - print_r($results); +// Output +// 51.489117499999999 +// -0.1579016 +``` - // Outputs - array( - 'latitude' => 51.489117499999999 - 'longitude' => -0.1579016 - ) +## Upgrade from 0.4 to 0.5 +* Wrap your calls to `->getCoordinates()` and `->lookup()` in a try catch block +```php +try { + $address = Postcode::getCoordinates($address) +} catch (AddressNotFoundException $e) { + // do something +} +``` +* The return type for `->getCoordinates()` is now an instance of `Lodge\Postcode\Coordinates` instead of an `array` +* The return type for `->lookup()` is now an instance of `Lodge\Postcode\Address` instead of an `array` +* If you are manually creating a new instance of `Lodge\Postcode\Postcode` then you will need to inject an instance of `GoogleApi` +```php +$postcode = new Lodge\Postcode\Postcode(new Lodge\Postocde\Gateways\GoogleApi($googleApiKey)); ``` ## Changelog +* **Version 0.5** + * This version introduces breaking changes + * Minimum supported PHP version is now 7.1 + * Use an object instead of returning an array + * Add a gateway interface, so that we can connect to multiple geocode backends + * Throw exceptions when an address is not found * **Version 0.4** * Added configuration file and the ability to set the Google API key. * Updated namespaces to PSR-4 diff --git a/composer.json b/composer.json index c74662f..85b8805 100644 --- a/composer.json +++ b/composer.json @@ -1,29 +1,30 @@ -{ - "name": "lodge/postcode-lookup", - "description": "A postcode lookup utility using the Google Maps API, ready to use with Laravel 5.", - "license": "MIT", - "authors": [ - { - "name": "Dan Ursu", - "email": "dan@schoolsup.com" - } - ], - "require": { - "php": ">=5.4.0", - "illuminate/support": "4.x|~5.0" - }, - "require-dev": { - "phpunit/phpunit": "~7.0" - }, - "autoload": { - "psr-4": { - "Lodge\\Postcode\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Lodge\\Postcode\\Tests\\": "tests/" - } - }, - "minimum-stability": "stable" -} +{ + "name": "lodge/postcode-lookup", + "description": "A postcode lookup utility using the Google Maps API, ready to use with Laravel 5.", + "license": "MIT", + "authors": [ + { + "name": "Dan Ursu", + "email": "dan@schoolsup.com" + } + ], + "require": { + "ext-json": "*", + "php": ">=7.1", + "illuminate/support": "4.x|~5.0" + }, + "require-dev": { + "phpunit/phpunit": "~7.0" + }, + "autoload": { + "psr-4": { + "Lodge\\Postcode\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Lodge\\Postcode\\Tests\\": "tests/" + } + }, + "minimum-stability": "stable" +} diff --git a/src/Address.php b/src/Address.php new file mode 100644 index 0000000..cb57d1f --- /dev/null +++ b/src/Address.php @@ -0,0 +1,188 @@ +coordinates = $coordinates; + $this->postcode = $postcode; + } + + /** + * @return string + */ + public function getPostcode() + { + return $this->postcode; + } + + /** + * @return string + */ + public function getStreetNumber() + { + return $this->streetNumber; + } + + /** + * @param string $streetNumber + */ + public function setStreetNumber($streetNumber) + { + $this->streetNumber = $streetNumber; + } + + /** + * @param string $county + */ + public function setCounty($county) + { + $this->county = $county; + } + + /** + * @param string $country + */ + public function setCountry($country) + { + $this->country = $country; + } + + /** + * @return string + */ + public function getStreet() + { + return $this->street; + } + + /** + * @param string $street + */ + public function setStreet($street) + { + $this->street = $street; + } + + /** + * @return string + */ + public function getSublocality() + { + return $this->sublocality; + } + + /** + * @param string $sublocality + */ + public function setSublocality($sublocality) + { + $this->sublocality = $sublocality; + } + + /** + * @return string + */ + public function getTown() + { + return $this->town; + } + + /** + * @param string $town + */ + public function setTown($town) + { + $this->town = $town; + } + + /** + * @return string + */ + public function getCounty() + { + return $this->county; + } + + /** + * @return string + */ + public function getCountry() + { + return $this->country; + } + + /** + * @return \Lodge\Postcode\Coordinates + */ + public function getCoordinates() + { + return $this->coordinates; + } + + /** + * @return array + */ + public function toArray() + { + return [ + 'postcode' => $this->postcode, + 'street_number' => $this->streetNumber, + 'street' => $this->street, + 'sublocality' => $this->sublocality, + 'town' => $this->town, + 'county' => $this->county, + 'country' => $this->country, + 'latitude' => $this->coordinates->getLatitude(), + 'longitude' => $this->coordinates->getLongitude(), + ]; + } +} diff --git a/src/Coordinates.php b/src/Coordinates.php new file mode 100644 index 0000000..b43d681 --- /dev/null +++ b/src/Coordinates.php @@ -0,0 +1,44 @@ +latitude = $latitude; + $this->longitude = $longitude; + } + + /** + * @return float + */ + public function getLatitude() + { + return $this->latitude; + } + + /** + * @return float + */ + public function getLongitude() + { + return $this->longitude; + } +} diff --git a/src/Exceptions/AddressNotFoundException.php b/src/Exceptions/AddressNotFoundException.php new file mode 100644 index 0000000..d640b78 --- /dev/null +++ b/src/Exceptions/AddressNotFoundException.php @@ -0,0 +1,7 @@ +apiKey = $apiKey; + } + + /** + * Sets the Google API key. + * + * @param string $key + * @return $this + */ + public function setApiKey($key) + { + $this->apiKey = $key; + + return $this; + } + + /** + * Returns coordinates from the given address. + * + * @param string $address + * @return \Lodge\Postcode\Coordinates + * @throws \Lodge\Postcode\Exceptions\AddressNotFoundException + * @throws \Lodge\Postcode\ServiceUnavailableException + */ + public function geocodeFromAddress($address) + { + // Sanitize the address: + $search_code = urlencode($address); + + // Retrieve the latitude and longitude + $url = 'address=' . $search_code . '&sensor=false'; + + $json = $this->fetch($url); + + if (!empty($json->results)) { + $lat = $json->results[0]->geometry->location->lat; + $lng = $json->results[0]->geometry->location->lng; + + return new Coordinates($lat, $lng); + } + + throw new AddressNotFoundException($address); + } + + /** + * Returns the best address found at the given coordinates. + * + * @param \Lodge\Postcode\Coordinates $coordinates + * @param string $postcode + * @return \Lodge\Postcode\Address + * @throws \Lodge\Postcode\Exceptions\AddressNotFoundException + */ + public function geocodeLatLng(Coordinates $coordinates, $postcode) + { + $address_json = $this->fetch(sprintf( + 'latlng=%s,%s&sensor=false', + $coordinates->getLatitude(), + $coordinates->getLongitude() + )); + + // The correct result is not always the first one, so loop through results here + foreach ($address_json->results as $current_address) { + foreach ($current_address->address_components as $component) { + // If this address_component is a postcode and matches... + if (array_search('postal_code', $component->types) !== FALSE + && $postcode == $this->mutatePostcode($component->long_name) + ) { + $address_data = $current_address->address_components; + break 2; + } + } + } + + // If no exact match found, use the first as a closest option + if (!isset($address_data) + && !empty($address_json->results) + ) { + $address_data = $address_json->results[0]->address_components; + } + + // If still nothing, return empty array + if (!isset($address_data)) { + throw new AddressNotFoundException(); + } + + $address = new Address($coordinates, $postcode); + + // Process the return + foreach ($address_data as $value) { + if (array_search('street_number', $value->types) !== FALSE) { + $address->setStreetNumber($value->long_name); + } elseif (array_search('route', $value->types) !== FALSE) { + $address->setStreet($value->long_name); + } elseif (array_search('sublocality', $value->types) !== FALSE) { + $address->setSublocality($value->long_name); + } elseif (array_search('locality', $value->types) !== FALSE) { + $address->setTown($value->long_name); + } elseif (array_search('administrative_area_level_2', $value->types) !== FALSE) { + $address->setCounty($value->long_name); + } elseif (array_search('country', $value->types) !== FALSE) { + $address->setCountry($value->long_name); + } + } + + return $address; + } + + /** + * Calls the Google API. + * + * @param string $path + * @return \stdClass + * @throws ServiceUnavailableException + */ + public function fetch($path) + { + $url = 'https://maps.googleapis.com/maps/api/geocode/json?'.$path; + + if ($this->apiKey) { + $url .= '&key='.$this->apiKey; + } + + try { + $json = json_decode(file_get_contents($url)); + } catch(\Exception $e) { + throw new ServiceUnavailableException; + } + + $this->checkApiError($json); + + return $json; + } + + /** + * @param \stdClass $json + * @throws ServiceUnavailableException + */ + private function checkApiError($json) + { + if (property_exists($json, 'error_message')) { + throw new ServiceUnavailableException($json->error_message); + } + } +} diff --git a/src/GoogleApi.php b/src/GoogleApi.php deleted file mode 100644 index bf7a2b8..0000000 --- a/src/GoogleApi.php +++ /dev/null @@ -1,70 +0,0 @@ -apiKey = $apiKey; - } - - /** - * Sets the Google API key. - * - * @param string $key - * @return $this - */ - public function setApiKey($key) - { - $this->apiKey = $key; - - return $this; - } - - /** - * Calls the Google API. - * - * @param string $url - * @return \stdClass - * @throws ServiceUnavailableException - */ - public function fetch($url) - { - if ($this->apiKey) { - $url .= '&key='.$this->apiKey; - } - - try { - $json = json_decode(file_get_contents($url)); - } catch(\Exception $e) { - throw new ServiceUnavailableException; - } - - $this->checkApiError($json); - - return $json; - } - - /** - * @param \stdClass $json - * @throws ServiceUnavailableException - */ - private function checkApiError($json) - { - if (property_exists($json, 'error_message')) { - throw new ServiceUnavailableException($json->error_message); - } - } -} diff --git a/src/Postcode.php b/src/Postcode.php index aad3fd6..9445182 100644 --- a/src/Postcode.php +++ b/src/Postcode.php @@ -2,8 +2,13 @@ namespace Lodge\Postcode; +use Lodge\Postcode\Gateways\GatewayInterface; +use Lodge\Postcode\Gateways\GoogleApi; + class Postcode { + use PostcodeUtils; + /** * Default country to search in. * @@ -20,105 +25,40 @@ class Postcode /** * Postcode constructor. - * @param string $apiKey + * + * @param \Lodge\Postcode\Gateways\GatewayInterface $apiGateway */ - public function __construct($apiKey = null) + public function __construct(GatewayInterface $apiGateway) { - $this->api = new GoogleApi($apiKey); + $this->api = $apiGateway; } /** * Retrieves the full address for a given postcode. * - * @param $postcode - * @return array + * @param string $postcode + * @return \Lodge\Postcode\Address + * @throws \Lodge\Postcode\Exceptions\AddressNotFoundException */ public function lookup($postcode) { // Mutate the postcode $postcode = $this->mutatePostcode($postcode); - // Sanitize the postcode: + // Retrieve the lat/lng from the address $coords = $this->getCoordinates($postcode); - // If empty, we must have no results - if (empty($coords)) { - return []; - } - - // A second call will now retrieve the address - $address_url = 'https://maps.googleapis.com/maps/api/geocode/json?latlng=' . $coords['latitude'] . ',' . $coords['longitude'] . '&sensor=false'; - - $address_json = $this->api->fetch($address_url); - - // The correct result is not always the first one, so loop through results here - foreach ($address_json->results as $current_address) { - foreach ($current_address->address_components as $component) { - // If this address_component is a postcode and matches... - if(array_search('postal_code', $component->types) !== FALSE - && $postcode == $this->mutatePostcode($component->long_name) - ) { - $address_data = $current_address->address_components; - break 2; - } - } - } - - // If no exact match found, use the first as a closest option - if (!isset($address_data) - && !empty($address_json->results) - ) { - $address_data = $address_json->results[0]->address_components; - } - - // If still nothing, return empty array - if (!isset($address_data)) { - return []; - } - - // Initialize all values as empty - $street_number = ''; - $street = ''; - $sublocality = ''; - $town = ''; - $county = ''; - $country = ''; - - // Process the return - foreach ($address_data as $value) { - if (array_search('street_number', $value->types) !== FALSE) { - $street_number = $value->long_name; - } elseif (array_search('route', $value->types) !== FALSE) { - $street = $value->long_name; - } elseif (array_search('sublocality', $value->types) !== FALSE) { - $sublocality = $value->long_name; - } elseif (array_search('locality', $value->types) !== FALSE) { - $town = $value->long_name; - } elseif (array_search('administrative_area_level_2', $value->types) !== FALSE) { - $county = $value->long_name; - } elseif (array_search('country', $value->types) !== FALSE) { - $country = $value->long_name; - } - } - - return [ - 'postcode' => $postcode, - 'street_number' => $street_number, - 'street' => $street, - 'sublocality' => $sublocality, - 'town' => $town, - 'county' => $county, - 'country' => $country, - 'latitude' => $coords['latitude'], - 'longitude' => $coords['longitude'] - ]; + // Attempt to reverse geocode the lat/lng + return $this->api->geocodeLatLng($coords, $postcode); } /** * Returns the lat/lng for the given address. * * @param string $address - * @return array + * @return \Lodge\Postcode\Coordinates + * @throws \Lodge\Postcode\Exceptions\AddressNotFoundException + * @throws \Lodge\Postcode\ServiceUnavailableException */ public function getCoordinates($address) { @@ -126,27 +66,7 @@ public function getCoordinates($address) $address = trim($address) . ' ' . $this->country; } - // Sanitize the address: - $search_code = urlencode($address); - - // Retrieve the latitude and longitude - $url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' . $search_code . '&sensor=false'; - - // If Google Maps API fails, catch it and throw a better error - $json = $this->api->fetch($url); - - if(!empty($json->results)) { - $lat = $json->results[0]->geometry->location->lat; - $lng = $json->results[0]->geometry->location->lng; - - return [ - 'latitude' => $lat, - 'longitude' => $lng - ]; - } - - // We must have nothing if we've got here - return []; + return $this->api->geocodeFromAddress($address); } /** @@ -162,31 +82,6 @@ public function setCountry($country = null) return $this; } - /** - * Remove all spaces from postcode. - * - * @param $postcode - * @return string - */ - public function mutatePostcode($postcode) - { - // Ensure the postcode is all upper case with no spaces - return preg_replace('/ /', '', strtoupper($postcode)); - } - - /** - * Replaces the Google API. - * - * @param mixed $api - * @return $this - */ - public function setApi($api) - { - $this->api = $api; - - return $this; - } - /** * Sets the Google API key. * diff --git a/src/PostcodeServiceProvider.php b/src/PostcodeServiceProvider.php index ff6b795..d554774 100644 --- a/src/PostcodeServiceProvider.php +++ b/src/PostcodeServiceProvider.php @@ -1,55 +1,58 @@ -app->runningInConsole()) { - $this->publishes([ - __DIR__.'/../config/postcode.php' => config_path('postcode.php'), - ], 'postcode-config'); - } - } - - /** - * Register the service provider. - * - * @return void - */ - public function register() - { - $this->mergeConfigFrom( - __DIR__.'/../config/postcode.php', 'postcode' - ); - - $this->app->singleton('postcode', function () { - return new Postcode(config('postcode.google_api_key')); - }); - } - - /** - * Get the services provided by the provider. - * - * @return array - */ - public function provides() - { - return ['postcode']; - } -} +app->runningInConsole()) { + $this->publishes([ + __DIR__.'/../config/postcode.php' => config_path('postcode.php'), + ], 'postcode-config'); + } + } + + /** + * Register the service provider. + * + * @return void + */ + public function register() + { + $this->mergeConfigFrom( + __DIR__.'/../config/postcode.php', 'postcode' + ); + + $this->app->singleton('postcode', function () { + return new Postcode( + new GoogleApi(config('postcode.google_api_key')) + ); + }); + } + + /** + * Get the services provided by the provider. + * + * @return array + */ + public function provides() + { + return ['postcode']; + } +} diff --git a/src/PostcodeUtils.php b/src/PostcodeUtils.php new file mode 100644 index 0000000..f613304 --- /dev/null +++ b/src/PostcodeUtils.php @@ -0,0 +1,18 @@ +getGateway(); + $gateway->method('fetch')->willReturn(json_decode(file_get_contents(__DIR__.'/../stubs/coordinates.json'))); + + $response = $gateway->geocodeFromAddress('test'); + $this->assertInstanceOf(Coordinates::class, $response); + $this->assertEquals(51.4891175, $response->getLatitude()); + $this->assertEquals(-0.1579016, $response->getLongitude()); + } + + public function test_it_throws_address_not_found() + { + /** @var \Lodge\Postcode\Gateways\GoogleApi $gateway */ + $gateway = $this->getGateway(); + $gateway->method('fetch')->willReturn([]); + + $this->expectException(AddressNotFoundException::class); + $gateway->geocodeFromAddress('test'); + } + + public function test_it_returns_an_address() + { + /** @var \Lodge\Postcode\Gateways\GoogleApi $gateway */ + $gateway = $this->getGateway(); + $gateway->method('fetch')->willReturn(json_decode(file_get_contents(__DIR__.'/../stubs/lookup.json'))); + $response = $gateway->geocodeLatLng(new Coordinates(50, -1), 'sw3 4sz'); + + $this->assertEquals('sw3 4sz', $response->getPostcode()); + $this->assertEquals('Franklins Row', $response->getStreet()); + $this->assertEquals('Greater London', $response->getCounty()); + $this->assertEquals('United Kingdom', $response->getCountry()); + $this->assertEquals(50, $response->getCoordinates()->getLatitude()); + $this->assertEquals(-1, $response->getCoordinates()->getLongitude()); + } + + private function getGateway() + { + return $this->getMockBuilder(GoogleApi::class)->setMethods(['fetch'])->getMock(); + } +} diff --git a/tests/PostcodeLookupTest.php b/tests/PostcodeLookupTest.php index 971f04b..36f9c84 100644 --- a/tests/PostcodeLookupTest.php +++ b/tests/PostcodeLookupTest.php @@ -2,7 +2,8 @@ namespace Lodge\Postcode\Tests; -use Lodge\Postcode\GoogleApi; +use Lodge\Postcode\Coordinates; +use Lodge\Postcode\Gateways\GoogleApi; use Lodge\Postcode\Postcode; use PHPUnit\Framework\TestCase; @@ -13,18 +14,6 @@ class PostcodeLookupTest extends TestCase */ private $postcode; - /** - * Instantiate the postcode class before each test - * - * @return void - */ - public function setUp() - { - parent::setUp(); - - $this->postcode = new Postcode(); - } - /** @test */ public function it_returns_an_array_with_the_address_coordinates() { @@ -32,19 +21,9 @@ public function it_returns_an_array_with_the_address_coordinates() $this->googleApiWillReturn(__DIR__.'/stubs/coordinates.json'); $response = $this->postcode->getCoordinates('SW3 4SZ'); - $this->assertTrue(is_array($response)); - $this->assertArrayHasKey('latitude', $response); - $this->assertArrayHasKey('longitude', $response); - } - - /** @test */ - public function it_mutates_the_postcode_so_that_it_doesnt_contain_spaces() - { - $postcode = $this->postcode->mutatePostcode('sw3 4sz'); - - // It contains uppercase letters and no spaces - $this->assertFalse(strpos(' ', $postcode)); - $this->assertEquals('SW34SZ', $postcode); + $this->assertInstanceOf(Coordinates::class, $response); + $this->assertEquals(51.4891175, $response->getLatitude()); + $this->assertEquals(-0.1579016, $response->getLongitude()); } /** @test */ @@ -53,28 +32,18 @@ public function it_returns_the_full_location_for_an_address() $this->googleApiWillReturn(__DIR__.'/stubs/lookup.json'); $response = $this->postcode->lookup('sw3 4sz'); - $this->assertEquals('SW34SZ', $response['postcode']); - $this->assertEquals('Franklins Row', $response['street']); - $this->assertEquals('Greater London', $response['county']); - $this->assertEquals('United Kingdom', $response['country']); - $this->assertEquals(51.4890557, $response['latitude']); - $this->assertEquals(-0.1579412, $response['longitude']); - - $this->assertArrayHasKey('postcode', $response); - $this->assertArrayHasKey('street_number', $response); - $this->assertArrayHasKey('street', $response); - $this->assertArrayHasKey('sublocality', $response); - $this->assertArrayHasKey('town', $response); - $this->assertArrayHasKey('county', $response); - $this->assertArrayHasKey('country', $response); - $this->assertArrayHasKey('latitude', $response); - $this->assertArrayHasKey('longitude', $response); + $this->assertEquals('SW34SZ', $response->getPostcode()); + $this->assertEquals('Franklins Row', $response->getStreet()); + $this->assertEquals('Greater London', $response->getCounty()); + $this->assertEquals('United Kingdom', $response->getCountry()); + $this->assertEquals(51.4890557, $response->getCoordinates()->getLatitude()); + $this->assertEquals(-0.1579412, $response->getCoordinates()->getLongitude()); } private function googleApiWillReturn($json) { - $googleMock = $this->createMock(GoogleApi::class); + $googleMock = $this->getMockBuilder(GoogleApi::class)->setMethods(['fetch'])->getMock(); $googleMock->method('fetch')->willReturn(json_decode(file_get_contents($json))); - $this->postcode->setApi($googleMock); + $this->postcode = new Postcode($googleMock); } } diff --git a/tests/PostcodeUtilsTest.php b/tests/PostcodeUtilsTest.php new file mode 100644 index 0000000..6fde55c --- /dev/null +++ b/tests/PostcodeUtilsTest.php @@ -0,0 +1,21 @@ +mutatePostcode('sw3 4sz'); + + // It contains uppercase letters and no spaces + $this->assertFalse(strpos(' ', $postcode)); + $this->assertEquals('SW34SZ', $postcode); + } +}