1 <?php
2
3 namespace GeoIp2\Test\WebService;
4
5 use Composer\CaBundle\CaBundle;
6 use GeoIp2\WebService\Client;
7 use MaxMind\WebService\Client as WsClient;
8
9 class ClientTest extends \PHPUnit_Framework_TestCase
10 {
11
12 private $country
13 = array(
14 'continent' => array(
15 'code' => 'NA',
16 'geoname_id' => 42,
17 'names' => array('en' => 'North America'),
18 ),
19 'country' => array(
20 'geoname_id' => 1,
21 'iso_code' => 'US',
22 'names' => array('en' => 'United States of America'),
23 ),
24 'maxmind' => array('queries_remaining' => 11),
25 'traits' => array(
26 'ip_address' => '1.2.3.4',
27 ),
28 );
29
30
31 private function getResponse($ipAddress)
32 {
33 $responses = array(
34 '1.2.3.4' => $this->response(
35 'country',
36 200,
37 $this->country
38 ),
39 'me' => $this->response(
40 'country',
41 200,
42 $this->country
43 ),
44 '1.2.3.5' => $this->response('country', 200),
45 '2.2.3.5' => $this->response('country', 200, 'bad body'),
46 '1.2.3.6' => $this->response(
47 'error',
48 400,
49 array(
50 'code' => 'IP_ADDRESS_INVALID',
51 'error' => 'The value "1.2.3" is not a valid ip address'
52 )
53 ),
54 '1.2.3.7' => $this->response(
55 'error',
56 400
57 ),
58 '1.2.3.8' => $this->response(
59 'error',
60 400,
61 array('weird' => 42)
62 ),
63 '1.2.3.9' => $this->response(
64 'error',
65 400,
66 null,
67 'bad body'
68 ),
69 '1.2.3.10' => $this->response(
70 null,
71 500
72 ),
73 '1.2.3.11' => $this->response(
74 null,
75 300
76 ),
77 '1.2.3.12' => $this->response(
78 'error',
79 406,
80 'Cannot satisfy your Accept-Charset requirements',
81 null,
82 'text/plain'
83 ),
84 '1.2.3.13' => $this->response(
85 'error',
86 404,
87 array(
88 'code' => 'IP_ADDRESS_NOT_FOUND',
89 'error' => 'The address "1.2.3.13" is not in our database.'
90 )
91 ),
92 '1.2.3.14' => $this->response(
93 'error',
94 400,
95 array(
96 'code' => 'IP_ADDRESS_RESERVED',
97 'error' => 'The address "1.2.3.14" is a private address.'
98 )
99 ),
100 '1.2.3.15' => $this->response(
101 'error',
102 401,
103 array(
104 'code' => 'AUTHORIZATION_INVALID',
105 'error' => 'A user ID and license key are required to use this service'
106 )
107 ),
108 '1.2.3.16' => $this->response(
109 'error',
110 401,
111 array(
112 'code' => 'LICENSE_KEY_REQUIRED',
113 'error' => 'A license key is required to use this service'
114 )
115 ),
116 '1.2.3.17' => $this->response(
117 'error',
118 401,
119 array(
120 'code' => 'USER_ID_REQUIRED',
121 'error' => 'A user ID is required to use this service'
122 )
123 ),
124 '1.2.3.18' => $this->response(
125 'error',
126 402,
127 array(
128 'code' => 'OUT_OF_QUERIES',
129 'error' => 'The license key you have provided is out of queries.'
130 )
131 ),
132 );
133 return $responses[$ipAddress];
134 }
135
136 public function testCountry()
137 {
138 $country = $this->makeRequest('Country', '1.2.3.4');
139
140 $this->assertInstanceOf('GeoIp2\Model\Country', $country);
141
142 $this->assertSame(
143 42,
144 $country->continent->geonameId,
145 'continent geoname_id is 42'
146 );
147
148 $this->assertSame(
149 'NA',
150 $country->continent->code,
151 'continent code is NA'
152 );
153
154 $this->assertSame(
155 array('en' => 'North America'),
156 $country->continent->names,
157 'continent names'
158 );
159
160 $this->assertSame(
161 'North America',
162 $country->continent->name,
163 'continent name is North America'
164 );
165
166 $this->assertSame(
167 1,
168 $country->country->geonameId,
169 'country geoname_id is 1'
170 );
171
172 $this->assertSame(
173 'US',
174 $country->country->isoCode,
175 'country iso_code is US'
176 );
177
178 $this->assertSame(
179 array('en' => 'United States of America'),
180 $country->country->names,
181 'country names'
182 );
183
184 $this->assertSame(
185 'United States of America',
186 $country->country->name,
187 'country name is United States of America'
188 );
189
190 $this->assertSame(
191 11,
192 $country->maxmind->queriesRemaining,
193 'queriesRemaining is correct'
194 );
195
196 }
197
198
199 public function testInsights()
200 {
201 $record = $this->makeRequest('Insights', '1.2.3.4');
202
203 $this->assertInstanceOf('GeoIp2\Model\Insights', $record);
204
205 $this->assertSame(
206 42,
207 $record->continent->geonameId,
208 'continent geoname_id is 42'
209 );
210 }
211
212 public function testCity()
213 {
214 $city = $this->makeRequest('City', '1.2.3.4');
215
216 $this->assertInstanceOf('GeoIp2\Model\City', $city);
217 }
218
219 public function testMe()
220 {
221 $city = $this->makeRequest('City', 'me');
222
223 $this->assertInstanceOf(
224 'GeoIp2\Model\City',
225 $city,
226 'can set ip parameter to me'
227 );
228 }
229
230 231 232 233
234 public function testNoBodyException()
235 {
236 $this->makeRequest('Country', '1.2.3.5');
237 }
238
239 240 241 242
243 public function testBadBodyException()
244 {
245 $this->makeRequest('Country', '2.2.3.5');
246 }
247
248
249 250 251 252 253
254 public function testInvalidIPException()
255 {
256 $this->makeRequest('Country', '1.2.3.6');
257 }
258
259 260 261 262 263
264 public function testNoErrorBodyIPException()
265 {
266 $this->makeRequest('Country', '1.2.3.7');
267 }
268
269 270 271 272
273 public function testWeirdErrorBodyIPException()
274 {
275 $this->makeRequest('Country', '1.2.3.8');
276
277 }
278
279 280 281 282 283
284 public function testInvalidErrorBodyIPException()
285 {
286 $this->makeRequest('Country', '1.2.3.9');
287
288 }
289
290 291 292 293 294
295 public function test500PException()
296 {
297 $this->makeRequest('Country', '1.2.3.10');
298 }
299
300 301 302 303 304
305 public function test3xxException()
306 {
307 $this->makeRequest('Country', '1.2.3.11');
308 }
309
310 311 312 313 314
315 public function test406Exception()
316 {
317 $this->makeRequest('Country', '1.2.3.12');
318 }
319
320 321 322 323
324 public function testAddressNotFoundException()
325 {
326 $this->makeRequest('Country', '1.2.3.13');
327 }
328
329 330 331 332
333 public function testAddressReservedException()
334 {
335 $this->makeRequest('Country', '1.2.3.14');
336 }
337
338 339 340 341
342 public function testAuthorizationException()
343 {
344 $this->makeRequest('Country', '1.2.3.15');
345 }
346
347 348 349 350
351 public function testMissingLicenseKeyException()
352 {
353 $this->makeRequest('Country', '1.2.3.16');
354 }
355
356 357 358 359
360 public function testMissingUserIdException()
361 {
362 $this->makeRequest('Country', '1.2.3.17');
363 }
364
365 366 367 368
369 public function testOutOfQueriesException()
370 {
371 $this->makeRequest('Country', '1.2.3.18');
372 }
373
374 public function testParams()
375 {
376 $this->makeRequest(
377 'Country',
378 '1.2.3.4',
379 array('en'),
380 array(
381 'host' => 'api.maxmind.com',
382 'timeout' => 27,
383 'connectTimeout' => 72,
384 )
385 );
386 }
387
388
389 private function response(
390 $endpoint,
391 $status,
392 $body = null,
393 $bad = null,
394 $contentType = null
395 ) {
396 $headers = array();
397 if ($contentType) {
398 $headers['Content-Type'] = $contentType;
399 } elseif ($status == 200 || ($status >= 400 && $status < 500)) {
400 $headers['Content-Type'] = 'application/vnd.maxmind.com-'
401 . $endpoint . '+json; charset=UTF-8; version=1.0;';
402 }
403
404 if ($bad) {
405 $body = '{ invalid: }';
406 } elseif (is_array($body)) {
407 $body = json_encode($body);
408 }
409
410 $headers['Content-Length'] = strlen($body);
411
412 return array($status, $headers, $body, );
413 }
414
415 private function makeRequest(
416 $service,
417 $ipAddress,
418 $locales = array('en'),
419 $options = array(),
420 $callsToRequest = 1
421 ) {
422 $userId = 42;
423 $licenseKey = 'abcdef123456';
424
425 list($statusCode, $headers, $responseBody)
426 = $this->getResponse($ipAddress);
427
428 $stub = $this->getMockForAbstractClass(
429 'MaxMind\\WebService\\Http\\Request'
430 );
431 $contentType = isset($headers['Content-Type'])
432 ? $headers['Content-Type']
433 : null;
434 $stub->expects($this->exactly($callsToRequest))
435 ->method('get')
436 ->willReturn(array($statusCode, $contentType, $responseBody));
437 $factory = $this->getMockBuilder(
438 'MaxMind\\WebService\\Http\\RequestFactory'
439 )->getMock();
440 $host = isset($options['host']) ? $options['host'] : 'geoip.maxmind.com';
441 $url = 'https://' . $host . '/geoip/v2.1/' . strtolower($service)
442 . '/' . $ipAddress;
443 $headers = array(
444 'Authorization: Basic '
445 . base64_encode($userId . ':' . $licenseKey),
446 'Accept: application/json',
447 );
448
449 $caBundle = CaBundle::getSystemCaRootBundlePath();
450
451 $curlVersion = curl_version();
452 $factory->expects($this->exactly($callsToRequest))
453 ->method('request')
454 ->with(
455 $this->equalTo($url),
456 $this->equalTo(
457 array(
458 'headers' => $headers,
459 'userAgent' => 'GeoIP2-API/' . \GeoIp2\WebService\Client::VERSION
460 . ' MaxMind-WS-API/' . WsClient::VERSION
461 . ' PHP/' . PHP_VERSION
462 . ' curl/' . $curlVersion['version'],
463 'connectTimeout' => isset($options['connectTimeout'])
464 ? $options['connectTimeout'] : null,
465 'timeout' => isset($options['timeout'])
466 ? $options['timeout'] : null,
467 'proxy' => isset($options['proxy'])
468 ? $options['proxy'] : null,
469 'caBundle' => $caBundle,
470 )
471 )
472 )->willReturn($stub);
473 $options['httpRequestFactory'] = $factory;
474
475 $method = strtolower($service);
476
477 $client = new \GeoIp2\WebService\Client(
478 $userId,
479 $licenseKey,
480 $locales,
481 $options
482 );
483 return $client->$method($ipAddress);
484 }
485 }
486