Completed
Branch master (1f9acc)
by Tobias
45:08 queued 20:09
created

IntegrationTest::testGeocodeQueryWithNoResults()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 4
nop 0
dl 0
loc 14
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Geocoder package.
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @license    MIT License
9
 */
10
11
namespace Geocoder\Provider\AlgoliaPlaces\Tests;
12
13
use Geocoder\IntegrationTest\ProviderIntegrationTest;
14
use Geocoder\IntegrationTest\CachedResponseClient;
15
use Geocoder\Provider\AlgoliaPlaces\AlgoliaPlaces;
16
use Geocoder\Collection;
17
use Geocoder\Location;
18
use Geocoder\Model\AdminLevelCollection;
19
use Geocoder\Model\Bounds;
20
use Geocoder\Model\Coordinates;
21
use Geocoder\Model\Country;
22
use Geocoder\Provider\Provider;
23
use Geocoder\Query\GeocodeQuery;
24
use Geocoder\Query\ReverseQuery;
25
use Http\Client\HttpClient;
26
use Http\Discovery\HttpClientDiscovery;
27
28
/**
29
 * @author Sébastien Barré <[email protected]>
30
 */
31
class IntegrationTest extends ProviderIntegrationTest
32
{
33
    protected $testIpv4 = false;
34
35
    protected $testIpv6 = false;
36
37
    protected $testReverse = false;
38
39
    protected function createProvider(HttpClient $httpClient)
40
    {
41
        return new AlgoliaPlaces($httpClient, $this->getApiKey(), $this->getAppId());
42
    }
43
44
    protected function getCacheDir()
45
    {
46
        return __DIR__.'/.cached_responses';
47
    }
48
49
    /**
50
     * This client will make real request if cache was not found.
51
     *
52
     * @return CachedResponseClient
53
     */
54
    private function getCachedHttpClient()
55
    {
56
        try {
57
            $client = HttpClientDiscovery::find();
58
        } catch (\Http\Discovery\NotFoundException $e) {
59
            $client = $this->getMockForAbstractClass(HttpClient::class);
60
61
            $client
62
                ->expects($this->any())
63
                ->method('sendRequest')
64
                ->willThrowException($e);
65
        }
66
67
        return new CachedResponseClient($client, $this->getCacheDir(), $this->getAppId());
68
    }
69
70
    protected function getApiKey()
71
    {
72
        return $_SERVER['ALGOLIA_API_KEY'];
73
    }
74
75
    protected function getAppId()
76
    {
77
        return $_SERVER['ALGOLIA_APP_ID'];
78
    }
79
80
    public function testGeocodeQuery()
81
    {
82
        if (isset($this->skippedTests[__FUNCTION__])) {
83
            $this->markTestSkipped($this->skippedTests[__FUNCTION__]);
84
        }
85
        if (!$this->testAddress) {
86
            $this->markTestSkipped('Geocoding address is not supported by this provider');
87
        }
88
89
        $provider = $this->createProvider($this->getCachedHttpClient());
90
        $query = GeocodeQuery::create('10 Downing Street, Westminster, Greater London, United Kingdom')->withLocale('en');
91
        $result = $provider->geocodeQuery($query);
92
        $this->assertWellFormattedResult($result);
93
94
        // Check Downing Street
95
        $location = $result->first();
96
        $this->assertEquals(51.5033, $location->getCoordinates()->getLatitude(), 'Latitude should be in London', 0.1);
97
        $this->assertEquals(-0.1276, $location->getCoordinates()->getLongitude(), 'Longitude should be in London', 0.1);
98
        $this->assertContains('Downing', $location->getStreetName(), 'Street name should contain "Downing St"');
99
100
        if (null !== $streetNumber = $location->getStreetNumber()) {
101
            $this->assertContains('10', $streetNumber, 'Street number should contain "10"');
102
        }
103
    }
104
105
    public function testGeocodeQueryWithNoResults()
106
    {
107
        if (isset($this->skippedTests[__FUNCTION__])) {
108
            $this->markTestSkipped($this->skippedTests[__FUNCTION__]);
109
        }
110
        if (!$this->testAddress) {
111
            $this->markTestSkipped('Geocoding address is not supported by this provider');
112
        }
113
114
        $provider = $this->createProvider($this->getCachedHttpClient());
115
        $query = GeocodeQuery::create('jsajhgsdkfjhsfkjhaldkadjaslgldasd')->withLocale('en');
116
        $result = $provider->geocodeQuery($query);
117
        $this->assertWellFormattedResult($result);
118
        $this->assertEquals(0, $result->count());
119
    }
120
121
    public function testReverseQuery()
122
    {
123
        if (isset($this->skippedTests[__FUNCTION__])) {
124
            $this->markTestSkipped($this->skippedTests[__FUNCTION__]);
125
        }
126
        if (!$this->testReverse) {
127
            $this->markTestSkipped('Reverse geocoding address is not supported by this provider');
128
        }
129
130
        $provider = $this->createProvider($this->getCachedHttpClient());
131
132
        // Close to the white house
133
        $result = $provider->reverseQuery(ReverseQuery::fromCoordinates(38.900206, -77.036991)->withLocale('en'));
134
        $this->assertWellFormattedResult($result);
135
    }
136
137
    public function testReverseQueryWithNoResults()
138
    {
139
        if (isset($this->skippedTests[__FUNCTION__])) {
140
            $this->markTestSkipped($this->skippedTests[__FUNCTION__]);
141
        }
142
143
        if (!$this->testReverse) {
144
            $this->markTestSkipped('Reverse geocoding address is not supported by this provider');
145
        }
146
147
        $provider = $this->createProvider($this->getCachedHttpClient());
148
149
        $result = $provider->reverseQuery(ReverseQuery::fromCoordinates(0, 0));
150
        $this->assertEquals(0, $result->count());
151
    }
152
153
    /**
154
     * Make sure that a result for a Geocoder is well formatted. Be aware that even
155
     * a Location with no data may be well formatted.
156
     *
157
     * @param $result
158
     */
159
    private function assertWellFormattedResult(Collection $result)
160
    {
161
        $this->assertInstanceOf(
162
            Collection::class,
163
            $result,
164
            'The result must be an instance of a Geocoder\Collection'
165
        );
166
167
        /** @var Location $location */
168
        foreach ($result as $location) {
169
            $this->assertInstanceOf(
170
                Location::class,
171
                $location,
172
                'All items in Geocoder\Collection must implement Geocoder\Location'
173
            );
174
175
            $this->assertInstanceOf(
176
                AdminLevelCollection::class,
177
                $location->getAdminLevels(),
178
                'Location::getAdminLevels MUST always return a AdminLevelCollection'
179
            );
180
            $arrayData = $location->toArray();
181
            $this->assertTrue(is_array($arrayData), 'Location::toArray MUST return an array.');
182
            $this->assertNotEmpty($arrayData, 'Location::toArray cannot be empty.');
183
184
            // Verify coordinates
185
            if (null !== $coords = $location->getCoordinates()) {
186
                $this->assertInstanceOf(
187
                    Coordinates::class,
188
                    $coords,
189
                    'Location::getCoordinates MUST always return a Coordinates or null'
190
                );
191
192
                // Using "assertNotEmpty" means that we can not have test code where coordinates is on equator or long = 0
193
                $this->assertNotEmpty($coords->getLatitude(), 'If coordinate object exists it cannot have an empty latitude.');
194
                $this->assertNotEmpty($coords->getLongitude(), 'If coordinate object exists it cannot have an empty longitude.');
195
            }
196
197
            // Verify bounds
198
            if (null !== $bounds = $location->getBounds()) {
199
                $this->assertInstanceOf(
200
                    Bounds::class,
201
                    $bounds,
202
                    'Location::getBounds MUST always return a Bounds or null'
203
                );
204
205
                // Using "assertNotEmpty" means that we can not have test code where coordinates is on equator or long = 0
206
                $this->assertNotEmpty($bounds->getSouth(), 'If bounds object exists it cannot have an empty values.');
207
                $this->assertNotEmpty($bounds->getWest(), 'If bounds object exists it cannot have an empty values.');
208
                $this->assertNotEmpty($bounds->getNorth(), 'If bounds object exists it cannot have an empty values.');
209
                $this->assertNotEmpty($bounds->getEast(), 'If bounds object exists it cannot have an empty values.');
210
            }
211
212
            // Check country
213
            if (null !== $country = $location->getCountry()) {
214
                $this->assertInstanceOf(
215
                    Country::class,
216
                    $country,
217
                    'Location::getCountry MUST always return a Country or null'
218
                );
219
                $this->assertFalse(null === $country->getCode() && null === $country->getName(), 'Both code and name cannot be empty');
220
221
                if (null !== $country->getCode()) {
222
                    $this->assertNotEmpty(
223
                        $location->getCountry()->getCode(),
224
                        'The Country should not have an empty code.'
225
                    );
226
                }
227
228
                if (null !== $country->getName()) {
229
                    $this->assertNotEmpty(
230
                        $location->getCountry()->getName(),
231
                        'The Country should not have an empty name.'
232
                    );
233
                }
234
            }
235
        }
236
    }
237
}
238