Browse Source

Merge pull request #103 from pelias/address-details

Detail Param
pull/93/merge 1.2.0
Diana Shkolnikov 10 years ago
parent
commit
d8ac05ea65
  1. 10
      DOCS.md
  2. 2
      controller/doc.js
  3. 2
      controller/search.js
  4. 2
      controller/suggest.js
  5. 33
      helper/geojsonify.js
  6. 39
      sanitiser/_details.js
  7. 4
      sanitiser/_geo.js
  8. 4
      sanitiser/_id.js
  9. 4
      sanitiser/_input.js
  10. 4
      sanitiser/_size.js
  11. 3
      sanitiser/coarse.js
  12. 3
      sanitiser/doc.js
  13. 1
      sanitiser/reverse.js
  14. 1
      sanitiser/search.js
  15. 1
      sanitiser/suggest.js
  16. 54
      test/unit/controller/doc.js
  17. 54
      test/unit/controller/search.js
  18. 64
      test/unit/controller/suggest.js
  19. 84
      test/unit/helper/geojsonify.js
  20. 3
      test/unit/sanitiser/coarse.js
  21. 46
      test/unit/sanitiser/doc.js
  22. 40
      test/unit/sanitiser/reverse.js
  23. 42
      test/unit/sanitiser/search.js
  24. 42
      test/unit/sanitiser/suggest.js

10
DOCS.md

@ -20,7 +20,10 @@ Full text search endpoint which queries the elasticsearch doc store, slightly sl
* can be one of the following comma separated string values * can be one of the following comma separated string values
* bottom left lat, bottom left lon, top right lat, top right lon * bottom left lat, bottom left lon, top right lat, top right lon
* left, bottom, right, top * left, bottom, right, top
* min longitude, min latitude, max longitude, max latitude * min longitude, min latitude, max longitude, max latitude
* **details**: indicates if results should contain detailed, should be `true` or `false`
* when false results will only contain `id`, `layer`, and `text` properties
* when true, all available properties will be included in results
## /search/coarse ## /search/coarse
@ -37,6 +40,7 @@ This is a coarse forward geocoder endpoint which only searches admin dataset lay
* **bbox**: the bounding box frome which you want all your results to come * **bbox**: the bounding box frome which you want all your results to come
* **size**: (defaults to 10) * **size**: (defaults to 10)
* **layers**: (defaults to ```admin```) * **layers**: (defaults to ```admin```)
* **details**: (defaults to `true`)
## /suggest ## /suggest
@ -53,6 +57,7 @@ The autocomplete endpoint, it offers fast response time. Mixes results from arou
* **zoom**: zoom level from which you wish to view the world * **zoom**: zoom level from which you wish to view the world
* **size**: number of results requested (defaults to 10) * **size**: number of results requested (defaults to 10)
* **layers**: datasets you wish to query (defaults to ```poi,admin,address```) * **layers**: datasets you wish to query (defaults to ```poi,admin,address```)
* **details**: (defaults to `true`)
## /suggest/coarse ## /suggest/coarse
@ -69,6 +74,7 @@ Only queries the admin layers.
* **zoom**: zoom level from which you wish to view the world * **zoom**: zoom level from which you wish to view the world
* **size**: number of results requested (defaults to 10) * **size**: number of results requested (defaults to 10)
* **layers**: datasets you wish to query (defaults to ```admin```) * **layers**: datasets you wish to query (defaults to ```admin```)
* **details**: (defaults to `true`)
## /suggest/nearby ## /suggest/nearby
@ -85,6 +91,7 @@ Works as autocomplete for places located near a latitude/longitude, this endpoin
* **zoom**: zoom level from which you wish to view the world * **zoom**: zoom level from which you wish to view the world
* **size**: number of results you need (defaults to 10) * **size**: number of results you need (defaults to 10)
* **layers**: datasets you wish to query (defaults to ```poi,admin,address```) * **layers**: datasets you wish to query (defaults to ```poi,admin,address```)
* **details**: (defaults to `true`)
## /reverse ## /reverse
@ -99,6 +106,7 @@ Reverse geocoding endpoint.
* **zoom**: zoom level from which you wish to view the world * **zoom**: zoom level from which you wish to view the world
* **bbox**: bounding box * **bbox**: bounding box
* **layers**: (defaults to ```poi,admin,address```) * **layers**: (defaults to ```poi,admin,address```)
* **details**: (defaults to `true`)
## /doc ## /doc

2
controller/doc.js

@ -23,7 +23,7 @@ function setup( backend ){
if( err ){ return next( err ); } if( err ){ return next( err ); }
// convert docs to geojson // convert docs to geojson
var geojson = geojsonify( docs ); var geojson = geojsonify( docs, req.clean );
// response envelope // response envelope
geojson.date = new Date().getTime(); geojson.date = new Date().getTime();

2
controller/search.js

@ -28,7 +28,7 @@ function setup( backend, query ){
if( err ){ return next( err ); } if( err ){ return next( err ); }
// convert docs to geojson // convert docs to geojson
var geojson = geojsonify( docs ); var geojson = geojsonify( docs, req.clean );
// response envelope // response envelope
geojson.date = new Date().getTime(); geojson.date = new Date().getTime();

2
controller/suggest.js

@ -27,7 +27,7 @@ function setup( backend, query, query_mixer ){
function reply( docs ){ function reply( docs ){
// convert docs to geojson // convert docs to geojson
var geojson = geojsonify( docs ); var geojson = geojsonify( docs, req.clean );
// response envelope // response envelope
geojson.date = new Date().getTime(); geojson.date = new Date().getTime();

33
helper/geojsonify.js

@ -3,7 +3,7 @@ var GeoJSON = require('geojson'),
extent = require('geojson-extent'), extent = require('geojson-extent'),
outputGenerator = require('./outputGenerator'); outputGenerator = require('./outputGenerator');
function search( docs ){ function search( docs, params ){
// emit a warning if the doc format is invalid // emit a warning if the doc format is invalid
// @note: if you see this error, fix it ASAP! // @note: if you see this error, fix it ASAP!
@ -12,6 +12,9 @@ function search( docs ){
return false; // remove offending doc from results return false; // remove offending doc from results
} }
var details = params ? params.details : {};
details = details === true || details === 1;
// flatten & expand data for geojson conversion // flatten & expand data for geojson conversion
var geodata = docs.map( function( doc ){ var geodata = docs.map( function( doc ){
@ -29,19 +32,21 @@ function search( docs ){
output.lat = parseFloat( doc.center_point.lat ); output.lat = parseFloat( doc.center_point.lat );
output.lng = parseFloat( doc.center_point.lon ); output.lng = parseFloat( doc.center_point.lon );
// map name if (details) {
if( !doc.name || !doc.name.default ) { return warning(); } // map name
output.name = doc.name.default; if( !doc.name || !doc.name.default ) { return warning(); }
output.name = doc.name.default;
// map admin values
if( doc.alpha3 ){ output.alpha3 = doc.alpha3; } // map admin values
if( doc.admin0 ){ output.admin0 = doc.admin0; } if( doc.alpha3 ){ output.alpha3 = doc.alpha3; }
if( doc.admin1 ){ output.admin1 = doc.admin1; } if( doc.admin0 ){ output.admin0 = doc.admin0; }
if( doc.admin1_abbr ){ output.admin1_abbr = doc.admin1_abbr; } if( doc.admin1 ){ output.admin1 = doc.admin1; }
if( doc.admin2 ){ output.admin2 = doc.admin2; } if( doc.admin1_abbr ){ output.admin1_abbr = doc.admin1_abbr; }
if( doc.local_admin ){ output.local_admin = doc.local_admin; } if( doc.admin2 ){ output.admin2 = doc.admin2; }
if( doc.locality ){ output.locality = doc.locality; } if( doc.local_admin ){ output.local_admin = doc.local_admin; }
if( doc.neighborhood ){ output.neighborhood = doc.neighborhood; } if( doc.locality ){ output.locality = doc.locality; }
if( doc.neighborhood ){ output.neighborhood = doc.neighborhood; }
}
// generate region-specific text string // generate region-specific text string
output.text = outputGenerator( doc ); output.text = outputGenerator( doc );

39
sanitiser/_details.js

@ -0,0 +1,39 @@
var isObject = require('is-object');
// validate inputs, convert types and apply defaults
function sanitize( req, default_value ){
var clean = req.clean || {};
var params= req.query;
if (default_value === undefined) {
default_value = true;
}
default_value = !!default_value;
// ensure the input params are a valid object
if( !isObject( params ) ){
params = {};
}
if (params.details !== undefined) {
var details = params.details;
if (typeof params.details === 'string') {
details = params.details === 'true';
}
clean.details = details === true || details === 1;
} else {
clean.details = default_value;
}
req.clean = clean;
return {'error':false};
}
// export function
module.exports = sanitize;

4
sanitiser/_geo.js

@ -1,3 +1,5 @@
var isObject = require('is-object');
// validate inputs, convert types and apply defaults // validate inputs, convert types and apply defaults
function sanitize( req, latlon_is_required ){ function sanitize( req, latlon_is_required ){
@ -6,7 +8,7 @@ function sanitize( req, latlon_is_required ){
latlon_is_required = latlon_is_required || false; latlon_is_required = latlon_is_required || false;
// ensure the input params are a valid object // ensure the input params are a valid object
if( Object.prototype.toString.call( params ) !== '[object Object]' ){ if( !isObject( params ) ){
params = {}; params = {};
} }

4
sanitiser/_id.js

@ -1,3 +1,5 @@
var isObject = require('is-object');
// validate inputs, convert types and apply defaults // validate inputs, convert types and apply defaults
// id generally looks like 'geoname:4163334' (type:id) // id generally looks like 'geoname:4163334' (type:id)
// so, both type and id are required fields. // so, both type and id are required fields.
@ -10,7 +12,7 @@ function sanitize( req ){
var delim = ':'; var delim = ':';
// ensure params is a valid object // ensure params is a valid object
if( Object.prototype.toString.call( params ) !== '[object Object]' ){ if( !isObject( params ) ){
params = {}; params = {};
} }

4
sanitiser/_input.js

@ -1,3 +1,5 @@
var isObject = require('is-object');
// validate inputs, convert types and apply defaults // validate inputs, convert types and apply defaults
function sanitize( req ){ function sanitize( req ){
@ -6,7 +8,7 @@ function sanitize( req ){
var delim = ','; var delim = ',';
// ensure the input params are a valid object // ensure the input params are a valid object
if( Object.prototype.toString.call( params ) !== '[object Object]' ){ if( !isObject( params ) ){
params = {}; params = {};
} }

4
sanitiser/_size.js

@ -1,3 +1,5 @@
var isObject = require('is-object');
// validate inputs, convert types and apply defaults // validate inputs, convert types and apply defaults
function sanitize( req, default_size){ function sanitize( req, default_size){
@ -7,7 +9,7 @@ function sanitize( req, default_size){
default_size = default_size || 10; default_size = default_size || 10;
// ensure the input params are a valid object // ensure the input params are a valid object
if( Object.prototype.toString.call( params ) !== '[object Object]' ){ if( !isObject( params ) ){
params = {}; params = {};
} }

3
sanitiser/coarse.js

@ -9,7 +9,8 @@ var logger = require('../src/logger'),
var layers = require('../sanitiser/_layers'); var layers = require('../sanitiser/_layers');
return layers(req); return layers(req);
}, },
latlonzoom: require('../sanitiser/_geo') latlonzoom: require('../sanitiser/_geo'),
details: require('../sanitiser/_details')
}; };
var sanitize = function(req, cb) { _sanitize(req, sanitizers, cb); }; var sanitize = function(req, cb) { _sanitize(req, sanitizers, cb); };

3
sanitiser/doc.js

@ -2,7 +2,8 @@
var logger = require('../src/logger'), var logger = require('../src/logger'),
_sanitize = require('../sanitiser/_sanitize'), _sanitize = require('../sanitiser/_sanitize'),
sanitizers = { sanitizers = {
id: require('../sanitiser/_id') id: require('../sanitiser/_id'),
details: require('../sanitiser/_details')
}; };
var sanitize = function(req, cb) { _sanitize(req, sanitizers, cb); }; var sanitize = function(req, cb) { _sanitize(req, sanitizers, cb); };

1
sanitiser/reverse.js

@ -6,6 +6,7 @@ var _sanitize = require('../sanitiser/_sanitize'),
return geo(req, true); return geo(req, true);
}, },
layers: require('../sanitiser/_layers'), layers: require('../sanitiser/_layers'),
details: require('../sanitiser/_details'),
size: function( req ) { size: function( req ) {
var size = require('../sanitiser/_size'); var size = require('../sanitiser/_size');
return size(req, 1); return size(req, 1);

1
sanitiser/search.js

@ -5,6 +5,7 @@ var logger = require('../src/logger'),
input: require('../sanitiser/_input'), input: require('../sanitiser/_input'),
size: require('../sanitiser/_size'), size: require('../sanitiser/_size'),
layers: require('../sanitiser/_layers'), layers: require('../sanitiser/_layers'),
details: require('../sanitiser/_details'),
latlonzoom: require('../sanitiser/_geo') latlonzoom: require('../sanitiser/_geo')
}; };

1
sanitiser/suggest.js

@ -5,6 +5,7 @@ var logger = require('../src/logger'),
input: require('../sanitiser/_input'), input: require('../sanitiser/_input'),
size: require('../sanitiser/_size'), size: require('../sanitiser/_size'),
layers: require('../sanitiser/_layers'), layers: require('../sanitiser/_layers'),
details: require('../sanitiser/_details'),
latlonzoom: function( req ) { latlonzoom: function( req ) {
var geo = require('../sanitiser/_geo'); var geo = require('../sanitiser/_geo');
return geo(req, true); return geo(req, true);

54
test/unit/controller/doc.js

@ -17,6 +17,52 @@ module.exports.tests.functional_success = function(test, common) {
// expected geojson features for 'client/doc/ok/1' fixture // expected geojson features for 'client/doc/ok/1' fixture
var expected = [{ var expected = [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ -50.5, 100.1 ]
},
properties: {
id: 'myid1',
layer: 'mytype1',
text: 'test name1, city1, state1'
}
}, {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ -51.5, 100.2 ]
},
properties: {
id: 'myid2',
layer: 'mytype2',
text: 'test name2, city2, state2'
}
}];
test('functional success', function(t) {
var backend = mockBackend( 'client/mget/ok/1', function( cmd ){
t.deepEqual(cmd, { body: { docs: [ { _id: 123, _index: 'pelias', _type: 'a' } ] } }, 'correct backend command');
});
var controller = setup( backend );
var res = {
status: function( code ){
t.equal(code, 200, 'status set');
return res;
},
json: function( json ){
t.equal(typeof json, 'object', 'returns json');
t.equal(typeof json.date, 'number', 'date set');
t.equal(json.type, 'FeatureCollection', 'valid geojson');
t.true(Array.isArray(json.features), 'features is array');
t.deepEqual(json.features, expected, 'values correctly mapped');
t.end();
}
};
controller( { clean: { ids: [ {'id' : 123, 'type': 'a' } ] } }, res );
});
var detailed_expectation = [{
type: 'Feature', type: 'Feature',
geometry: { geometry: {
type: 'Point', type: 'Point',
@ -47,8 +93,8 @@ module.exports.tests.functional_success = function(test, common) {
text: 'test name2, city2, state2' text: 'test name2, city2, state2'
} }
}]; }];
test('functional success', function(t) { test('functional success (with details)', function(t) {
var backend = mockBackend( 'client/mget/ok/1', function( cmd ){ var backend = mockBackend( 'client/mget/ok/1', function( cmd ){
t.deepEqual(cmd, { body: { docs: [ { _id: 123, _index: 'pelias', _type: 'a' } ] } }, 'correct backend command'); t.deepEqual(cmd, { body: { docs: [ { _id: 123, _index: 'pelias', _type: 'a' } ] } }, 'correct backend command');
}); });
@ -63,11 +109,11 @@ module.exports.tests.functional_success = function(test, common) {
t.equal(typeof json.date, 'number', 'date set'); t.equal(typeof json.date, 'number', 'date set');
t.equal(json.type, 'FeatureCollection', 'valid geojson'); t.equal(json.type, 'FeatureCollection', 'valid geojson');
t.true(Array.isArray(json.features), 'features is array'); t.true(Array.isArray(json.features), 'features is array');
t.deepEqual(json.features, expected, 'values correctly mapped'); t.deepEqual(json.features, detailed_expectation, 'values correctly mapped along with details');
t.end(); t.end();
} }
}; };
controller( { clean: { ids: [ {'id' : 123, 'type': 'a' } ] } }, res ); controller( { clean: { ids: [ {'id' : 123, 'type': 'a' } ], details: true } }, res );
}); });
}; };

54
test/unit/controller/search.js

@ -18,6 +18,52 @@ module.exports.tests.functional_success = function(test, common) {
// expected geojson features for 'client/suggest/ok/1' fixture // expected geojson features for 'client/suggest/ok/1' fixture
var expected = [{ var expected = [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ -50.5, 100.1 ]
},
properties: {
id: 'myid1',
layer: 'mytype1',
text: 'test name1, city1, state1'
}
}, {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ -51.5, 100.2 ]
},
properties: {
id: 'myid2',
layer: 'mytype2',
text: 'test name2, city2, state2'
}
}];
test('functional success', function(t) {
var backend = mockBackend( 'client/search/ok/1', function( cmd ){
t.deepEqual(cmd, { body: { a: 'b' }, index: 'pelias', searchType: 'dfs_query_then_fetch' }, 'correct backend command');
});
var controller = setup( backend, mockQuery() );
var res = {
status: function( code ){
t.equal(code, 200, 'status set');
return res;
},
json: function( json ){
t.equal(typeof json, 'object', 'returns json');
t.equal(typeof json.date, 'number', 'date set');
t.equal(json.type, 'FeatureCollection', 'valid geojson');
t.true(Array.isArray(json.features), 'features is array');
t.deepEqual(json.features, expected, 'values correctly mapped');
t.end();
}
};
controller( { clean: { a: 'b' } }, res );
});
var detailed_expectation = [{
type: 'Feature', type: 'Feature',
geometry: { geometry: {
type: 'Point', type: 'Point',
@ -49,9 +95,9 @@ module.exports.tests.functional_success = function(test, common) {
} }
}]; }];
test('functional success', function(t) { test('functional success (with details)', 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', searchType: 'dfs_query_then_fetch' }, 'correct backend command'); t.deepEqual(cmd, { body: { a: 'b', details: true }, index: 'pelias', searchType: 'dfs_query_then_fetch' }, 'correct backend command');
}); });
var controller = setup( backend, mockQuery() ); var controller = setup( backend, mockQuery() );
var res = { var res = {
@ -64,11 +110,11 @@ module.exports.tests.functional_success = function(test, common) {
t.equal(typeof json.date, 'number', 'date set'); t.equal(typeof json.date, 'number', 'date set');
t.equal(json.type, 'FeatureCollection', 'valid geojson'); t.equal(json.type, 'FeatureCollection', 'valid geojson');
t.true(Array.isArray(json.features), 'features is array'); t.true(Array.isArray(json.features), 'features is array');
t.deepEqual(json.features, expected, 'values correctly mapped'); t.deepEqual(json.features, detailed_expectation, 'values with details correctly mapped');
t.end(); t.end();
} }
}; };
controller( { clean: { a: 'b' } }, res ); controller( { clean: { a: 'b', details: true } }, res );
}); });
}; };

64
test/unit/controller/suggest.js

@ -18,6 +18,62 @@ module.exports.tests.functional_success = function(test, common) {
// expected geojson features for 'client/mget/ok/1' fixture // expected geojson features for 'client/mget/ok/1' fixture
var expected = [{ var expected = [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ -50.5, 100.1 ]
},
properties: {
id: 'myid1',
layer: 'mytype1',
text: 'test name1, city1, state1'
}
}, {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ -51.5, 100.2 ]
},
properties: {
id: 'myid2',
layer: 'mytype2',
text: 'test name2, city2, state2'
}
}];
test('functional success', function(t) {
var backend = mockBackend( 'client/suggest/ok/1', function( cmd ){
// the backend executes suggest (vanilla and admin-only) and mget, so we check them all based on cmd
if( cmd.body.docs ){
t.deepEqual(cmd, {
body: { docs: [
{ _id: 'mockid1', _index: 'pelias', _type: 'mocktype' },
{ _id: 'mockid2', _index: 'pelias', _type: 'mocktype' }
]}
}, 'correct mget command');
} else {
t.deepEqual(cmd, { body: { input: 'b' }, index: 'pelias' }, 'correct suggest command');
}
});
var controller = setup( backend, mockQuery() );
var res = {
status: function( code ){
t.equal(code, 200, 'status set');
return res;
},
json: function( json ){
t.equal(typeof json, 'object', 'returns json');
t.equal(typeof json.date, 'number', 'date set');
t.equal(json.type, 'FeatureCollection', 'valid geojson');
t.true(Array.isArray(json.features), 'features is array');
t.deepEqual(json.features, expected, 'values correctly mapped');
t.end();
}
};
controller( { clean: { input: 'b' } }, res );
});
var detailed_expectation = [{
type: 'Feature', type: 'Feature',
geometry: { geometry: {
type: 'Point', type: 'Point',
@ -49,7 +105,7 @@ module.exports.tests.functional_success = function(test, common) {
} }
}]; }];
test('functional success', function(t) { test('functional success (with details)', function(t) {
var backend = mockBackend( 'client/suggest/ok/1', function( cmd ){ var backend = mockBackend( 'client/suggest/ok/1', function( cmd ){
// the backend executes suggest (vanilla and admin-only) and mget, so we check them all based on cmd // the backend executes suggest (vanilla and admin-only) and mget, so we check them all based on cmd
if( cmd.body.docs ){ if( cmd.body.docs ){
@ -60,7 +116,7 @@ module.exports.tests.functional_success = function(test, common) {
]} ]}
}, 'correct mget command'); }, 'correct mget command');
} else { } else {
t.deepEqual(cmd, { body: { input: 'b' }, index: 'pelias' }, 'correct suggest command'); t.deepEqual(cmd, { body: { input: 'b', details: true }, index: 'pelias' }, 'correct suggest command');
} }
}); });
var controller = setup( backend, mockQuery() ); var controller = setup( backend, mockQuery() );
@ -74,11 +130,11 @@ module.exports.tests.functional_success = function(test, common) {
t.equal(typeof json.date, 'number', 'date set'); t.equal(typeof json.date, 'number', 'date set');
t.equal(json.type, 'FeatureCollection', 'valid geojson'); t.equal(json.type, 'FeatureCollection', 'valid geojson');
t.true(Array.isArray(json.features), 'features is array'); t.true(Array.isArray(json.features), 'features is array');
t.deepEqual(json.features, expected, 'values correctly mapped'); t.deepEqual(json.features, detailed_expectation, 'values with details correctly mapped');
t.end(); t.end();
} }
}; };
controller( { clean: { input: 'b' } }, res ); controller( { clean: { input: 'b', details: true } }, res );
}); });
}; };

84
test/unit/helper/geojsonify.js

@ -6,7 +6,7 @@ module.exports.tests = {};
module.exports.tests.interface = function(test, common) { module.exports.tests.interface = function(test, common) {
test('valid interface .search()', function(t) { test('valid interface .search()', function(t) {
t.equal(typeof geojsonify.search, 'function', 'search is a function'); t.equal(typeof geojsonify.search, 'function', 'search is a function');
t.equal(geojsonify.search.length, 1, 'accepts x arguments'); t.equal(geojsonify.search.length, 2, 'accepts x arguments');
t.end(); t.end();
}); });
}; };
@ -178,11 +178,89 @@ module.exports.tests.search = function(test, common) {
] ]
}; };
test('geojsonify.search()', function(t) { var truthy_params = [true, 1];
test('geojsonify.search(doc, true) with details', function(t) {
var json = geojsonify.search( input, { details: true } );
t.deepEqual(json, expected, 'all docs (with details) mapped');
t.end();
});
truthy_params.forEach(function(details) {
test('geojsonify.search(doc, '+ details +') with details', function(t) {
var json = geojsonify.search( input, { details: details } );
t.deepEqual(json, expected, 'all docs (with details) mapped');
t.end();
});
});
var no_details_expected = {
'type': 'FeatureCollection',
'bbox': [ -73.985656, 40.748432, -0.101795, 51.5337144 ],
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [
-0.1069716,
51.5337144
]
},
'properties': {
'id': 'id1',
'layer': 'type1',
'text': '\'Round Midnight Jazz and Blues Bar, test3, Angel'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [
-0.101795,
51.517806
]
},
'properties': {
'id': 'id2',
'layer': 'type2',
'text': 'Blues Cafe, test3, Smithfield'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [
-73.985656,
40.748432
]
},
'properties': {
'id': '34633854',
'layer': 'osmway',
'text': 'Empire State Building, Manhattan, NY'
}
}
]
};
test('geojsonify.search(doc) with no details (default)', function(t) {
var json = geojsonify.search( input ); var json = geojsonify.search( input );
t.deepEqual(json, expected, 'all docs mapped'); t.deepEqual(json, no_details_expected, 'all docs (with no details) mapped');
t.end(); t.end();
}); });
var falsy_params = [false, undefined, null, 0, -1, 123, 'abc'];
falsy_params.forEach(function(details) {
test('geojsonify.search(doc, '+ details +') with no details', function(t) {
var json = geojsonify.search( input, { details: details } );
t.deepEqual(json, no_details_expected, 'all docs (with no details) mapped');
t.end();
});
});
}; };
module.exports.all = function (tape, common) { module.exports.all = function (tape, common) {

3
test/unit/sanitiser/coarse.js

@ -53,7 +53,8 @@ module.exports.tests.middleware_success = function(test, common) {
size: 10, size: 10,
layers: [ 'admin0', 'admin1', 'admin2', 'neighborhood', 'locality', 'local_admin' ], layers: [ 'admin0', 'admin1', 'admin2', 'neighborhood', 'locality', 'local_admin' ],
lat: 0, lat: 0,
lon: 0 lon: 0,
details: true
}; };
t.equal(message, undefined, 'no error message set'); t.equal(message, undefined, 'no error message set');
t.deepEqual(req.clean, defaultClean); t.deepEqual(req.clean, defaultClean);

46
test/unit/sanitiser/doc.js

@ -10,7 +10,7 @@ var doc = require('../../../sanitiser/doc'),
defaultMissingTypeError = function(input) { defaultMissingTypeError = function(input) {
var type = input.split(delimiter)[0]; var type = input.split(delimiter)[0];
return type + ' is invalid. It must be one of these values - [' + indeces.join(', ') + ']'; }, return type + ' is invalid. It must be one of these values - [' + indeces.join(', ') + ']'; },
defaultClean = { ids: [ { id: '123', type: 'geoname' } ] }, defaultClean = { ids: [ { id: '123', type: 'geoname' } ], details: true },
sanitize = function(query, cb) { _sanitize({'query':query}, cb); }, sanitize = function(query, cb) { _sanitize({'query':query}, cb); },
inputs = { inputs = {
valid: [ 'geoname:1', 'osmnode:2', 'admin0:53', 'osmway:44', 'geoname:5' ], valid: [ 'geoname:1', 'osmnode:2', 'admin0:53', 'osmway:44', 'geoname:5' ],
@ -56,7 +56,7 @@ module.exports.tests.sanitize_id = function(test, common) {
test('valid input', function(t) { test('valid input', function(t) {
inputs.valid.forEach( function( input ){ inputs.valid.forEach( function( input ){
var input_parts = input.split(delimiter); var input_parts = input.split(delimiter);
var expected = { ids: [ { id: input_parts[1], type: input_parts[0] } ] }; var expected = { ids: [ { id: input_parts[1], type: input_parts[0] } ], details: true };
sanitize({ id: input }, function( err, clean ){ sanitize({ id: input }, function( err, clean ){
t.equal(err, undefined, 'no error (' + input + ')' ); t.equal(err, undefined, 'no error (' + input + ')' );
t.deepEqual(clean, expected, 'clean set correctly (' + input + ')'); t.deepEqual(clean, expected, 'clean set correctly (' + input + ')');
@ -94,6 +94,7 @@ module.exports.tests.sanitize_ids = function(test, common) {
var input_parts = input.split(delimiter); var input_parts = input.split(delimiter);
expected.ids.push({ id: input_parts[1], type: input_parts[0] }); expected.ids.push({ id: input_parts[1], type: input_parts[0] });
}); });
expected.details = true;
sanitize({ id: inputs.valid }, function( err, clean ){ sanitize({ id: inputs.valid }, function( err, clean ){
t.equal(err, undefined, 'no error' ); t.equal(err, undefined, 'no error' );
t.deepEqual(clean, expected, 'clean set correctly'); t.deepEqual(clean, expected, 'clean set correctly');
@ -102,8 +103,47 @@ module.exports.tests.sanitize_ids = function(test, common) {
}); });
}; };
module.exports.tests.sanitize_details = function(test, common) {
var invalid_values = [null, -1, 123, NaN, 'abc'];
invalid_values.forEach(function(details) {
test('invalid details param ' + details, function(t) {
sanitize({ id:'geoname:123', details: details }, function( err, clean ){
t.equal(clean.details, false, 'default details set (to false)');
t.end();
});
});
});
var valid_values = ['true', true, 1];
valid_values.forEach(function(details) {
test('valid details param ' + details, function(t) {
sanitize({ id:'geoname:123', details: details }, function( err, clean ){
t.equal(clean.details, true, 'details set to true');
t.end();
});
});
});
var valid_false_values = ['false', false, 0];
valid_false_values.forEach(function(details) {
test('test setting false explicitly ' + details, function(t) {
sanitize({ id:'geoname:123', details: details }, function( err, clean ){
t.equal(clean.details, false, 'details set to false');
t.end();
});
});
});
test('test default behavior', function(t) {
sanitize({ id:'geoname:123' }, function( err, clean ){
t.equal(clean.details, true, 'details set to true');
t.end();
});
});
};
module.exports.tests.de_dupe = function(test, common) { module.exports.tests.de_dupe = function(test, common) {
var expected = { ids: [ { id: '1', type: 'geoname' }, { id: '2', type: 'osmnode' } ] }; var expected = { ids: [ { id: '1', type: 'geoname' }, { id: '2', type: 'osmnode' } ], details: true };
test('duplicate ids', function(t) { test('duplicate ids', function(t) {
sanitize( { id: ['geoname:1', 'osmnode:2', 'geoname:1'] }, function( err, clean ){ sanitize( { id: ['geoname:1', 'osmnode:2', 'geoname:1'] }, function( err, clean ){
t.equal(err, undefined, 'no error' ); t.equal(err, undefined, 'no error' );

40
test/unit/sanitiser/reverse.js

@ -9,6 +9,7 @@ var suggest = require('../../../sanitiser/reverse'),
'locality', 'local_admin', 'osmaddress', 'openaddresses' ], 'locality', 'local_admin', 'osmaddress', 'openaddresses' ],
lon: 0, lon: 0,
size: 1, size: 1,
details: true,
categories: [] categories: []
}, },
sanitize = function(query, cb) { _sanitize({'query':query}, cb); }; sanitize = function(query, cb) { _sanitize({'query':query}, cb); };
@ -125,6 +126,45 @@ module.exports.tests.sanitize_size = function(test, common) {
}); });
}; };
module.exports.tests.sanitize_details = function(test, common) {
var invalid_values = [null, -1, 123, NaN, 'abc'];
invalid_values.forEach(function(details) {
test('invalid details param ' + details, function(t) {
sanitize({ input: 'test', lat: 0, lon: 0, details: details }, function( err, clean ){
t.equal(clean.details, false, 'details set to false');
t.end();
});
});
});
var valid_values = [true, 'true', 1];
valid_values.forEach(function(details) {
test('valid details param ' + details, function(t) {
sanitize({ input: 'test', lat: 0, lon: 0, details: details }, function( err, clean ){
t.equal(clean.details, true, 'details set to true');
t.end();
});
});
});
test('test default behavior', function(t) {
sanitize({ input: 'test', lat: 0, lon: 0 }, function( err, clean ){
t.equal(clean.details, true, 'details set to true');
t.end();
});
});
var valid_false_values = ['false', false, 0];
valid_false_values.forEach(function(details) {
test('test setting false explicitly ' + details, function(t) {
sanitize({ input: 'test', lat: 0, lon: 0, details: details }, function( err, clean ){
t.equal(clean.details, false, 'details set to false');
t.end();
});
});
});
};
module.exports.tests.sanitize_layers = function(test, common) { module.exports.tests.sanitize_layers = function(test, common) {
test('unspecified', function(t) { test('unspecified', function(t) {
sanitize({ layers: undefined, input: 'test', lat: 0, lon: 0 }, function( err, clean ){ sanitize({ layers: undefined, input: 'test', lat: 0, lon: 0 }, function( err, clean ){

42
test/unit/sanitiser/search.js

@ -7,7 +7,8 @@ var search = require('../../../sanitiser/search'),
defaultClean = { input: 'test', defaultClean = { input: 'test',
layers: [ 'geoname', 'osmnode', 'osmway', 'admin0', 'admin1', 'admin2', 'neighborhood', layers: [ 'geoname', 'osmnode', 'osmway', 'admin0', 'admin1', 'admin2', 'neighborhood',
'locality', 'local_admin', 'osmaddress', 'openaddresses' ], 'locality', 'local_admin', 'osmaddress', 'openaddresses' ],
size: 10 size: 10,
details: true
}, },
sanitize = function(query, cb) { _sanitize({'query':query}, cb); }; sanitize = function(query, cb) { _sanitize({'query':query}, cb); };
@ -266,6 +267,45 @@ module.exports.tests.sanitize_size = function(test, common) {
}); });
}; };
module.exports.tests.sanitize_details = function(test, common) {
var invalid_values = [null, -1, 123, NaN, 'abc'];
invalid_values.forEach(function(details) {
test('invalid details param ' + details, function(t) {
sanitize({ input: 'test', lat: 0, lon: 0, details: details }, function( err, clean ){
t.equal(clean.details, false, 'default details set (to false)');
t.end();
});
});
});
var valid_values = ['true', true, 1];
valid_values.forEach(function(details) {
test('valid details param ' + details, function(t) {
sanitize({ input: 'test', lat: 0, lon: 0, details: details }, function( err, clean ){
t.equal(clean.details, true, 'details set to true');
t.end();
});
});
});
var valid_false_values = ['false', false, 0];
valid_false_values.forEach(function(details) {
test('test setting false explicitly ' + details, function(t) {
sanitize({ input: 'test', lat: 0, lon: 0, details: details }, function( err, clean ){
t.equal(clean.details, false, 'details set to false');
t.end();
});
});
});
test('test default behavior', function(t) {
sanitize({ input: 'test', lat: 0, lon: 0 }, function( err, clean ){
t.equal(clean.details, true, 'details set to true');
t.end();
});
});
};
module.exports.tests.sanitize_layers = function(test, common) { module.exports.tests.sanitize_layers = function(test, common) {
test('unspecified', function(t) { test('unspecified', function(t) {
sanitize({ layers: undefined, input: 'test' }, function( err, clean ){ sanitize({ layers: undefined, input: 'test' }, function( err, clean ){

42
test/unit/sanitiser/suggest.js

@ -9,7 +9,8 @@ var suggest = require('../../../sanitiser/suggest'),
layers: [ 'geoname', 'osmnode', 'osmway', 'admin0', 'admin1', 'admin2', 'neighborhood', layers: [ 'geoname', 'osmnode', 'osmway', 'admin0', 'admin1', 'admin2', 'neighborhood',
'locality', 'local_admin', 'osmaddress', 'openaddresses' ], 'locality', 'local_admin', 'osmaddress', 'openaddresses' ],
lon: 0, lon: 0,
size: 10 size: 10,
details: true
}, },
sanitize = function(query, cb) { _sanitize({'query':query}, cb); }; sanitize = function(query, cb) { _sanitize({'query':query}, cb); };
@ -235,6 +236,45 @@ module.exports.tests.sanitize_size = function(test, common) {
}); });
}; };
module.exports.tests.sanitize_details = function(test, common) {
var invalid_values = [null, -1, 123, NaN, 'abc'];
invalid_values.forEach(function(details) {
test('invalid details param ' + details, function(t) {
sanitize({ input: 'test', lat: 0, lon: 0, details: details }, function( err, clean ){
t.equal(clean.details, false, 'default details set (to false)');
t.end();
});
});
});
var valid_values = ['true', true, 1];
valid_values.forEach(function(details) {
test('valid details param ' + details, function(t) {
sanitize({ input: 'test', lat: 0, lon: 0, details: details }, function( err, clean ){
t.equal(clean.details, true, 'details set to true');
t.end();
});
});
});
var valid_false_values = ['false', false, 0];
valid_false_values.forEach(function(details) {
test('test setting false explicitly ' + details, function(t) {
sanitize({ input: 'test', lat: 0, lon: 0, details: details }, function( err, clean ){
t.equal(clean.details, false, 'details set to false');
t.end();
});
});
});
test('test default behavior', function(t) {
sanitize({ input: 'test', lat: 0, lon: 0 }, function( err, clean ){
t.equal(clean.details, true, 'details set to true');
t.end();
});
});
};
module.exports.tests.sanitize_layers = function(test, common) { module.exports.tests.sanitize_layers = function(test, common) {
test('unspecified', function(t) { test('unspecified', function(t) {
sanitize({ layers: undefined, input: 'test', lat: 0, lon: 0 }, function( err, clean ){ sanitize({ layers: undefined, input: 'test', lat: 0, lon: 0 }, function( err, clean ){

Loading…
Cancel
Save