-
-
Notifications
You must be signed in to change notification settings - Fork 211
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #216 from andrewlively/master
Add support for mapzen
- Loading branch information
Showing
3 changed files
with
188 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <string> value Value to geocode (Address) | ||
* @param <function> 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:<number>,lon:<number>} lat: Latitude, lon: Longitude | ||
* @param <function> 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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
(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'); | ||
|
||
}); | ||
|
||
}); | ||
|
||
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(); | ||
}); | ||
|
||
}); | ||
|
||
|
||
}); | ||
|
||
})(); |