Browse Source

geojsonify /search and /reverse FTW

pull/18/head
Peter Johnson 10 years ago
parent
commit
17134105d5
  1. 13
      controller/search.js
  2. 44
      helper/geojsonify.js
  3. 9
      test/ciao/reverse/success.coffee
  4. 9
      test/ciao/search/success.coffee
  5. 37
      test/unit/controller/search.js
  6. 102
      test/unit/helper/geojsonify.js
  7. 18
      test/unit/mock/backend.js

13
controller/search.js

@ -1,4 +1,6 @@
var geojsonify = require('../helper/geojsonify').search;
function setup( backend, query ){ function setup( backend, query ){
// allow overriding of dependencies // allow overriding of dependencies
@ -27,11 +29,14 @@ function setup( backend, query ){
}); });
} }
// convert docs to geojson
var geojson = geojsonify( docs );
// response envelope
geojson.date = new Date().getTime();
// respond // respond
return res.status(200).json({ return res.status(200).json( geojson );
date: new Date().getTime(),
body: docs
});
}); });
} }

44
helper/geojsonify.js

@ -42,4 +42,48 @@ function suggest( docs ){
} }
function search( docs ){
// emit a warning if the doc format is invalid
// @note: if you see this error, fix it ASAP!
function warning(){
console.error( 'error: invalid doc', __filename );
return false; // remove offending doc from results
}
// flatten & expand data for geojson conversion
var geodata = docs.map( function( doc ){
var output = {};
// something went very wrong
if( !doc ) return warning();
// map center_point
if( !doc.center_point ) return warning();
output.lat = parseFloat( doc.center_point.lat );
output.lng = parseFloat( doc.center_point.lon );
// map name
if( !doc.name || !doc.name.default ) return warning();
output.name = doc.name.default;
// map admin values
if( doc.admin0 ){ output.admin0 = doc.admin0; }
if( doc.admin1 ){ output.admin1 = doc.admin1; }
if( doc.admin2 ){ output.admin2 = doc.admin2; }
return output;
// filter-out invalid entries
}).filter( function( doc ){
return doc;
});
// convert to geojson
return GeoJSON.parse( geodata, { Point: ['lat', 'lng'] } );
}
module.exports.suggest = suggest; module.exports.suggest = suggest;
module.exports.search = search;

9
test/ciao/reverse/success.coffee

@ -8,7 +8,8 @@ response.statusCode.should.equal 200
now = new Date().getTime() now = new Date().getTime()
should.exist json should.exist json
should.not.exist json.error should.not.exist json.error
should.exist json.date json.date.should.be.within now-5000, now+5000
json.date.should.be.within now-2000, now+2000
should.exist json.body #? valid geojson
json.body.should.be.instanceof Array json.type.should.equal 'FeatureCollection'
json.features.should.be.instanceof Array

9
test/ciao/search/success.coffee

@ -8,7 +8,8 @@ response.statusCode.should.equal 200
now = new Date().getTime() now = new Date().getTime()
should.exist json should.exist json
should.not.exist json.error should.not.exist json.error
should.exist json.date json.date.should.be.within now-5000, now+5000
json.date.should.be.within now-2000, now+2000
should.exist json.body #? valid geojson
json.body.should.be.instanceof Array json.type.should.equal 'FeatureCollection'
json.features.should.be.instanceof Array

37
test/unit/controller/search.js

@ -15,7 +15,35 @@ module.exports.tests.interface = function(test, common) {
// functionally test controller (backend success) // functionally test controller (backend success)
module.exports.tests.functional_success = function(test, common) { module.exports.tests.functional_success = function(test, common) {
test('functional test', function(t) {
// expected geojson features for 'client/suggest/ok/1' fixture
var expected = [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ -50.5, 100.1 ]
},
properties: {
name: 'test name1',
admin0: 'country1',
admin1: 'state1',
admin2: 'city1'
}
}, {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ -51.5, 100.2 ]
},
properties: {
name: 'test name2',
admin0: 'country2',
admin1: 'state2',
admin2: 'city2'
}
}];
test('functional success', function(t) {
var backend = mockBackend( 'client/search/ok/1', function( cmd ){ var backend = mockBackend( 'client/search/ok/1', function( cmd ){
t.deepEqual(cmd, { body: { a: 'b' }, index: 'pelias' }, 'correct backend command'); t.deepEqual(cmd, { body: { a: 'b' }, index: 'pelias' }, 'correct backend command');
}); });
@ -28,8 +56,9 @@ module.exports.tests.functional_success = function(test, common) {
json: function( json ){ json: function( json ){
t.equal(typeof json, 'object', 'returns json'); t.equal(typeof json, 'object', 'returns json');
t.equal(typeof json.date, 'number', 'date set'); t.equal(typeof json.date, 'number', 'date set');
t.true(Array.isArray(json.body), 'body is array'); t.equal(json.type, 'FeatureCollection', 'valid geojson');
// t.deepEqual(json.body, [ { value: 1 }, { value: 2 } ], 'values correctly mapped'); t.true(Array.isArray(json.features), 'features is array');
t.deepEqual(json.features, expected, 'values correctly mapped');
t.end(); t.end();
} }
}; };
@ -39,7 +68,7 @@ module.exports.tests.functional_success = function(test, common) {
// functionally test controller (backend failure) // functionally test controller (backend failure)
module.exports.tests.functional_failure = function(test, common) { module.exports.tests.functional_failure = function(test, common) {
test('functional test', function(t) { test('functional failure', function(t) {
var backend = mockBackend( 'client/search/fail/1', function( cmd ){ var backend = mockBackend( 'client/search/fail/1', function( cmd ){
t.deepEqual(cmd, { body: { a: 'b' }, index: 'pelias' }, 'correct backend command'); t.deepEqual(cmd, { body: { a: 'b' }, index: 'pelias' }, 'correct backend command');
}); });

102
test/unit/helper/geojsonify.js

@ -70,6 +70,108 @@ module.exports.tests.suggest = function(test, common) {
}); });
}; };
module.exports.tests.search = function(test, common) {
var input = [
{
"center_point": {
"lat": 51.5337144,
"lon": -0.1069716
},
"name": {
"default": "'Round Midnight Jazz and Blues Bar"
},
"type": "node",
"address": {
"number": "13",
"street": "Liverpool Road",
"zip": "N1 0RW"
},
"admin0": "United Kingdom",
"admin1": "Islington",
"admin2": "Angel",
"suggest": {
"input": [
"'round midnight jazz and blues bar"
],
"payload": {
"id": "osmnode/2208150035",
"geo": "-0.10697160000000001,51.53371440000001"
},
"output": "'Round Midnight Jazz and Blues Bar, Angel, United Kingdom"
}
},
{
"type": "way",
"name": {
"default": "Blues Cafe"
},
"center_point": {
"lat": "51.517806",
"lon": "-0.101795"
},
"admin0": "United Kingdom",
"admin1": "City And County Of The City Of London",
"admin2": "Smithfield",
"suggest": {
"input": [
"blues cafe"
],
"payload": {
"id": "osmway/147495160",
"geo": "-0.101795,51.517806"
},
"output": "Blues Cafe, Smithfield, United Kingdom"
}
}
];
var expected = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-0.1069716,
51.5337144
]
},
"properties": {
"name": "'Round Midnight Jazz and Blues Bar",
"admin0": "United Kingdom",
"admin1": "Islington",
"admin2": "Angel"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-0.101795,
51.517806
]
},
"properties": {
"name": "Blues Cafe",
"admin0": "United Kingdom",
"admin1": "City And County Of The City Of London",
"admin2": "Smithfield"
}
}
]
};
test('geojsonify.search()', function(t) {
var json = geojsonify.search( input );
t.deepEqual(json, expected, 'all docs mapped');
t.end();
});
};
module.exports.all = function (tape, common) { module.exports.all = function (tape, common) {
function test(name, testFunction) { function test(name, testFunction) {

18
test/unit/mock/backend.js

@ -12,7 +12,21 @@ responses['client/suggest/fail/1'] = function( cmd, cb ){
return cb( 'a backend error occurred' ); return cb( 'a backend error occurred' );
}; };
responses['client/search/ok/1'] = function( cmd, cb ){ responses['client/search/ok/1'] = function( cmd, cb ){
return cb( undefined, searchEnvelope([ { value: 1 }, { value: 2 } ]) ); return cb( undefined, searchEnvelope([{
_source: {
value: 1,
center_point: { lat: 100.1, lon: -50.5 },
name: { default: 'test name1' },
admin0: 'country1', admin1: 'state1', admin2: 'city1'
}
}, {
_source: {
value: 2,
center_point: { lat: 100.2, lon: -51.5 },
name: { default: 'test name2' },
admin0: 'country2', admin1: 'state2', admin2: 'city2'
}
}]));
}; };
responses['client/search/fail/1'] = function( cmd, cb ){ responses['client/search/fail/1'] = function( cmd, cb ){
return cb( 'a backend error occurred' ); return cb( 'a backend error occurred' );
@ -41,7 +55,7 @@ function suggestEnvelope( options ){
} }
function searchEnvelope( options ){ function searchEnvelope( options ){
return { pelias: [{ options: options }]}; return { hits: { total: options.length, hits: options } };
} }
module.exports = setup; module.exports = setup;
Loading…
Cancel
Save