Browse Source

geojsonify suggest API

pull/12/head
Peter Johnson 10 years ago
parent
commit
42ac5f05eb
  1. 55
      controller/suggest.js
  2. 1
      package.json
  3. 9
      test/ciao/suggest/success.coffee
  4. 36
      test/unit/controller/suggest.js
  5. 7
      test/unit/mock/backend.js

55
controller/suggest.js

@ -1,4 +1,6 @@
var GeoJSON = require('geojson');
function setup( backend, query ){ function setup( backend, query ){
// allow overriding of dependencies // allow overriding of dependencies
@ -26,10 +28,15 @@ function setup( backend, query ){
docs = data['pelias'][0].options || []; docs = data['pelias'][0].options || [];
} }
// respond // convert docs to geojson
return res.status(200).json({ geoJsonifyDocs( docs, function( geojson ){
date: new Date().getTime(),
body: docs // response envelope
geojson.date = new Date().getTime();
// respond
return res.status(200).json( geojson );
}); });
}); });
@ -38,4 +45,44 @@ function setup( backend, query ){
return controller; return controller;
} }
function geoJsonifyDocs( docs, cb ){
// 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 ){
// something went very wrong
if( !doc || !doc.payload ) return warning();
// split payload id string in to geojson properties
if( 'string' !== typeof doc.payload.id ) return warning();
var idParts = doc.payload.id.split('/');
doc.type = idParts[0];
doc.id = idParts[1];
// split payload geo string in to geojson properties
if( 'string' !== typeof doc.payload.geo ) return warning();
var geoParts = doc.payload.geo.split(',');
doc.lat = parseFloat( geoParts[0] );
doc.lng = parseFloat( geoParts[1] );
// remove payload from doc
delete doc.payload;
return doc;
// filter-out invalid entries
}).filter( function( doc ){
return doc;
});
// convert to geojson
GeoJSON.parse( geodata, { Point: ['lat', 'lng'] }, cb );
}
module.exports = setup; module.exports = setup;

1
package.json

@ -33,6 +33,7 @@
}, },
"dependencies": { "dependencies": {
"express": "^4.8.8", "express": "^4.8.8",
"geojson": "https://github.com/missinglink/GeoJSON.js/tarball/master",
"geopipes-elasticsearch-backend": "0.0.7", "geopipes-elasticsearch-backend": "0.0.7",
"pelias-esclient": "0.0.25", "pelias-esclient": "0.0.25",
"toobusy": "^0.2.4" "toobusy": "^0.2.4"

9
test/ciao/suggest/success.coffee

@ -9,7 +9,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

36
test/unit/controller/suggest.js

@ -15,7 +15,33 @@ 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: [ -10.1, 101 ]
},
properties: {
id: 'mockid',
type: 'mocktype',
value: 1
}
}, {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ -10.1, 101 ]
},
properties: {
id: 'mockid',
type: 'mocktype',
value: 2
}
}];
test('functional success', function(t) {
var backend = mockBackend( 'client/suggest/ok/1', function( cmd ){ var backend = mockBackend( 'client/suggest/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');
}); });
@ -26,10 +52,12 @@ module.exports.tests.functional_success = function(test, common) {
return res; return res;
}, },
json: function( json ){ json: function( json ){
console.log(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 +67,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/suggest/fail/1', function( cmd ){ var backend = mockBackend( 'client/suggest/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');
}); });

7
test/unit/mock/backend.js

@ -1,7 +1,12 @@
var mockPayload = {
id: 'mocktype/mockid',
geo: '101,-10.1'
};
var responses = {}; var responses = {};
responses['client/suggest/ok/1'] = function( cmd, cb ){ responses['client/suggest/ok/1'] = function( cmd, cb ){
return cb( undefined, suggestEnvelope([ { value: 1 }, { value: 2 } ]) ); return cb( undefined, suggestEnvelope([ { value: 1, payload: mockPayload }, { value: 2, payload: mockPayload } ]) );
}; };
responses['client/suggest/fail/1'] = function( cmd, cb ){ responses['client/suggest/fail/1'] = function( cmd, cb ){
return cb( 'a backend error occurred' ); return cb( 'a backend error occurred' );

Loading…
Cancel
Save