Skip to content

Commit 9cb77ea

Browse files
authored
Added some basic tests (#2)
* Added some basic tests * cs
1 parent ea59c12 commit 9cb77ea

8 files changed

+835
-3
lines changed

.cached_responses/.gitkeep

Whitespace-only changes.

.cached_responses/maps.googleapis.com_232e58df426ff2103395e35d8dc5dbcec523b150

Lines changed: 551 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
s:2135:"{
2+
"results" : [
3+
{
4+
"address_components" : [
5+
{
6+
"long_name" : "10",
7+
"short_name" : "10",
8+
"types" : [ "street_number" ]
9+
},
10+
{
11+
"long_name" : "Downing Street",
12+
"short_name" : "Downing St",
13+
"types" : [ "route" ]
14+
},
15+
{
16+
"long_name" : "Westminster",
17+
"short_name" : "Westminster",
18+
"types" : [ "neighborhood", "political" ]
19+
},
20+
{
21+
"long_name" : "London",
22+
"short_name" : "London",
23+
"types" : [ "postal_town" ]
24+
},
25+
{
26+
"long_name" : "Greater London",
27+
"short_name" : "Greater London",
28+
"types" : [ "administrative_area_level_2", "political" ]
29+
},
30+
{
31+
"long_name" : "England",
32+
"short_name" : "England",
33+
"types" : [ "administrative_area_level_1", "political" ]
34+
},
35+
{
36+
"long_name" : "United Kingdom",
37+
"short_name" : "GB",
38+
"types" : [ "country", "political" ]
39+
},
40+
{
41+
"long_name" : "SW1A 2AA",
42+
"short_name" : "SW1A 2AA",
43+
"types" : [ "postal_code" ]
44+
}
45+
],
46+
"formatted_address" : "10 Downing St, Westminster, London SW1A 2AA, UK",
47+
"geometry" : {
48+
"location" : {
49+
"lat" : 51.5033635,
50+
"lng" : -0.1276248
51+
},
52+
"location_type" : "APPROXIMATE",
53+
"viewport" : {
54+
"northeast" : {
55+
"lat" : 51.5047124802915,
56+
"lng" : -0.126275819708498
57+
},
58+
"southwest" : {
59+
"lat" : 51.5020145197085,
60+
"lng" : -0.128973780291502
61+
}
62+
}
63+
},
64+
"place_id" : "ChIJRxzRQcUEdkgRGVaKyzmkgvg",
65+
"types" : [ "establishment", "point_of_interest" ]
66+
}
67+
],
68+
"status" : "OK"
69+
}
70+
";
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
s:52:"{
2+
"results" : [],
3+
"status" : "ZERO_RESULTS"
4+
}
5+
";

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ class IntegrationTest extends ProviderIntegrationTest
2828
{
2929
return new GoogleMaps($httpClient);
3030
}
31+
32+
protected function getCacheDir()
33+
{
34+
return dirname(__DIR__).'/.cached_responses';
35+
}
36+
37+
protected function getApiKey()
38+
{
39+
return env('GOOLE_API_KEY');
40+
}
3141
}
3242
```
3343

src/CachedResponseClient.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ public function sendRequest(RequestInterface $request)
5656
{
5757
$url = (string) $request->getUri();
5858
$host = (string) $request->getUri()->getHost();
59-
if ($this->apiKey) {
59+
if (!empty($this->apiKey)) {
6060
$url = str_replace($this->apiKey, '[apikey]', $url);
6161
}
6262

63-
$file = sprintf('%s/%s/%s_%s', __DIR__, $this->cacheDir, $host, sha1($url));
63+
$file = sprintf('%s/%s_%s', $this->cacheDir, $host, sha1($url));
6464
if (is_file($file) && is_readable($file)) {
6565
return new Response(200, [], Psr7\stream_for(unserialize(file_get_contents($file))));
6666
}

src/ProviderIntegrationTest.php

Lines changed: 187 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,18 @@
1010

1111
namespace Geocoder\IntegrationTest;
1212

13+
use Geocoder\Collection;
14+
use Geocoder\Location;
15+
use Geocoder\Model\AdminLevelCollection;
16+
use Geocoder\Model\Bounds;
17+
use Geocoder\Model\Coordinates;
18+
use Geocoder\Model\Country;
1319
use Geocoder\Model\Query\GeocodeQuery;
1420
use Geocoder\Model\Query\ReverseQuery;
1521
use Geocoder\Provider\Provider;
1622
use GuzzleHttp\Psr7\Response;
1723
use Http\Client\HttpClient;
24+
use Http\Discovery\HttpClientDiscovery;
1825
use PHPUnit\Framework\TestCase;
1926
use Psr\Http\Message\ResponseInterface;
2027

@@ -29,10 +36,20 @@ abstract class ProviderIntegrationTest extends TestCase
2936
protected $skippedTests = [];
3037

3138
/**
32-
* @return Provider that is used in the tests
39+
* @return Provider that is used in the tests.
3340
*/
3441
abstract protected function createProvider(HttpClient $httpClient);
3542

43+
/**
44+
* @return string the directory where cached responses are stored
45+
*/
46+
abstract protected function getCacheDir();
47+
48+
/**
49+
* @return string the API key or substring to be removed from cache.
50+
*/
51+
abstract protected function getApiKey();
52+
3653
/**
3754
* @param ResponseInterface $response
3855
*
@@ -50,6 +67,88 @@ private function getHttpClient(ResponseInterface $response)
5067
return $client;
5168
}
5269

70+
/**
71+
* This client will make real request if cache was not found.
72+
*
73+
* @return CachedResponseClient
74+
*/
75+
private function getCachedHttpClient()
76+
{
77+
$client = HttpClientDiscovery::find();
78+
79+
return new CachedResponseClient($client, $this->getCacheDir(), $this->getApiKey());
80+
}
81+
82+
public function testGeocodeQuery()
83+
{
84+
if (isset($this->skippedTests[__FUNCTION__])) {
85+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
86+
}
87+
88+
$provider = $this->createProvider($this->getCachedHttpClient());
89+
$query = GeocodeQuery::create('10 Downing St, London, UK')->withLocale('en');
90+
$result = $provider->geocodeQuery($query);
91+
$this->assertWellFormattedResult($result);
92+
93+
// Check Downing Street
94+
$location = $result->first();
95+
$this->assertEquals(51.5033, $location->getCoordinates()->getLatitude(), 'Latitude should be in London', 0.1);
96+
$this->assertEquals(-0.1276, $location->getCoordinates()->getLongitude(), 'Longitude should be in London', 0.1);
97+
$this->assertContains('Downing', $location->getStreetName(), 'Street name should contain "Downing St"');
98+
$this->assertContains('10', $location->getStreetNumber(), 'Street number should contain "10"');
99+
}
100+
101+
public function testReverseQuery()
102+
{
103+
if (isset($this->skippedTests[__FUNCTION__])) {
104+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
105+
}
106+
107+
$provider = $this->createProvider($this->getCachedHttpClient());
108+
109+
// Close to the white house
110+
$result = $provider->reverseQuery(ReverseQuery::fromCoordinates(38.900206, -77.036991)->withLocale('en'));
111+
$this->assertWellFormattedResult($result);
112+
}
113+
114+
/**
115+
* @expectedException \Geocoder\Exception\InvalidArgument
116+
*/
117+
public function testEmptyQuery()
118+
{
119+
if (isset($this->skippedTests[__FUNCTION__])) {
120+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
121+
}
122+
123+
$provider = $this->createProvider($this->getCachedHttpClient());
124+
$provider->geocodeQuery(GeocodeQuery::create(''));
125+
}
126+
127+
/**
128+
* @expectedException \Geocoder\Exception\InvalidArgument
129+
*/
130+
public function testNullQuery()
131+
{
132+
if (isset($this->skippedTests[__FUNCTION__])) {
133+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
134+
}
135+
136+
$provider = $this->createProvider($this->getCachedHttpClient());
137+
$provider->geocodeQuery(GeocodeQuery::create(null));
138+
}
139+
140+
public function testEmptyReverseQuery()
141+
{
142+
if (isset($this->skippedTests[__FUNCTION__])) {
143+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
144+
}
145+
146+
$provider = $this->createProvider($this->getCachedHttpClient());
147+
148+
$result = $provider->reverseQuery(ReverseQuery::fromCoordinates(0, 0));
149+
$this->assertEquals(0, $result->count());
150+
}
151+
53152
/**
54153
* @expectedException \Geocoder\Exception\InvalidServerResponse
55154
*/
@@ -179,4 +278,91 @@ public function testQuotaExceededResponseReverse()
179278
$provider = $this->createProvider($this->getHttpClient(new Response(429)));
180279
$provider->reverseQuery(ReverseQuery::fromCoordinates(0, 0));
181280
}
281+
282+
/**
283+
* Make sure that a result for a Geocoder is well formatted. Be aware that even
284+
* a Location with no data may be well formatted.
285+
*
286+
* @param $result
287+
*/
288+
private function assertWellFormattedResult(Collection $result)
289+
{
290+
$this->assertInstanceOf(
291+
Collection::class,
292+
$result,
293+
'The result must be an instance of a Geocoder\Collection'
294+
);
295+
296+
$this->assertNotEmpty($result, 'Geocoder\Exception should never be empty. A NoResult exception should be thrown.');
297+
298+
/** @var Location $location */
299+
foreach ($result as $location) {
300+
$this->assertInstanceOf(
301+
Location::class,
302+
$location,
303+
'All items in Geocoder\Collection must implement Geocoder\Location'
304+
);
305+
306+
$this->assertInstanceOf(
307+
AdminLevelCollection::class,
308+
$location->getAdminLevels(),
309+
'Location::getAdminLevels MUST always return a AdminLevelCollection'
310+
);
311+
$arrayData = $location->toArray();
312+
$this->assertTrue(is_array($arrayData), 'Location::toArray MUST return an array.');
313+
$this->assertNotEmpty($arrayData, 'Location::toArray cannot be empty.');
314+
315+
// Verify coordinates
316+
if (null !== $coords = $location->getCoordinates()) {
317+
$this->assertInstanceOf(
318+
Coordinates::class,
319+
$coords,
320+
'Location::getCoordinates MUST always return a Coordinates or null'
321+
);
322+
323+
// Using "assertNotEmpty" means that we can not have test code where coordinates is on equator or long = 0
324+
$this->assertNotEmpty($coords->getLatitude(), 'If coordinate object exists it cannot have an empty latitude.');
325+
$this->assertNotEmpty($coords->getLongitude(), 'If coordinate object exists it cannot have an empty longitude.');
326+
}
327+
328+
// Verify bounds
329+
if (null !== $bounds = $location->getBounds()) {
330+
$this->assertInstanceOf(
331+
Bounds::class,
332+
$bounds,
333+
'Location::getBounds MUST always return a Bounds or null'
334+
);
335+
336+
// Using "assertNotEmpty" means that we can not have test code where coordinates is on equator or long = 0
337+
$this->assertNotEmpty($bounds->getSouth(), 'If bounds object exists it cannot have an empty values.');
338+
$this->assertNotEmpty($bounds->getWest(), 'If bounds object exists it cannot have an empty values.');
339+
$this->assertNotEmpty($bounds->getNorth(), 'If bounds object exists it cannot have an empty values.');
340+
$this->assertNotEmpty($bounds->getEast(), 'If bounds object exists it cannot have an empty values.');
341+
}
342+
343+
// Check country
344+
if (null !== $country = $location->getCountry()) {
345+
$this->assertInstanceOf(
346+
Country::class,
347+
$country,
348+
'Location::getCountry MUST always return a Country or null'
349+
);
350+
$this->assertFalse(null === $country->getCode() && null === $country->getName(), 'Both code and name cannot be empty');
351+
352+
if (null !== $country->getCode()) {
353+
$this->assertNotEmpty(
354+
$location->getCountry()->getCode(),
355+
'The Country should not have an empty code.'
356+
);
357+
}
358+
359+
if (null !== $country->getName()) {
360+
$this->assertNotEmpty(
361+
$location->getCountry()->getName(),
362+
'The Country should not have an empty name.'
363+
);
364+
}
365+
}
366+
}
367+
}
182368
}

tests/GoogleMapsTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,14 @@ protected function createProvider(HttpClient $httpClient)
2323
{
2424
return new GoogleMaps($httpClient);
2525
}
26+
27+
protected function getCacheDir()
28+
{
29+
return dirname(__DIR__).'/.cached_responses';
30+
}
31+
32+
protected function getApiKey()
33+
{
34+
return '';
35+
}
2636
}

0 commit comments

Comments
 (0)