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