Browse Source

merge with master

pull/250/head
Peter Johnson 9 years ago
parent
commit
e726636c3d
  1. 3
      controller/status.js
  2. 2
      package.json
  3. 8
      routes/v1.js
  4. 35
      sanitiser/_categories.js
  5. 35
      sanitiser/_details.js
  6. 11
      sanitiser/_geo_common.js
  7. 37
      sanitiser/_geo_reverse.js
  8. 37
      sanitiser/_geo_search.js
  9. 129
      sanitiser/_id.js
  10. 17
      sanitiser/_sanitize.js
  11. 53
      sanitiser/_size.js
  12. 102
      sanitiser/_targets.js
  13. 41
      sanitiser/_text.js
  14. 7
      sanitiser/place.js
  15. 26
      sanitiser/reverse.js
  16. 26
      sanitiser/sanitizeAll.js
  17. 14
      sanitiser/search.js
  18. 89
      test/unit/sanitiser/_layers.js
  19. 69
      test/unit/sanitiser/_sources.js
  20. 10
      test/unit/sanitiser/reverse.js
  21. 2
      test/unit/sanitiser/search.js

3
controller/status.js

@ -0,0 +1,3 @@
module.exports = function controller( req, res, next) {
res.send('status: ok');
};

2
package.json

@ -35,6 +35,7 @@
"dependencies": {
"addressit": "1.3.0",
"async": "^0.9.0",
"check-types": "^3.3.1",
"cluster2": "git://github.com/missinglink/cluster2.git#node_zero_twelve",
"express": "^4.8.8",
"express-http-proxy": "^0.6.0",
@ -43,7 +44,6 @@
"geojson-extent": "^0.3.1",
"geolib": "^2.0.18",
"geopipes-elasticsearch-backend": "^0.2.0",
"is-object": "^1.0.1",
"lodash": "^3.10.1",
"markdown": "0.5.0",
"microtime": "1.4.0",

8
routes/v1.js

@ -19,7 +19,8 @@ var middleware = {
var controllers = {
mdToHTML: require('../controller/markdownToHtml'),
place: require('../controller/place'),
search: require('../controller/search')
search: require('../controller/search'),
status: require('../controller/status')
};
/** ----------------------- controllers ----------------------- **/
@ -83,6 +84,9 @@ function addRoutes(app, peliasConfig) {
postProc.renamePlacenames(),
postProc.geocodeJSON(peliasConfig),
postProc.sendJSON
]),
status: createRouter([
controllers.status
])
};
@ -97,6 +101,8 @@ function addRoutes(app, peliasConfig) {
app.get ( base + 'search', routers.search );
app.post( base + 'search', routers.search );
app.get ( base + 'reverse', routers.reverse );
app.get ( '/status', routers.status );
}
/**

35
sanitiser/_categories.js

@ -1,36 +1,33 @@
var isObject = require('is-object');
var check = require('check-types');
// validate inputs, convert types and apply defaults
function sanitize( req ){
function sanitize( raw, clean ){
var clean = req.clean || {};
var params= req.query;
// ensure the input params are a valid object
if( !isObject( params ) ){
params = {};
}
// error & warning messages
var messages = { errors: [], warnings: [] };
// default case (no categories specified in GET params)
if('string' !== typeof params.categories || !params.categories.length){
clean.categories = [];
}
else {
// parse GET params
clean.categories = params.categories.split(',')
clean.categories = [];
// if categories string has been set
if( check.unemptyString( raw.categories ) ){
// map input categories to valid format
clean.categories = raw.categories.split(',')
.map(function (cat) {
return cat.toLowerCase().trim(); // lowercase inputs
})
.filter( function( cat ) {
return ( cat.length > 0 );
});
}
// pass validated params to next middleware
req.clean = clean;
if( !clean.categories.length ){
messages.warnings.push( 'invalid \'categories\': no valid category strings found');
}
}
return { 'error': false };
return messages;
}

35
sanitiser/_details.js

@ -1,36 +1,25 @@
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;
}
var check = require('check-types');
var DEFAULT_DETAILS_BOOL = true;
default_value = !!default_value;
// validate inputs, convert types and apply defaults
function sanitize( raw, clean ){
// ensure the input params are a valid object
if( !isObject( params ) ){
params = {};
}
// error & warning messages
var messages = { errors: [], warnings: [] };
if (params.details !== undefined) {
clean.details = isTruthy(params.details);
if( !check.undefined( raw.details ) ){
clean.details = isTruthy( raw.details );
} else {
clean.details = default_value;
clean.details = DEFAULT_DETAILS_BOOL;
}
req.clean = clean;
return {'error':false};
return messages;
}
// be lenient with 'truthy' values
function isTruthy(val) {
if (typeof val === 'string') {
if( check.string( val ) ){
return ['true', '1', 'yes', 'y'].indexOf(val) !== -1;
}

11
sanitiser/_geo_common.js

@ -1,7 +1,8 @@
/**
* helper sanitiser methods for geo parameters
*/
var util = require( 'util' );
var util = require('util'),
check = require('check-types');
/**
* Parse and validate bbox parameter
@ -9,15 +10,15 @@ var util = require( 'util' );
* bbox = left, bottom, right, top
* bbox = min Longitude, min Latitude, max Longitude, max Latitude
*
* @param {object} raw
* @param {object} clean
* @param {string} param
*/
function sanitize_bbox( clean, param ) {
if( !param ) {
function sanitize_bbox( raw, clean ) {
if( !check.unemptyString( raw.bbox ) ) {
return;
}
var bboxArr = param.split( ',' );
var bboxArr = raw.bbox.split( ',' );
if( Array.isArray( bboxArr ) && bboxArr.length === 4 ) {
var bbox = bboxArr.map(parseFloat);

37
sanitiser/_geo_reverse.js

@ -1,39 +1,26 @@
var isObject = require('is-object');
var geo_common = require ('./_geo_common');
var LAT_LON_IS_REQUIRED = true,
CIRCLE_IS_REQUIRED = false,
CIRCLE_MUST_BE_COMPLETE = false;
// validate inputs, convert types and apply defaults
module.exports = function sanitize( req ){
var clean = req.clean || {};
var params = req.query;
var latlon_is_required = true;
var circle_is_required = false;
var circle_must_be_complete = false;
module.exports = function sanitize( raw, clean ){
// ensure the input params are a valid object
if( !isObject( params ) ){
params = {};
}
if( !isObject( params.point ) ){
params.point = {};
}
// error & warning messages
var messages = { errors: [], warnings: [] };
try {
geo_common.sanitize_coord( 'lat', clean, params['point.lat'], latlon_is_required );
geo_common.sanitize_coord( 'lon', clean, params['point.lon'], latlon_is_required );
geo_common.sanitize_coord( 'lat', clean, raw['point.lat'], LAT_LON_IS_REQUIRED );
geo_common.sanitize_coord( 'lon', clean, raw['point.lon'], LAT_LON_IS_REQUIRED );
// boundary.circle.* is not mandatory, and only specifying radius is fine,
// as point.lat/lon will be used to fill those values by default
geo_common.sanitize_boundary_circle( clean, params, circle_is_required, circle_must_be_complete);
geo_common.sanitize_boundary_circle( clean, raw, CIRCLE_IS_REQUIRED, CIRCLE_MUST_BE_COMPLETE);
}
catch (err) {
return {
'error': true,
'message': err.message
};
messages.errors.push( err.message );
}
req.clean = clean;
return { 'error': false };
return messages;
};

37
sanitiser/_geo_search.js

@ -1,38 +1,21 @@
var isObject = require('is-object');
var geo_common = require ('./_geo_common');
var LAT_LON_IS_REQUIRED = false;
// validate inputs, convert types and apply defaults
module.exports = function sanitize( req ){
var clean = req.clean || {};
var params = req.query;
var latlon_is_required = false;
// ensure the input params are a valid object
if( !isObject( params ) ){
params = {};
}
module.exports = function sanitize( raw, clean ){
if( !isObject( params.focus ) ){
params.focus = {};
}
if( !isObject( params.focus.point ) ){
params.focus.point = {};
}
// error & warning messages
var messages = { errors: [], warnings: [] };
try {
geo_common.sanitize_coord( 'lat', clean, params['focus.point.lat'], latlon_is_required );
geo_common.sanitize_coord( 'lon', clean, params['focus.point.lon'], latlon_is_required );
geo_common.sanitize_bbox(clean, params.bbox);
geo_common.sanitize_coord( 'lat', clean, raw['focus.point.lat'], LAT_LON_IS_REQUIRED );
geo_common.sanitize_coord( 'lon', clean, raw['focus.point.lon'], LAT_LON_IS_REQUIRED );
geo_common.sanitize_bbox(raw, clean);
}
catch (err) {
return {
'error': true,
'message': err.message
};
messages.errors.push( err.message );
}
req.clean = clean;
return { 'error': false };
return messages;
};

129
sanitiser/_id.js

@ -1,72 +1,79 @@
var isObject = require('is-object');
var check = require('check-types'),
types = require('../query/types');
var ID_DELIM = ':';
// validate inputs, convert types and apply defaults
// id generally looks like 'geoname:4163334' (type:id)
// so, both type and id are required fields.
function sanitize( req ){
req.clean = req.clean || {};
var params = req.query;
var types = require('../query/types');
var delim = ':';
// ensure params is a valid object
if( !isObject( params ) ){
params = {};
}
var errormessage = function(fieldname, message) {
return {
'error': true,
'message': message || ('invalid param \''+ fieldname + '\': text length, must be >0')
};
};
if(('string' === typeof params.id && !params.id.length) || params.id === undefined){
return errormessage('id');
}
if( params && params.id && params.id.length ){
req.clean.ids = [];
params.ids = Array.isArray(params.id) ? params.id : [params.id];
// de-dupe
params.ids = params.ids.filter(function(item, pos) {
return params.ids.indexOf(item) === pos;
});
function errorMessage(fieldname, message) {
return message || 'invalid param \''+ fieldname + '\': text length, must be >0';
}
function sanitize( raw, clean ){
for (var i=0; i<params.ids.length; i++) {
var thisparam = params.ids[i];
// basic format/ presence of ':'
if(thisparam.indexOf(delim) === -1) {
return errormessage(null, 'invalid: must be of the format type:id for ex: \'geoname:4163334\'');
}
var param_index = thisparam.indexOf(delim);
var type = thisparam.substring(0, param_index );
var id = thisparam.substring(param_index + 1);
// id text
if('string' !== typeof id || !id.length){
return errormessage(thisparam);
}
// type text
if('string' !== typeof type || !type.length){
return errormessage(thisparam);
}
// type text must be one of the types
if(types.indexOf(type) === -1){
return errormessage('type', type + ' is invalid. It must be one of these values - [' + types.join(', ') + ']');
}
req.clean.ids.push({
id: id,
type: type
});
// error & warning messages
var messages = { errors: [], warnings: [] };
// 'raw.id' can be an array!?
var rawIds = check.array( raw.id ) ? raw.id : [ raw.id ];
// de-dupe ids
rawIds = rawIds.filter(function(item, pos) {
return rawIds.indexOf( item ) === pos;
});
// ensure all elements are valid non-empty strings
rawIds = rawIds.filter( function( uc ){
if( !check.unemptyString( uc ) ){
messages.errors.push( errorMessage('id') );
return false;
}
}
return true;
});
// init 'clean.ids'
clean.ids = [];
// cycle through raw ids and set those which are valid
rawIds.forEach( function( rawId ){
var param_index = rawId.indexOf(ID_DELIM);
var type = rawId.substring(0, param_index );
var id = rawId.substring(param_index + 1);
// basic format/ presence of ':'
if(param_index === -1) {
messages.errors.push(
errorMessage(null, 'invalid: must be of the format type:id for ex: \'geoname:4163334\'')
);
}
// id text
if( !check.unemptyString( id ) ){
messages.errors.push( errorMessage( rawId ) );
}
// type text
if( !check.unemptyString( type ) ){
messages.errors.push( errorMessage( rawId ) );
}
// type text must be one of the types
if( types.indexOf( type ) === -1 ){
messages.errors.push(
errorMessage('type', type + ' is invalid. It must be one of these values - [' + types.join(', ') + ']')
);
}
// add valid id to 'clean.ids' array
clean.ids.push({
id: id,
type: type
});
});
return { 'error': false };
return messages;
}
// export function

17
sanitiser/_sanitize.js

@ -1,17 +0,0 @@
function sanitize( req, sanitiser, cb ){
req.clean = req.clean || {};
for (var s in sanitiser) {
var sanity = sanitiser[s](req);
if (sanity.error) {
return cb(sanity.message);
}
}
return cb( undefined, req.clean );
}
// export function
module.exports = sanitize;

53
sanitiser/_size.js

@ -1,30 +1,47 @@
var isObject = require('is-object');
var MIN_SIZE = 1,
MAX_SIZE = 40,
DEFAULT_SIZE = 10;
// validate inputs, convert types and apply defaults
function sanitize( req, default_size){
function sanitize( raw, clean ){
var clean = req.clean || {};
var params= req.query;
// error & warning messages
var messages = { errors: [], warnings: [] };
default_size = default_size || 10;
// coercions
var _size = parseInt( raw.size, 10 );
// ensure the input params are a valid object
if( !isObject( params ) ){
params = {};
}
// invalid numeric input
// @todo: this can be removed now as queries have default sizes?
if( isNaN( _size ) ){
// total results
var size = parseInt( params.size, 10 );
if( !isNaN( size ) ){
clean.size = Math.min( Math.max( size, 1 ), 40 ); // max
} else {
clean.size = default_size; // default
// set the default size
messages.warnings.push('invalid integer \'size\', using DEFAULT_SIZE');
clean.size = DEFAULT_SIZE;
}
// valid numeric input
else {
// ensure size falls within defined range
if( _size > MAX_SIZE ){
// set the max size
messages.warnings.push('out-of-range integer \'size\', using MAX_SIZE');
clean.size = MAX_SIZE;
}
else if( _size < MIN_SIZE ){
// set the min size
messages.warnings.push('out-of-range integer \'size\', using MIN_SIZE');
clean.size = MIN_SIZE;
}
else {
// set the input size
clean.size = _size;
}
req.clean = clean;
return {'error':false};
}
return messages;
}
// export function

102
sanitiser/_targets.js

@ -1,57 +1,81 @@
var _ = require('lodash');
function setup(paramName, targetMap) {
return function (req ) {
return sanitize(paramName, targetMap, req);
var _ = require('lodash'),
check = require('check-types');
function setup( paramName, targetMap ) {
return function( raw, clean ){
return sanitize( raw, clean, {
paramName: paramName,
targetMap: targetMap,
targetMapKeysString: Object.keys(targetMap).join(',')
});
};
}
function sanitize( paramName, targetMap, req ) {
var params = req.query || {};
function sanitize( raw, clean, opts ) {
req.clean = req.clean || {};
req.clean.types = req.clean.types || {};
// error & warning messages
var messages = { errors: [], warnings: [] };
// default case (no sources specified in GET params)
// there is a case where the property is present, but set to null or undefined
if (params.hasOwnProperty(paramName) === false || typeof params[paramName] === 'undefined') {
return { error: false };
}
// init clean.types
clean.types = clean.types || {};
params[paramName] = params[paramName].trim();
// the string of targets (comma delimeted)
var targetsString = raw[opts.paramName];
if (params[paramName].length === 0) {
return {
error: true,
message: paramName + ' parameter cannot be an empty string. Valid options: ' + Object.keys(targetMap).join(', ')
};
}
// trim whitespace
if( check.unemptyString( targetsString ) ){
targetsString = targetsString.trim();
var targets = params[paramName].split(',').map( function( target ){
return target.toLowerCase(); // lowercase inputs
});
// param must be a valid non-empty string
if( !check.unemptyString( targetsString ) ){
messages.errors.push(
opts.paramName + ' parameter cannot be an empty string. Valid options: ' + opts.targetMapKeysString
);
}
else {
var invalidTargets = targets.filter(function(target) {
return targetMap.hasOwnProperty(target) === false;
});
// split string in to array and lowercase each target string
var targets = targetsString.split(',').map( function( target ){
return target.toLowerCase(); // lowercase inputs
});
if (invalidTargets.length > 0) {
return {
error: true,
message: invalidTargets[0] + ' is an invalid ' + paramName + ' parameter. Valid options: ' + Object.keys(targetMap).join(', ')
};
}
// emit an error for each target *not* present in the targetMap
targets.filter( function( target ){
return !opts.targetMap.hasOwnProperty(target);
}).forEach( function( target ){
messages.errors.push(
'\'' + target + '\' is an invalid ' + opts.paramName + ' parameter. Valid options: ' + opts.targetMapKeysString
);
});
// only set types value when no error occured
if( !messages.errors.length ){
var cleanPropName = 'from_' + paramName;
// store the values under a new key as 'clean.types.from_*'
var typesKey = 'from_' + opts.paramName;
req.clean.types[cleanPropName] = targets.reduce(function(acc, target) {
return acc.concat(targetMap[target]);
}, []);
// ?
clean.types[typesKey] = targets.reduce(function(acc, target) {
return acc.concat(opts.targetMap[target]);
}, []);
// dedupe in case aliases expanded to common things or user typed in duplicates
clean.types[typesKey] = _.unique(clean.types[typesKey]);
}
}
}
// string is empty
else if( check.string( targetsString ) ){
messages.errors.push(
opts.paramName + ' parameter cannot be an empty string. Valid options: ' + opts.targetMapKeysString
);
}
// dedupe in case aliases expanded to common things or user typed in duplicates
req.clean.types[cleanPropName] = _.unique(req.clean.types[cleanPropName]);
return { error: false };
return messages;
}
module.exports = setup;

41
sanitiser/_text.js

@ -1,32 +1,33 @@
var isObject = require('is-object');
var query_parser = require('../helper/query_parser');
var check = require('check-types'),
query_parser = require('../helper/query_parser');
// validate texts, convert types and apply defaults
function sanitize( req ){
req.clean = req.clean || {};
var params= req.query;
function sanitize( raw, clean ){
// ensure the text params are a valid object
if( !isObject( params ) ){
params = {};
}
// error & warning messages
var messages = { errors: [], warnings: [] };
// text text
if('string' !== typeof params.text || !params.text.length){
return {
'error': true,
'message': 'invalid param \'text\': text length, must be >0'
};
// invalid input 'text'
if( !check.unemptyString( raw.text ) ){
messages.errors.push('invalid param \'text\': text length, must be >0');
}
req.clean.text = params.text;
// valid input 'text'
else {
req.clean.parsed_text = query_parser.get_parsed_address(params.text);
// valid text
clean.text = raw.text;
req.clean.types = req.clean.layers || {};
req.clean.types.from_address_parsing = query_parser.get_layers(params.text);
// parse text with query parser
clean.parsed_text = query_parser.get_parsed_address(clean.text);
// try to set layers from query parser results
clean.types = clean.layers || {};
clean.types.from_address_parsing = query_parser.get_layers(clean.text);
}
return { 'error': false };
return messages;
}
// export function

7
sanitiser/place.js

@ -1,13 +1,15 @@
var _sanitize = require('../sanitiser/_sanitize'),
var sanitizeAll = require('../sanitiser/sanitizeAll'),
sanitizers = {
id: require('../sanitiser/_id'),
details: require('../sanitiser/_details')
};
var sanitize = function(req, cb) { _sanitize(req, sanitizers, cb); };
var sanitize = function(req, cb) { sanitizeAll(req, sanitizers, cb); };
// export sanitize for testing
module.exports.sanitize = sanitize;
module.exports.sanitiser_list = sanitizers;
// middleware
module.exports.middleware = function( req, res, next ){
@ -16,7 +18,6 @@ module.exports.middleware = function( req, res, next ){
res.status(400); // 400 Bad Request
return next(err);
}
req.clean = clean;
next();
});
};

26
sanitiser/reverse.js

@ -1,21 +1,19 @@
var _sanitize = require('../sanitiser/_sanitize');
var sanitiser = {
latlonzoom: require('../sanitiser/_geo_reverse'),
layers: require('../sanitiser/_targets')('layers', require('../query/layers')),
sources: require('../sanitiser/_targets')('sources', require('../query/sources')),
details: require('../sanitiser/_details'),
size: require('../sanitiser/_size'),
categories: function (req) {
var categories = require('../sanitiser/_categories');
return categories(req);
}
};
var sanitizeAll = require('../sanitiser/sanitizeAll'),
sanitizers = {
layers: require('../sanitiser/_targets')('layers', require('../query/layers')),
sources: require('../sanitiser/_targets')('sources', require('../query/sources')),
size: require('../sanitiser/_size'),
details: require('../sanitiser/_details'),
geo_reverse: require('../sanitiser/_geo_reverse'),
categories: require('../sanitiser/_categories')
};
var sanitize = function(req, cb) { _sanitize(req, sanitiser, cb); };
var sanitize = function(req, cb) { sanitizeAll(req, sanitizers, cb); };
// export sanitize for testing
module.exports.sanitize = sanitize;
module.exports.sanitiser_list = sanitizers;
// middleware
module.exports.middleware = function( req, res, next ){
@ -24,9 +22,7 @@ module.exports.middleware = function( req, res, next ){
res.status(400); // 400 Bad Request
return next(err);
}
req.clean = clean;
next();
});
};
module.exports.sanitiser_list = sanitiser;

26
sanitiser/sanitizeAll.js

@ -0,0 +1,26 @@
function sanitize( req, sanitizers, cb ){
// init an object to store clean
// (sanitized) input parameters
req.clean = {};
// source of input parameters
// (in this case from the GET querystring params)
var params = req.query || {};
for (var s in sanitizers) {
var sanity = sanitizers[s]( params, req.clean );
// errors
if( sanity.errors.length ){
return cb( sanity.errors[0] );
}
}
return cb( undefined, req.clean );
}
// export function
module.exports = sanitize;

14
sanitiser/search.js

@ -1,22 +1,20 @@
var _sanitize = require('../sanitiser/_sanitize'),
var sanitizeAll = require('../sanitiser/sanitizeAll'),
sanitizers = {
text: require('../sanitiser/_text'),
size: require('../sanitiser/_size'),
layers: require('../sanitiser/_targets')('layers', require( '../query/layers' )),
sources: require('../sanitiser/_targets')('sources', require( '../query/sources' )),
details: require('../sanitiser/_details'),
latlonzoom: require('../sanitiser/_geo_search'),
categories: function (req) {
var categories = require('../sanitiser/_categories');
return categories(req);
}
geo_search: require('../sanitiser/_geo_search'),
categories: require('../sanitiser/_categories')
};
var sanitize = function(req, cb) { _sanitize(req, sanitizers, cb); };
var sanitize = function(req, cb) { sanitizeAll(req, sanitizers, cb); };
// export sanitize for testing
module.exports.sanitize = sanitize;
module.exports.sanitiser_list = sanitizers;
// middleware
module.exports.middleware = function( req, res, next ){
@ -25,9 +23,7 @@ module.exports.middleware = function( req, res, next ){
res.status(400); // 400 Bad Request
return next(err);
}
req.clean = clean;
next();
});
};
module.exports.sanitiser_list = sanitizers;

89
test/unit/sanitiser/_layers.js

@ -5,78 +5,105 @@ module.exports.tests = {};
module.exports.tests.sanitize_layers = function(test, common) {
test('unspecified', function(t) {
var res = sanitize({ query: { layers: undefined } });
t.equal(res.error, false);
var messages = sanitize({ layers: undefined }, {});
t.equal(messages.errors.length, 0, 'no errors');
t.end();
});
test('invalid layer', function(t) {
var req = { query: { layers: 'test_layer' } };
var res = sanitize(req);
var raw = { layers: 'test_layer' };
var clean = {};
var messages = sanitize(raw, clean);
var msg = ' is an invalid layers parameter. Valid options: ';
t.true(res.error, 'error flag set');
t.true(res.message.match(msg), 'invalid layer requested');
t.true(res.message.length > msg.length, 'invalid error message');
t.equal(messages.errors.length, 1, 'errors set');
t.true(messages.errors[0].match(msg), 'invalid layer requested');
t.true(messages.errors[0].length > msg.length, 'invalid error message');
t.end();
});
test('venue (alias) layer', function(t) {
var venue_layers = ['geoname','osmnode','osmway'];
var req = { query: { layers: 'venue' } };
sanitize(req);
t.deepEqual(req.clean.types.from_layers, venue_layers, 'venue layers set');
var raw = { layers: 'venue' };
var clean = {};
sanitize(raw, clean);
t.deepEqual(clean.types.from_layers, venue_layers, 'venue layers set');
t.end();
});
test('coarse (alias) layer', function(t) {
var admin_layers = ['admin0','admin1','admin2','neighborhood','locality','local_admin'];
var req = { query: { layers: 'coarse' } };
sanitize(req);
t.deepEqual(req.clean.types.from_layers, admin_layers, 'coarse layers set');
var raw = { layers: 'coarse' };
var clean = {};
sanitize(raw, clean);
t.deepEqual(clean.types.from_layers, admin_layers, 'coarse layers set');
t.end();
});
test('address (alias) layer', function(t) {
var address_layers = ['osmaddress','openaddresses'];
var req = { query: { layers: 'address' } };
sanitize(req);
t.deepEqual(req.clean.types.from_layers, address_layers, 'address layers set');
var raw = { layers: 'address' };
var clean = {};
sanitize(raw, clean);
t.deepEqual(clean.types.from_layers, address_layers, 'address layers set');
t.end();
});
test('venue alias layer plus regular layers', function(t) {
var venue_layers = ['geoname','osmnode','osmway'];
var reg_layers = ['admin0', 'admin1'];
var req = { query: { layers: 'venue,country,region' } };
sanitize(req);
t.deepEqual(req.clean.types.from_layers, venue_layers.concat(reg_layers), 'venue + regular layers');
var raw = { layers: 'venue,country,region' };
var clean = {};
sanitize(raw, clean);
t.deepEqual(clean.types.from_layers, venue_layers.concat(reg_layers), 'venue + regular layers');
t.end();
});
test('coarse alias layer plus regular layers', function(t) {
var admin_layers = ['admin0','admin1','admin2','neighborhood','locality','local_admin'];
var reg_layers = ['geoname', 'osmnode', 'osmway'];
var req = { query: { layers: 'coarse,venue,country' } };
sanitize(req);
t.deepEqual(req.clean.types.from_layers, admin_layers.concat(reg_layers), 'coarse + regular layers set');
var raw = { layers: 'coarse,venue,country' };
var clean = {};
sanitize(raw, clean);
t.deepEqual(clean.types.from_layers, admin_layers.concat(reg_layers), 'coarse + regular layers set');
t.end();
});
test('address alias layer plus regular layers', function(t) {
var address_layers = ['osmaddress','openaddresses'];
var reg_layers = ['admin0', 'locality'];
var req = { query: { layers: 'address,country,locality' } };
sanitize(req);
t.deepEqual(req.clean.types.from_layers, address_layers.concat(reg_layers), 'address + regular layers set');
var raw = { layers: 'address,country,locality' };
var clean = {};
sanitize(raw, clean);
t.deepEqual(clean.types.from_layers, address_layers.concat(reg_layers), 'address + regular layers set');
t.end();
});
test('alias layer plus regular layers (no duplicates)', function(t) {
var venue_layers = ['geoname','osmnode','osmway','admin0'];
var req = { query: { layers: 'venue,country' } };
sanitize(req);
t.deepEqual(req.clean.types.from_layers, venue_layers, 'venue layers found (no duplicates)');
var raw = { layers: 'venue,country' };
var clean = {};
sanitize(raw, clean);
t.deepEqual(clean.types.from_layers, venue_layers, 'venue layers found (no duplicates)');
t.end();
});
test('multiple alias layers (no duplicates)', function(t) {
var alias_layers = ['geoname','osmnode','osmway','admin0','admin1','admin2','neighborhood','locality','local_admin'];
var req = { query: { layers: 'venue,coarse' } };
sanitize(req);
t.deepEqual(req.clean.types.from_layers, alias_layers, 'all layers found (no duplicates)');
var raw = { layers: 'venue,coarse' };
var clean = {};
sanitize(raw, clean);
t.deepEqual(clean.types.from_layers, alias_layers, 'all layers found (no duplicates)');
t.end();
});
};

69
test/unit/sanitiser/_sources.js

@ -1,19 +1,21 @@
var sanitize = require( '../../../sanitiser/_targets' )('sources', require('../../../query/sources'));
var success_response = { error: false };
var success_messages = { error: false };
module.exports.tests = {};
module.exports.tests.no_sources = function(test, common) {
test('sources is not set', function(t) {
var req = {
query: { }
query: { },
clean: { }
};
var response = sanitize(req);
var messages = sanitize(req.query, req.clean);
t.deepEqual(req.clean.types, {}, 'clean.types should be empty object');
t.deepEqual(response, success_response, 'no error returned');
t.deepEqual(messages.errors, [], 'no error returned');
t.deepEqual(messages.warnings, [], 'no warnings returned');
t.end();
});
@ -21,19 +23,19 @@ module.exports.tests.no_sources = function(test, common) {
var req = {
query: {
sources: ''
}
},
clean: { }
};
var expected_response = {
error: true,
message: 'sources parameter cannot be an empty string. ' +
'Valid options: gn, geonames, oa, openaddresses, qs, quattroshapes, osm, openstreetmap'
};
var expected_error = 'sources parameter cannot be an empty string. ' +
'Valid options: gn,geonames,oa,openaddresses,qs,quattroshapes,osm,openstreetmap';
var response = sanitize(req);
var messages = sanitize(req.query, req.clean);
t.deepEqual(req.clean.types, {}, 'clean.types should be empty object');
t.deepEqual(response, expected_response, 'no error returned');
t.deepEqual(messages.errors.length, 1, 'error returned');
t.deepEqual(messages.errors[0], expected_error, 'error returned');
t.deepEqual(messages.warnings, [], 'no warnings returned');
t.end();
});
};
@ -43,13 +45,16 @@ module.exports.tests.valid_sources = function(test, common) {
var req = {
query: {
sources: 'geonames'
}
},
clean: { }
};
var response = sanitize(req);
var messages = sanitize(req.query, req.clean);
t.deepEqual(req.clean.types, { from_sources: ['geoname'] }, 'clean.types should contain from_source entry with geonames');
t.deepEqual(response, success_response, 'no error returned');
t.deepEqual(messages.errors, [], 'no error returned');
t.deepEqual(messages.warnings, [], 'no warnings returned');
t.end();
});
@ -57,16 +62,18 @@ module.exports.tests.valid_sources = function(test, common) {
var req = {
query: {
sources: 'openstreetmap'
}
},
clean: { }
};
var expected_types = {
from_sources: ['osmaddress', 'osmnode', 'osmway']
};
var response = sanitize(req);
var messages = sanitize(req.query, req.clean);
t.deepEqual(req.clean.types, expected_types, 'clean.types should contain from_source entry with multiple entries for openstreetmap');
t.deepEqual(response, success_response, 'no error returned');
t.deepEqual(messages.errors, [], 'no error returned');
t.deepEqual(messages.warnings, [], 'no warnings returned');
t.end();
});
@ -74,17 +81,19 @@ module.exports.tests.valid_sources = function(test, common) {
var req = {
query: {
sources: 'openstreetmap,openaddresses'
}
},
clean: { }
};
var expected_types = {
from_sources: ['osmaddress', 'osmnode', 'osmway', 'openaddresses']
};
var response = sanitize(req);
var messages = sanitize(req.query, req.clean);
t.deepEqual(req.clean.types, expected_types,
'clean.types should contain from_source entry with multiple entries for openstreetmap and openadresses');
t.deepEqual(response, success_response, 'no error returned');
t.deepEqual(messages.errors, [], 'no error returned');
t.deepEqual(messages.warnings, [], 'no warnings returned');
t.end();
});
};
@ -94,17 +103,19 @@ module.exports.tests.invalid_sources = function(test, common) {
var req = {
query: {
sources: 'notasource'
}
},
clean: { }
};
var expected_response = {
error: true,
message: 'notasource is an invalid sources parameter. ' +
'Valid options: gn, geonames, oa, openaddresses, qs, quattroshapes, osm, openstreetmap'
var expected_messages = {
errors: [
'\'notasource\' is an invalid sources parameter. Valid options: gn,geonames,oa,openaddresses,qs,quattroshapes,osm,openstreetmap'
],
warnings: []
};
var response = sanitize(req);
var messages = sanitize(req.query, req.clean);
t.deepEqual(response, expected_response, 'error with message returned');
t.deepEqual(messages, expected_messages, 'error with message returned');
t.deepEqual(req.clean.types, { }, 'clean.types should remain empty');
t.end();
});
@ -112,7 +123,7 @@ module.exports.tests.invalid_sources = function(test, common) {
module.exports.all = function (tape, common) {
function test(name, testFunction) {
return tape('SANTIZE _source ' + name, testFunction);
return tape('SANTIZE _sources ' + name, testFunction);
}
for( var testCase in module.exports.tests ){

10
test/unit/sanitiser/reverse.js

@ -1,7 +1,7 @@
var suggest = require('../../../sanitiser/reverse'),
_sanitize = suggest.sanitize,
middleware = suggest.middleware,
var reverse = require('../../../sanitiser/reverse'),
_sanitize = reverse.sanitize,
middleware = reverse.middleware,
defaultError = 'missing param \'lat\'',
defaultClean = { lat:0,
types: {
@ -30,8 +30,8 @@ module.exports.tests.interface = function(test, common) {
module.exports.tests.sanitisers = function(test, common) {
test('check sanitiser list', function (t) {
var expected = ['latlonzoom', 'layers', 'sources', 'details', 'size', 'categories'];
t.deepEqual(Object.keys(suggest.sanitiser_list), expected);
var expected = ['layers', 'sources', 'size', 'details', 'geo_reverse', 'categories'];
t.deepEqual(Object.keys(reverse.sanitiser_list), expected);
t.end();
});
};

2
test/unit/sanitiser/search.js

@ -32,7 +32,7 @@ module.exports.tests.interface = function(test, common) {
module.exports.tests.sanitisers = function(test, common) {
test('check sanitiser list', function (t) {
var expected = ['text', 'size', 'layers', 'sources', 'details', 'latlonzoom', 'categories' ];
var expected = ['text', 'size', 'layers', 'sources', 'details', 'geo_search', 'categories' ];
t.deepEqual(Object.keys(search.sanitiser_list), expected);
t.end();
});

Loading…
Cancel
Save