From d7e3c5c6c9bfd44acabeae74ffe8e114fe28f646 Mon Sep 17 00:00:00 2001 From: Andrew Lively Date: Thu, 18 May 2017 11:47:17 -0400 Subject: [PATCH 1/6] Added support for mapzen (#204) --- lib/geocoder/mapzengeocoder.js | 105 +++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 lib/geocoder/mapzengeocoder.js diff --git a/lib/geocoder/mapzengeocoder.js b/lib/geocoder/mapzengeocoder.js new file mode 100644 index 00000000..59f2e7a1 --- /dev/null +++ b/lib/geocoder/mapzengeocoder.js @@ -0,0 +1,105 @@ +var querystring = require('querystring'), + util = require('util'), + AbstractGeocoder = require('./abstractgeocoder'); + +/** + * Constructor + */ +var MapzenGeocoder = function MapzenGeocoder(httpAdapter, apiKey) { + + MapzenGeocoder.super_.call(this, httpAdapter); + + if (!apiKey || apiKey == 'undefined') { + + throw new Error(this.constructor.name + ' needs an apiKey'); + } + + this.apiKey = apiKey; + this._endpoint = 'https://search.mapzen.com/v1'; +}; + +util.inherits(MapzenGeocoder, AbstractGeocoder); + +/** + * Geocode + * @param value Value to geocode (Address) + * @param callback Callback method + */ +MapzenGeocoder.prototype._geocode = function (value, callback) { + var _this = this; + this.httpAdapter.get(this._endpoint + '/search', { + 'text': value, + 'api_key': querystring.unescape(this.apiKey) + }, function (err, result) { + if (err) { + return callback(err); + } + if (result.error) { + return callback(new Error('Status is ' + result.error), {raw: result}); + } + + var results = []; + + var locations = result.features; + + for (var i = 0; i < locations.length; i++) { + results.push(_this._formatResult(locations[i])); + } + + results.raw = result; + callback(false, results); + }); +}; + +MapzenGeocoder.prototype._formatResult = function (result) { + var accuracy = (result.properties.confidence < 1) ? result.properties.confidence - 0.1 : 1; + + return { + 'latitude': result.geometry.coordinates[1], + 'longitude': result.geometry.coordinates[0], + 'country': result.properties.country, + 'city': result.properties.locality, + 'state': result.properties.region, + 'zipcode': null, + 'streetName': result.properties.street, + 'streetNumber': result.properties.housenumber, + 'countryCode': result.properties.country_a, + 'extra': { + confidence: accuracy || 0 + } + }; +}; + +/** + * Reverse geocoding + * @param {lat:,lon:} lat: Latitude, lon: Longitude + * @param callback Callback method + */ +MapzenGeocoder.prototype._reverse = function (query, callback) { + var lat = query.lat; + var lng = query.lon; + + var _this = this; + + this.httpAdapter.get(this._endpoint + '/reverse', { + 'point.lat': lat, + 'point.lon': lng, + 'api_key': querystring.unescape(this.apiKey) + }, function (err, result) { + if (err) { + return callback(err); + } + + var results = []; + var locations = result.results; + + for (var i = 0; i < locations.length; i++) { + results.push(_this._formatResult(locations[i])); + } + + results.raw = result; + callback(false, results); + }); +}; + +module.exports = MapzenGeocoder; From 16295ecb0f8ea66ad0037fee2e0fde7bf76ef2b0 Mon Sep 17 00:00:00 2001 From: Andrew Lively Date: Thu, 18 May 2017 12:07:35 -0400 Subject: [PATCH 2/6] Added test for mazpen geocoder --- test/geocoder/mapzengeocoder.js | 106 ++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 test/geocoder/mapzengeocoder.js diff --git a/test/geocoder/mapzengeocoder.js b/test/geocoder/mapzengeocoder.js new file mode 100644 index 00000000..08acd84f --- /dev/null +++ b/test/geocoder/mapzengeocoder.js @@ -0,0 +1,106 @@ +(function() { + var chai = require('chai'), + should = chai.should(), + expect = chai.expect, + sinon = require('sinon'); + + var MapzenGeocoder = require('../../lib/geocoder/MapzenGeocoder.js'); + var HttpAdapter = require('../../lib/httpadapter/httpadapter.js'); + + var mockedHttpAdapter = { + get: function() {} + }; + + describe('MapzenGeocoder', function() { + + describe('#constructor' , function() { + + it('an http adapter must be set', function() { + + expect(function() {new MapzenGeocoder();}).to.throw(Error, 'MapzenGeocoder need an httpAdapter'); + }); + + it('an apiKey must be set', function() { + + expect(function() {new MapzenGeocoder(mockedHttpAdapter);}).to.throw(Error, 'MapzenGeocoder needs an apiKey'); + }); + + it('Should be an instance of MapzenGeocoder', function() { + + var mapzenAdapter = new MapzenGeocoder(mockedHttpAdapter, 'API_KEY'); + + mapzenAdapter.should.be.instanceof(MapzenGeocoder); + }); + + }); + + describe('#geocode' , function() { + + it('Should not accept IPv4', function() { + + var mapzenAdapter = new MapzenGeocoder(mockedHttpAdapter, 'API_KEY'); + + expect(function() { + mapzenAdapter.geocode('127.0.0.1'); + }).to.throw(Error, 'MapzenGeocoder does not support geocoding IPv4'); + + }); + + it('Should not accept IPv6', function() { + + var mapzenAdapter = new MapzenGeocoder(mockedHttpAdapter, 'API_KEY'); + + expect(function() { + mapzenAdapter.geocode('2001:0db8:0000:85a3:0000:0000:ac1f:8001'); + }).to.throw(Error, 'MapzenGeocoder does not support geocoding IPv6'); + + }); + + it('Should return a geocoded address', function(done) { + + var mapzenAdapter = new MapzenGeocoder(new HttpAdapter(), 'API_KEY'); + + mapzenAdapter.geocode('2600 Clifton Ave, Cincinnati, OH 45220', function(err, results) { + err.should.to.equal(false); + + results[0].should.to.deep.equal({ + "latitude": 39.12968, + "longitude": -84.52065, + "country": "United States", + "state": "Ohio", + "city": "Cincinnati", + "zipcode": null, + "streetName": "Clifton Avenue", + "streetNumber": "2600", + "countryCode": "USA", + "extra": { + "confidence": 0.7000000000000001 + } + }); + + done(); + }); + + }); + + }); + + describe('#reverse' , function() { + it('Should call httpAdapter get method', function() { + + var mock = sinon.mock(mockedHttpAdapter); + mock.expects('get').once().returns({then: function() {}}); + + var mapzenAdapter = new MapzenGeocoder(mockedHttpAdapter, 'API_KEY'); + + mapzenAdapter.reverse({lat:10.0235,lon:-2.3662}); + + mock.verify(); + }); + + }); + + + }); + +})(); From 41f03f5ca1efbb202718f1b1ce393d07ced47232 Mon Sep 17 00:00:00 2001 From: Andrew Lively Date: Thu, 18 May 2017 12:07:35 -0400 Subject: [PATCH 3/6] Added test for mazpen geocoder --- test/geocoder/mapzengeocoder.js | 106 ++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 test/geocoder/mapzengeocoder.js diff --git a/test/geocoder/mapzengeocoder.js b/test/geocoder/mapzengeocoder.js new file mode 100644 index 00000000..08acd84f --- /dev/null +++ b/test/geocoder/mapzengeocoder.js @@ -0,0 +1,106 @@ +(function() { + var chai = require('chai'), + should = chai.should(), + expect = chai.expect, + sinon = require('sinon'); + + var MapzenGeocoder = require('../../lib/geocoder/MapzenGeocoder.js'); + var HttpAdapter = require('../../lib/httpadapter/httpadapter.js'); + + var mockedHttpAdapter = { + get: function() {} + }; + + describe('MapzenGeocoder', function() { + + describe('#constructor' , function() { + + it('an http adapter must be set', function() { + + expect(function() {new MapzenGeocoder();}).to.throw(Error, 'MapzenGeocoder need an httpAdapter'); + }); + + it('an apiKey must be set', function() { + + expect(function() {new MapzenGeocoder(mockedHttpAdapter);}).to.throw(Error, 'MapzenGeocoder needs an apiKey'); + }); + + it('Should be an instance of MapzenGeocoder', function() { + + var mapzenAdapter = new MapzenGeocoder(mockedHttpAdapter, 'API_KEY'); + + mapzenAdapter.should.be.instanceof(MapzenGeocoder); + }); + + }); + + describe('#geocode' , function() { + + it('Should not accept IPv4', function() { + + var mapzenAdapter = new MapzenGeocoder(mockedHttpAdapter, 'API_KEY'); + + expect(function() { + mapzenAdapter.geocode('127.0.0.1'); + }).to.throw(Error, 'MapzenGeocoder does not support geocoding IPv4'); + + }); + + it('Should not accept IPv6', function() { + + var mapzenAdapter = new MapzenGeocoder(mockedHttpAdapter, 'API_KEY'); + + expect(function() { + mapzenAdapter.geocode('2001:0db8:0000:85a3:0000:0000:ac1f:8001'); + }).to.throw(Error, 'MapzenGeocoder does not support geocoding IPv6'); + + }); + + it('Should return a geocoded address', function(done) { + + var mapzenAdapter = new MapzenGeocoder(new HttpAdapter(), 'API_KEY'); + + mapzenAdapter.geocode('2600 Clifton Ave, Cincinnati, OH 45220', function(err, results) { + err.should.to.equal(false); + + results[0].should.to.deep.equal({ + "latitude": 39.12968, + "longitude": -84.52065, + "country": "United States", + "state": "Ohio", + "city": "Cincinnati", + "zipcode": null, + "streetName": "Clifton Avenue", + "streetNumber": "2600", + "countryCode": "USA", + "extra": { + "confidence": 0.7000000000000001 + } + }); + + done(); + }); + + }); + + }); + + describe('#reverse' , function() { + it('Should call httpAdapter get method', function() { + + var mock = sinon.mock(mockedHttpAdapter); + mock.expects('get').once().returns({then: function() {}}); + + var mapzenAdapter = new MapzenGeocoder(mockedHttpAdapter, 'API_KEY'); + + mapzenAdapter.reverse({lat:10.0235,lon:-2.3662}); + + mock.verify(); + }); + + }); + + + }); + +})(); From 23f263398fbaed8867935613a247c754ba6b5549 Mon Sep 17 00:00:00 2001 From: Andrew Lively Date: Thu, 18 May 2017 12:54:06 -0400 Subject: [PATCH 4/6] Include mapzen in geocoderfactory --- lib/geocoderfactory.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/geocoderfactory.js b/lib/geocoderfactory.js index 6f3b4f87..bc3efe13 100644 --- a/lib/geocoderfactory.js +++ b/lib/geocoderfactory.js @@ -15,6 +15,7 @@ var DataScienceToolkitGeocoder = require('./geocoder/datasciencetoolkitgeocoder. var OpenStreetMapGeocoder = require('./geocoder/openstreetmapgeocoder.js'); var LocationIQGeocoder = require('./geocoder/locationiqgeocoder.js'); var MapQuestGeocoder = require('./geocoder/mapquestgeocoder.js'); +var MapzenGeocoder = require('./geocoder/mapzengeocoder.js'); var OpenMapQuestGeocoder = require('./geocoder/openmapquestgeocoder.js'); var YandexGeocoder = require('./geocoder/yandexgeocoder.js'); var GeocodioGeocoder = require('./geocoder/geocodiogeocoder.js'); @@ -76,6 +77,9 @@ var GeocoderFactory = { if (geocoderName === 'mapquest') { return new MapQuestGeocoder(adapter, extra.apiKey); } + if (geocoderName === 'mapzen') { + return new MapzenGeocoder(adapter, extra.apiKey); + } if (geocoderName === 'openmapquest') { return new OpenMapQuestGeocoder(adapter, extra.apiKey); } From d0b8f93fba33bf90472616a65c20a9f1eeba2668 Mon Sep 17 00:00:00 2001 From: Andrew Lively Date: Mon, 19 Jun 2017 10:31:15 -0400 Subject: [PATCH 5/6] Fix path to mapzengeocoder in test --- test/geocoder/mapzengeocoder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/geocoder/mapzengeocoder.js b/test/geocoder/mapzengeocoder.js index 08acd84f..84312924 100644 --- a/test/geocoder/mapzengeocoder.js +++ b/test/geocoder/mapzengeocoder.js @@ -4,7 +4,7 @@ expect = chai.expect, sinon = require('sinon'); - var MapzenGeocoder = require('../../lib/geocoder/MapzenGeocoder.js'); + var MapzenGeocoder = require('../../lib/geocoder/mapzengeocoder.js'); var HttpAdapter = require('../../lib/httpadapter/httpadapter.js'); var mockedHttpAdapter = { From fa5de5e06c506ba8bddb695aeb544ac8245c408a Mon Sep 17 00:00:00 2001 From: Andrew Lively Date: Mon, 19 Jun 2017 13:04:04 -0400 Subject: [PATCH 6/6] Remove data specific test --- test/geocoder/mapzengeocoder.js | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/test/geocoder/mapzengeocoder.js b/test/geocoder/mapzengeocoder.js index 84312924..590e341f 100644 --- a/test/geocoder/mapzengeocoder.js +++ b/test/geocoder/mapzengeocoder.js @@ -56,33 +56,6 @@ }); - it('Should return a geocoded address', function(done) { - - var mapzenAdapter = new MapzenGeocoder(new HttpAdapter(), 'API_KEY'); - - mapzenAdapter.geocode('2600 Clifton Ave, Cincinnati, OH 45220', function(err, results) { - err.should.to.equal(false); - - results[0].should.to.deep.equal({ - "latitude": 39.12968, - "longitude": -84.52065, - "country": "United States", - "state": "Ohio", - "city": "Cincinnati", - "zipcode": null, - "streetName": "Clifton Avenue", - "streetNumber": "2600", - "countryCode": "USA", - "extra": { - "confidence": 0.7000000000000001 - } - }); - - done(); - }); - - }); - }); describe('#reverse' , function() {