Browse Source

Merge pull request #952 from pelias/staging

Merge staging into production
pull/1005/head
Diana Shkolnikov 7 years ago committed by GitHub
parent
commit
09d455ffcf
  1. 7
      README.md
  2. 3
      app.js
  3. 10
      middleware/changeLanguage.js
  4. 9
      package.json
  5. 25
      query/reverse.js
  6. 34
      routes/legacy.js
  7. 6
      routes/v1.js
  8. 32
      sanitizer/_details.js
  9. 5
      sanitizer/_geo_reverse.js
  10. 31
      sanitizer/_location_bias.js
  11. 29
      sanitizer/autocomplete.js
  12. 53
      sanitizer/search.js
  13. 50
      sanitizer/structured_geocoding.js
  14. 8
      schema.js
  15. 51
      test/unit/controller/placeholder.js
  16. 41
      test/unit/fixture/search_boundary_country.js
  17. 1594
      test/unit/fixture/search_fallback.js
  18. 50
      test/unit/fixture/search_fallback_postalcode_only.js
  19. 41
      test/unit/fixture/search_linguistic_bbox.js
  20. 41
      test/unit/fixture/search_linguistic_focus.js
  21. 41
      test/unit/fixture/search_linguistic_focus_bbox.js
  22. 41
      test/unit/fixture/search_linguistic_focus_null_island.js
  23. 41
      test/unit/fixture/search_linguistic_only.js
  24. 41
      test/unit/fixture/search_linguistic_viewport.js
  25. 41
      test/unit/fixture/search_linguistic_viewport_min_diagonal.js
  26. 41
      test/unit/fixture/search_with_category_filtering.js
  27. 41
      test/unit/fixture/search_with_source_filtering.js
  28. 11
      test/unit/fixture/structured_geocoding/boundary_country.json
  29. 1596
      test/unit/fixture/structured_geocoding/fallback.json
  30. 11
      test/unit/fixture/structured_geocoding/linguistic_bbox.json
  31. 11
      test/unit/fixture/structured_geocoding/linguistic_focus.json
  32. 9
      test/unit/fixture/structured_geocoding/linguistic_focus_bbox.json
  33. 11
      test/unit/fixture/structured_geocoding/linguistic_focus_null_island.json
  34. 11
      test/unit/fixture/structured_geocoding/linguistic_only.json
  35. 11
      test/unit/fixture/structured_geocoding/linguistic_viewport.json
  36. 11
      test/unit/fixture/structured_geocoding/linguistic_viewport_min_diagonal.json
  37. 50
      test/unit/fixture/structured_geocoding/postalcode_only.js
  38. 12
      test/unit/fixture/structured_geocoding/with_source_filtering.json
  39. 84
      test/unit/middleware/changeLanguage.js
  40. 17
      test/unit/query/reverse.js
  41. 1
      test/unit/run.js
  42. 22
      test/unit/sanitizer/_geo_reverse.js
  43. 109
      test/unit/sanitizer/_location_bias.js
  44. 121
      test/unit/sanitizer/autocomplete.js
  45. 1
      test/unit/sanitizer/nearby.js
  46. 1
      test/unit/sanitizer/reverse.js
  47. 23
      test/unit/sanitizer/search.js
  48. 22
      test/unit/sanitizer/structured_geocoding.js
  49. 102
      test/unit/schema.js

7
README.md

@ -42,10 +42,10 @@ The API recognizes the following properties under the top-level `api` key in you
|`host`|*yes*||specifies the url under which the http service is to run| |`host`|*yes*||specifies the url under which the http service is to run|
|`textAnalyzer`|*no*|*addressit*|can be either `libpostal` or `addressit` however will soon be **deprecated** and only `libpostal` will be supported going forward| |`textAnalyzer`|*no*|*addressit*|can be either `libpostal` or `addressit` however will soon be **deprecated** and only `libpostal` will be supported going forward|
|`indexName`|*no*|*pelias*|name of the Elasticsearch index to be used when building queries| |`indexName`|*no*|*pelias*|name of the Elasticsearch index to be used when building queries|
|`legacyUrl`|*no*||the url to redirect to in case the user does not specify a version such as `v1`
|`relativeScores`|*no*|true|if set to true, confidence scores will be normalized, realistically at this point setting this to false is not tested or desirable |`relativeScores`|*no*|true|if set to true, confidence scores will be normalized, realistically at this point setting this to false is not tested or desirable
|`accessLog`|*no*||name of the format to use for access logs; may be any one of the [predefined values](https://github.com/expressjs/morgan#predefined-formats) in the `morgan` package. Defaults to `"common"`; if set to `false`, or an otherwise falsy value, disables access-logging entirely.| |`accessLog`|*no*||name of the format to use for access logs; may be any one of the [predefined values](https://github.com/expressjs/morgan#predefined-formats) in the `morgan` package. Defaults to `"common"`; if set to `false`, or an otherwise falsy value, disables access-logging entirely.|
|`services`|*no*||service definitions for [point-in-polygon](https://github.com/pelias/pip-service) and [placholder](https://github.com/pelias/placeholder) services. If missing (which is not recommended), the point-in-polygon and placeholder services will not be called.| |`services`|*no*||service definitions for [point-in-polygon](https://github.com/pelias/pip-service) and [placholder](https://github.com/pelias/placeholder) services. If missing (which is not recommended), the point-in-polygon and placeholder services will not be called.|
|`defaultParameters.focus.point.lon` <br> `defaultParameters.focus.point.lat`|no | |default coordinates for focus point
Example configuration file would look something like this: Example configuration file would look something like this:
@ -65,7 +65,6 @@ Example configuration file would look something like this:
"api": { "api": {
"host": "localhost:3100/v1/", "host": "localhost:3100/v1/",
"indexName": "foobar", "indexName": "foobar",
"legacyUrl": "pelias.mapzen.com",
"relativeScores": true, "relativeScores": true,
"textAnalyzer": "libpostal", "textAnalyzer": "libpostal",
"services": { "services": {
@ -76,6 +75,10 @@ Example configuration file would look something like this:
"url": "http://myplaceholderservice.com:5000" "url": "http://myplaceholderservice.com:5000"
} }
} }
"defaultParameters": {
"focus.point.lat": 12.121212,
"focus.point.lon": 21.212121
}
}, },
"interpolation": { "interpolation": {
"client": { "client": {

3
app.js

@ -16,9 +16,6 @@ app.use( require('./middleware/jsonp') );
/** ----------------------- routes ----------------------- **/ /** ----------------------- routes ----------------------- **/
var legacy = require('./routes/legacy');
legacy.addRoutes(app, peliasConfig.api);
var v1 = require('./routes/v1'); var v1 = require('./routes/v1');
v1.addRoutes(app, peliasConfig); v1.addRoutes(app, peliasConfig);

10
middleware/changeLanguage.js

@ -1,6 +1,7 @@
var logger = require( 'pelias-logger' ).get( 'api' ); var logger = require( 'pelias-logger' ).get( 'api' );
var service = require('../service/language'); var service = require('../service/language');
const _ = require('lodash');
/** /**
example response from language web service: example response from language web service:
@ -28,7 +29,6 @@ example response from language web service:
**/ **/
function setup() { function setup() {
var transport = service.findById(); var transport = service.findById();
var middleware = function(req, res, next) { var middleware = function(req, res, next) {
@ -145,18 +145,18 @@ function updateDocs( req, res, translations ){
if( !translations[id].hasOwnProperty( 'names' ) ){ continue; } if( !translations[id].hasOwnProperty( 'names' ) ){ continue; }
// requested language is not available // requested language is not available
if( !translations[id].names.hasOwnProperty( requestLanguage ) ){ if (_.isEmpty(_.get(translations[id].names, requestLanguage, [] ))) {
logger.info( '[language] [info]', 'missing translation', requestLanguage, id ); logger.debug( '[language] [debug]', 'missing translation', requestLanguage, id );
continue; continue;
} }
// translate 'parent.*' property // translate 'parent.*' property
adminValues[i] = translations[id].names[ requestLanguage ]; adminValues[i] = translations[id].names[ requestLanguage ][0];
// if the record is an admin record we also translate // if the record is an admin record we also translate
// the 'name.default' property. // the 'name.default' property.
if( adminKey === doc.layer ){ if( adminKey === doc.layer ){
doc.name.default = translations[id].names[ requestLanguage ]; doc.name.default = translations[id].names[ requestLanguage ][0];
} }
} }
} }

9
package.json

@ -43,7 +43,6 @@
"elasticsearch": "^12.0.1", "elasticsearch": "^12.0.1",
"elasticsearch-exceptions": "0.0.4", "elasticsearch-exceptions": "0.0.4",
"express": "^4.8.8", "express": "^4.8.8",
"express-http-proxy": "^0.11.0",
"extend": "^3.0.1", "extend": "^3.0.1",
"geojson": "^0.4.0", "geojson": "^0.4.0",
"@mapbox/geojson-extent": "^0.3.1", "@mapbox/geojson-extent": "^0.3.1",
@ -59,9 +58,9 @@
"pelias-config": "2.11.0", "pelias-config": "2.11.0",
"pelias-labels": "1.6.0", "pelias-labels": "1.6.0",
"pelias-logger": "0.2.0", "pelias-logger": "0.2.0",
"pelias-microservice-wrapper": "1.1.2", "pelias-microservice-wrapper": "1.1.3",
"pelias-model": "4.8.1", "pelias-model": "5.0.0",
"pelias-query": "8.15.0", "pelias-query": "8.16.1",
"pelias-sorting": "1.0.1", "pelias-sorting": "1.0.1",
"pelias-text-analyzer": "1.8.3", "pelias-text-analyzer": "1.8.3",
"predicates": "^1.0.1", "predicates": "^1.0.1",
@ -77,7 +76,7 @@
"jshint": "^2.5.6", "jshint": "^2.5.6",
"npm-check": "git://github.com/orangejulius/npm-check.git#disable-update-check", "npm-check": "git://github.com/orangejulius/npm-check.git#disable-update-check",
"nsp": "^2.2.0", "nsp": "^2.2.0",
"pelias-mock-logger": "1.1.0", "pelias-mock-logger": "1.1.1",
"precommit-hook": "^3.0.0", "precommit-hook": "^3.0.0",
"proxyquire": "^1.7.10", "proxyquire": "^1.7.10",
"semantic-release": "^6.3.2", "semantic-release": "^6.3.2",

25
query/reverse.js

@ -65,13 +65,24 @@ function generateQuery( clean ){
// where point.lan/point.lon are provided in the // where point.lan/point.lon are provided in the
// absense of boundary.circle.lat/boundary.circle.lon // absense of boundary.circle.lat/boundary.circle.lon
if( check.number(clean['boundary.circle.lat']) && if( check.number(clean['boundary.circle.lat']) &&
check.number(clean['boundary.circle.lon']) && check.number(clean['boundary.circle.lon']) ){
check.number(clean['boundary.circle.radius']) ){
vs.set({ vs.set({
'boundary:circle:lat': clean['boundary.circle.lat'], 'boundary:circle:lat': clean['boundary.circle.lat'],
'boundary:circle:lon': clean['boundary.circle.lon'], 'boundary:circle:lon': clean['boundary.circle.lon']
'boundary:circle:radius': clean['boundary.circle.radius'] + 'km' });
});
if (check.undefined(clean['boundary.circle.radius'])){
// for coarse reverse when boundary circle radius is undefined
vs.set({
'boundary:circle:radius': defaults['boundary:circle:radius']
});
} else if (check.number(clean['boundary.circle.radius'])){
// plain reverse where boundary circle is a valid number
vs.set({
'boundary:circle:radius': clean['boundary.circle.radius'] + 'km'
});
}
logStr += '[param:boundary_circle] '; logStr += '[param:boundary_circle] ';
} }

34
routes/legacy.js

@ -1,34 +0,0 @@
var proxy = require('express-http-proxy');
function addRoutes(app, peliasConfig) {
var sendToLegacy;
if (!peliasConfig.hasOwnProperty('legacyUrl')) {
sendToLegacy = function redirectToV1(req, res, next) {
res.redirect(301, '/v1');
};
}
else {
sendToLegacy = proxy(peliasConfig.legacyUrl);
}
// api root
app.get( '/', sendToLegacy );
// place API
app.get( '/place', sendToLegacy);
// suggest APIs
app.get( '/suggest', sendToLegacy );
app.get( '/suggest/nearby', sendToLegacy );
app.get( '/suggest/coarse',sendToLegacy );
// search APIs
app.get( '/search', sendToLegacy);
app.get( '/search/coarse', sendToLegacy);
// reverse API
app.get( '/reverse', sendToLegacy );
}
module.exports.addRoutes = addRoutes;

6
routes/v1.js

@ -129,7 +129,7 @@ function addRoutes(app, peliasConfig) {
controllers.mdToHTML(peliasConfig.api, './public/attribution.md') controllers.mdToHTML(peliasConfig.api, './public/attribution.md')
]), ]),
search: createRouter([ search: createRouter([
sanitizers.search.middleware, sanitizers.search.middleware(peliasConfig.api),
middleware.requestLanguage, middleware.requestLanguage,
middleware.calcSize(), middleware.calcSize(),
controllers.placeholder(placeholderService, placeholderShouldExecute), controllers.placeholder(placeholderService, placeholderShouldExecute),
@ -156,7 +156,7 @@ function addRoutes(app, peliasConfig) {
postProc.sendJSON postProc.sendJSON
]), ]),
structured: createRouter([ structured: createRouter([
sanitizers.structured_geocoding.middleware, sanitizers.structured_geocoding.middleware(peliasConfig.api),
middleware.requestLanguage, middleware.requestLanguage,
middleware.calcSize(), middleware.calcSize(),
controllers.search(peliasConfig.api, esclient, queries.structured_geocoding, not(hasResponseDataOrRequestErrors)), controllers.search(peliasConfig.api, esclient, queries.structured_geocoding, not(hasResponseDataOrRequestErrors)),
@ -177,7 +177,7 @@ function addRoutes(app, peliasConfig) {
postProc.sendJSON postProc.sendJSON
]), ]),
autocomplete: createRouter([ autocomplete: createRouter([
sanitizers.autocomplete.middleware, sanitizers.autocomplete.middleware(peliasConfig.api),
middleware.requestLanguage, middleware.requestLanguage,
controllers.search(peliasConfig.api, esclient, queries.autocomplete, not(hasResponseDataOrRequestErrors)), controllers.search(peliasConfig.api, esclient, queries.autocomplete, not(hasResponseDataOrRequestErrors)),
postProc.distances('focus.point.'), postProc.distances('focus.point.'),

32
sanitizer/_details.js

@ -1,32 +0,0 @@
var _ = require('lodash'),
check = require('check-types');
var DEFAULT_DETAILS_BOOL = true;
// validate inputs, convert types and apply defaults
function sanitize( raw, clean ){
// error & warning messages
var messages = { errors: [], warnings: [] };
if( !check.undefined( raw.details ) ){
clean.details = isTruthy( raw.details );
} else {
clean.details = DEFAULT_DETAILS_BOOL;
}
return messages;
}
// be lenient with 'truthy' values
function isTruthy(val) {
if( check.string( val ) ){
return _.includes( ['true', '1'], val );
}
return val === 1 || val === true;
}
// export function
module.exports = sanitize;

5
sanitizer/_geo_reverse.js

@ -29,11 +29,6 @@ module.exports = function sanitize( raw, clean ){
raw['boundary.circle.lat'] = clean['point.lat']; raw['boundary.circle.lat'] = clean['point.lat'];
raw['boundary.circle.lon'] = clean['point.lon']; raw['boundary.circle.lon'] = clean['point.lon'];
// if no radius was passed, set the default
if ( _.isUndefined( raw['boundary.circle.radius'] ) ) {
raw['boundary.circle.radius'] = defaults['boundary:circle:radius'];
}
// santize the boundary.circle // santize the boundary.circle
geo_common.sanitize_circle( 'boundary.circle', clean, raw, CIRCLE_IS_REQUIRED ); geo_common.sanitize_circle( 'boundary.circle', clean, raw, CIRCLE_IS_REQUIRED );

31
sanitizer/_location_bias.js

@ -0,0 +1,31 @@
const _ = require('lodash');
/**
Set a focus.lat and focus.lon if specified in pelias config
* @param {object} defaultParameters property of pelias config
*/
function setup(defaultParameters){
return function setLocationBias(raw, clean){
/*
check that:
1. {object} raw exists
2. pelias-config included the properties focus.point.lat and focus.point.lon
3. raw.focus.point.lon and raw.focus.point.lat have not been set
*/
if (!_.isUndefined(raw) &&
!_.isUndefined(defaultParameters['focus.point.lat']) &&
!_.isUndefined(defaultParameters['focus.point.lon']) &&
!_.has(raw, 'focus.point.lon') &&
!_.has(raw, 'focus.point.lat') ) {
raw['focus.point.lat'] = defaultParameters['focus.point.lat'];
raw['focus.point.lon'] = defaultParameters['focus.point.lon'];
}
return { errors: [], warnings: [] };
};
}
// if focus.point.lat and focus.point.lon already exists, don't change
module.exports = setup;

29
sanitizer/autocomplete.js

@ -1,7 +1,9 @@
var type_mapping = require('../helper/type_mapping'); var type_mapping = require('../helper/type_mapping');
var sanitizeAll = require('../sanitizer/sanitizeAll');
var sanitizeAll = require('../sanitizer/sanitizeAll'), // middleware
sanitizers = { module.exports.middleware = (_api_pelias_config) => {
var sanitizers = {
singleScalarParameters: require('../sanitizer/_single_scalar_parameters'), singleScalarParameters: require('../sanitizer/_single_scalar_parameters'),
text: require('../sanitizer/_text_addressit'), text: require('../sanitizer/_text_addressit'),
tokenizer: require('../sanitizer/_tokenizer'), tokenizer: require('../sanitizer/_tokenizer'),
@ -11,24 +13,21 @@ var sanitizeAll = require('../sanitizer/sanitizeAll'),
// depends on the layers and sources sanitizers, must be run after them // depends on the layers and sources sanitizers, must be run after them
sources_and_layers: require('../sanitizer/_sources_and_layers'), sources_and_layers: require('../sanitizer/_sources_and_layers'),
private: require('../sanitizer/_flag_bool')('private', false), private: require('../sanitizer/_flag_bool')('private', false),
location_bias: require('../sanitizer/_location_bias')(_api_pelias_config.defaultParameters),
geo_autocomplete: require('../sanitizer/_geo_autocomplete'), geo_autocomplete: require('../sanitizer/_geo_autocomplete'),
boundary_country: require('../sanitizer/_boundary_country'), boundary_country: require('../sanitizer/_boundary_country'),
categories: require('../sanitizer/_categories') categories: require('../sanitizer/_categories')
}; };
var sanitize = function(req, cb) { sanitizeAll(req, sanitizers, cb); }; var sanitize = function(req, cb) { sanitizeAll(req, sanitizers, cb); };
// export sanitize for testing
module.exports.sanitize = sanitize;
module.exports.sanitizer_list = sanitizers;
// middleware return function( req, res, next ){
module.exports.middleware = function( req, res, next ){ sanitize( req, function( err, clean ){
sanitize( req, function( err, clean ){ if( err ){
if( err ){ res.status(400); // 400 Bad Request
res.status(400); // 400 Bad Request return next(err);
return next(err); }
}
next(); next();
}); });
};
}; };

53
sanitizer/search.js

@ -1,30 +1,33 @@
var type_mapping = require('../helper/type_mapping'); var type_mapping = require('../helper/type_mapping');
var sanitizeAll = require('../sanitizer/sanitizeAll');
// middleware
module.exports.middleware = (_api_pelias_config) => {
var sanitizers = {
singleScalarParameters: require('../sanitizer/_single_scalar_parameters'),
quattroshapes_deprecation: require('../sanitizer/_deprecate_quattroshapes'),
text: require('../sanitizer/_text'),
iso2_to_iso3: require('../sanitizer/_iso2_to_iso3'),
city_name_standardizer: require('../sanitizer/_city_name_standardizer'),
size: require('../sanitizer/_size')(/* use defaults*/),
layers: require('../sanitizer/_targets')('layers', type_mapping.layer_mapping),
sources: require('../sanitizer/_targets')('sources', type_mapping.source_mapping),
// depends on the layers and sources sanitizers, must be run after them
sources_and_layers: require('../sanitizer/_sources_and_layers'),
private: require('../sanitizer/_flag_bool')('private', false),
location_bias: require('../sanitizer/_location_bias')(_api_pelias_config.defaultParameters),
geo_search: require('../sanitizer/_geo_search'),
boundary_country: require('../sanitizer/_boundary_country'),
categories: require('../sanitizer/_categories'),
// this can go away once geonames has been abrogated
geonames_warnings: require('../sanitizer/_geonames_warnings')
};
var sanitizeAll = require('../sanitizer/sanitizeAll'), var sanitize = function(req, cb) { sanitizeAll(req, sanitizers, cb); };
sanitizers = {
singleScalarParameters: require('../sanitizer/_single_scalar_parameters'),
quattroshapes_deprecation: require('../sanitizer/_deprecate_quattroshapes'),
text: require('../sanitizer/_text'),
iso2_to_iso3: require('../sanitizer/_iso2_to_iso3'),
city_name_standardizer: require('../sanitizer/_city_name_standardizer'),
size: require('../sanitizer/_size')(/* use defaults*/),
layers: require('../sanitizer/_targets')('layers', type_mapping.layer_mapping),
sources: require('../sanitizer/_targets')('sources', type_mapping.source_mapping),
// depends on the layers and sources sanitizers, must be run after them
sources_and_layers: require('../sanitizer/_sources_and_layers'),
private: require('../sanitizer/_flag_bool')('private', false),
geo_search: require('../sanitizer/_geo_search'),
boundary_country: require('../sanitizer/_boundary_country'),
categories: require('../sanitizer/_categories'),
// this can go away once geonames has been abrogated
geonames_warnings: require('../sanitizer/_geonames_warnings')
};
var sanitize = function(req, cb) { sanitizeAll(req, sanitizers, cb); }; return function( req, res, next ){
sanitize( req, function( err, clean ){
next();
});
};
// middleware
module.exports.middleware = function( req, res, next ){
sanitize( req, function( err, clean ){
next();
});
}; };

50
sanitizer/structured_geocoding.js

@ -1,28 +1,30 @@
var type_mapping = require('../helper/type_mapping'); var type_mapping = require('../helper/type_mapping');
var sanitizeAll = require('../sanitizer/sanitizeAll');
var sanitizeAll = require('../sanitizer/sanitizeAll'),
sanitizers = {
singleScalarParameters: require('../sanitizer/_single_scalar_parameters'),
quattroshapes_deprecation: require('../sanitizer/_deprecate_quattroshapes'),
synthesize_analysis: require('../sanitizer/_synthesize_analysis'),
iso2_to_iso3: require('../sanitizer/_iso2_to_iso3'),
city_name_standardizer: require('../sanitizer/_city_name_standardizer'),
size: require('../sanitizer/_size')(/* use defaults*/),
layers: require('../sanitizer/_targets')('layers', type_mapping.layer_mapping),
sources: require('../sanitizer/_targets')('sources', type_mapping.source_mapping),
// depends on the layers and sources sanitizers, must be run after them
sources_and_layers: require('../sanitizer/_sources_and_layers'),
private: require('../sanitizer/_flag_bool')('private', false),
geo_search: require('../sanitizer/_geo_search'),
boundary_country: require('../sanitizer/_boundary_country'),
categories: require('../sanitizer/_categories')
};
var sanitize = function(req, cb) { sanitizeAll(req, sanitizers, cb); };
// middleware // middleware
module.exports.middleware = function( req, res, next ){ module.exports.middleware = (_api_pelias_config) => {
sanitize( req, function( err, clean ){ var sanitizers = {
next(); singleScalarParameters: require('../sanitizer/_single_scalar_parameters'),
}); quattroshapes_deprecation: require('../sanitizer/_deprecate_quattroshapes'),
synthesize_analysis: require('../sanitizer/_synthesize_analysis'),
iso2_to_iso3: require('../sanitizer/_iso2_to_iso3'),
city_name_standardizer: require('../sanitizer/_city_name_standardizer'),
size: require('../sanitizer/_size')(/* use defaults*/),
layers: require('../sanitizer/_targets')('layers', type_mapping.layer_mapping),
sources: require('../sanitizer/_targets')('sources', type_mapping.source_mapping),
// depends on the layers and sources sanitizers, must be run after them
sources_and_layers: require('../sanitizer/_sources_and_layers'),
private: require('../sanitizer/_flag_bool')('private', false),
location_bias: require('../sanitizer/_location_bias')(_api_pelias_config.defaultParameters),
geo_search: require('../sanitizer/_geo_search'),
boundary_country: require('../sanitizer/_boundary_country'),
categories: require('../sanitizer/_categories')
};
var sanitize = function(req, cb) { sanitizeAll(req, sanitizers, cb); };
return function( req, res, next ){
sanitize( req, function( err, clean ){
next();
});
};
}; };

8
schema.js

@ -12,14 +12,12 @@ const Joi = require('joi');
// optional: // optional:
// * api.accessLog (string) // * api.accessLog (string)
// * api.relativeScores (boolean) // * api.relativeScores (boolean)
// * api.legacyUrl (string)
// * api.localization (flipNumberAndStreetCountries is array of 3 character strings) // * api.localization (flipNumberAndStreetCountries is array of 3 character strings)
module.exports = Joi.object().keys({ module.exports = Joi.object().keys({
api: Joi.object().keys({ api: Joi.object().keys({
version: Joi.string(), version: Joi.string(),
indexName: Joi.string(), indexName: Joi.string(),
host: Joi.string(), host: Joi.string(),
legacyUrl: Joi.string(),
accessLog: Joi.string(), accessLog: Joi.string(),
relativeScores: Joi.boolean(), relativeScores: Joi.boolean(),
requestRetries: Joi.number().integer().min(0), requestRetries: Joi.number().integer().min(0),
@ -39,7 +37,11 @@ module.exports = Joi.object().keys({
timeout: Joi.number().integer().optional().default(250).min(0), timeout: Joi.number().integer().optional().default(250).min(0),
retries: Joi.number().integer().optional().default(3).min(0), retries: Joi.number().integer().optional().default(3).min(0),
}).unknown(false).requiredKeys('url') }).unknown(false).requiredKeys('url')
}).unknown(false).default({}) // default api.services to an empty object }).unknown(false).default({}), // default api.services to an empty object
defaultParameters: Joi.object().keys({
'focus.point.lat': Joi.number(),
'focus.point.lon': Joi.number(),
}).unknown(true).default({})
}).requiredKeys('version', 'indexName', 'host').unknown(true), }).requiredKeys('version', 'indexName', 'host').unknown(true),
esclient: Joi.object().keys({ esclient: Joi.object().keys({

51
test/unit/controller/placeholder.js

@ -287,8 +287,7 @@ module.exports.tests.success = (test, common) => {
'default': 'name 3' 'default': 'name 3'
}, },
population: 4321, population: 4321,
popularity: 8765, popularity: 8765
parent: { }
} }
] ]
}; };
@ -352,8 +351,7 @@ module.exports.tests.success = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: { }
} }
] ]
}; };
@ -413,8 +411,7 @@ module.exports.tests.success = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: { }
} }
] ]
}; };
@ -472,8 +469,7 @@ module.exports.tests.success = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: { }
} }
] ]
}; };
@ -538,8 +534,7 @@ module.exports.tests.success = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 2' 'default': 'name 2'
}, }
parent: { }
} }
] ]
}; };
@ -608,8 +603,7 @@ module.exports.tests.success = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: { }
} }
] ]
}; };
@ -782,8 +776,7 @@ module.exports.tests.result_filtering = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: { }
}, },
{ {
_id: '10', _id: '10',
@ -800,8 +793,7 @@ module.exports.tests.result_filtering = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 10' 'default': 'name 10'
}, }
parent: { }
} }
] ]
}; };
@ -968,8 +960,7 @@ module.exports.tests.result_filtering = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: { }
}, },
{ {
_id: '10', _id: '10',
@ -986,8 +977,7 @@ module.exports.tests.result_filtering = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 10' 'default': 'name 10'
}, }
parent: { }
} }
] ]
}; };
@ -1107,8 +1097,7 @@ module.exports.tests.result_filtering = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: { }
}, },
{ {
_id: '3', _id: '3',
@ -1125,8 +1114,7 @@ module.exports.tests.result_filtering = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 3' 'default': 'name 3'
}, }
parent: { }
}, },
{ {
_id: '5', _id: '5',
@ -1143,8 +1131,7 @@ module.exports.tests.result_filtering = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 5' 'default': 'name 5'
}, }
parent: { }
} }
] ]
}; };
@ -1567,8 +1554,7 @@ module.exports.tests.geometry_errors = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: {}
} }
] ]
}; };
@ -1628,8 +1614,7 @@ module.exports.tests.centroid_errors = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: { }
} }
] ]
}; };
@ -1689,8 +1674,7 @@ module.exports.tests.centroid_errors = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: { }
} }
] ]
}; };
@ -1763,8 +1747,7 @@ module.exports.tests.boundingbox_errors = (test, common) => {
}, },
phrase: { phrase: {
'default': 'name 1' 'default': 'name 1'
}, }
parent: { }
} }
] ]
}; };

41
test/unit/fixture/search_boundary_country.js

@ -2,32 +2,29 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.street',
'_name': 'fallback.street', 'boost': 5,
'boost': 5, 'must': [
'must': [ {
{ 'match_phrase': {
'match_phrase': { 'address_parts.street': 'street value'
'address_parts.street': 'street value'
}
}
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
} }
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
] }
} }
}, ],
'filter': { 'filter': {
'bool': { 'bool': {
'must': [ 'must': [

1594
test/unit/fixture/search_fallback.js

File diff suppressed because it is too large Load Diff

50
test/unit/fixture/search_fallback_postalcode_only.js

@ -2,39 +2,31 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.postalcode',
'_name': 'fallback.postalcode', 'must': [
'must': [ {
{ 'multi_match': {
'multi_match': { 'query': '90210',
'query': '90210', 'type': 'phrase',
'type': 'phrase', 'fields': [
'fields': [ 'parent.postalcode'
'parent.postalcode' ]
]
}
}
],
'filter': {
'term': {
'layer': 'postalcode'
}
} }
} }
],
'filter': {
'term': {
'layer': 'postalcode'
}
} }
] }
}
},
'filter': {
'bool': {
'must': []
} }
} ]
} }
}, },
'max_boost': 20, 'max_boost': 20,

41
test/unit/fixture/search_linguistic_bbox.js

@ -2,32 +2,29 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.street',
'_name': 'fallback.street', 'boost': 5,
'boost': 5, 'must': [
'must': [ {
{ 'match_phrase': {
'match_phrase': { 'address_parts.street': 'street value'
'address_parts.street': 'street value'
}
}
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
} }
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
] }
} }
}, ],
'filter': { 'filter': {
'bool': { 'bool': {
'must': [ 'must': [

41
test/unit/fixture/search_linguistic_focus.js

@ -2,32 +2,29 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.street',
'_name': 'fallback.street', 'boost': 5,
'boost': 5, 'must': [
'must': [ {
{ 'match_phrase': {
'match_phrase': { 'address_parts.street': 'street value'
'address_parts.street': 'street value'
}
}
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
} }
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
] }
} }
}, ],
'filter': { 'filter': {
'bool': { 'bool': {
'must': [ 'must': [

41
test/unit/fixture/search_linguistic_focus_bbox.js

@ -2,32 +2,29 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.street',
'_name': 'fallback.street', 'boost': 5,
'boost': 5, 'must': [
'must': [ {
{ 'match_phrase': {
'match_phrase': { 'address_parts.street': 'street value'
'address_parts.street': 'street value'
}
}
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
} }
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
] }
} }
}, ],
'filter': { 'filter': {
'bool': { 'bool': {
'must': [ 'must': [

41
test/unit/fixture/search_linguistic_focus_null_island.js

@ -2,32 +2,29 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.street',
'_name': 'fallback.street', 'boost': 5,
'boost': 5, 'must': [
'must': [ {
{ 'match_phrase': {
'match_phrase': { 'address_parts.street': 'street value'
'address_parts.street': 'street value'
}
}
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
} }
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
] }
} }
}, ],
'filter': { 'filter': {
'bool': { 'bool': {
'must': [ 'must': [

41
test/unit/fixture/search_linguistic_only.js

@ -2,32 +2,29 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.street',
'_name': 'fallback.street', 'boost': 5,
'boost': 5, 'must': [
'must': [ {
{ 'match_phrase': {
'match_phrase': { 'address_parts.street': 'street value'
'address_parts.street': 'street value'
}
}
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
} }
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
] }
} }
}, ],
'filter': { 'filter': {
'bool': { 'bool': {
'must': [ 'must': [

41
test/unit/fixture/search_linguistic_viewport.js

@ -2,32 +2,29 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.street',
'_name': 'fallback.street', 'boost': 5,
'boost': 5, 'must': [
'must': [ {
{ 'match_phrase': {
'match_phrase': { 'address_parts.street': 'street value'
'address_parts.street': 'street value'
}
}
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
} }
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
] }
} }
}, ],
'filter': { 'filter': {
'bool': { 'bool': {
'must': [ 'must': [

41
test/unit/fixture/search_linguistic_viewport_min_diagonal.js

@ -2,32 +2,29 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.street',
'_name': 'fallback.street', 'boost': 5,
'boost': 5, 'must': [
'must': [ {
{ 'match_phrase': {
'match_phrase': { 'address_parts.street': 'street value'
'address_parts.street': 'street value'
}
}
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
} }
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
] }
} }
}, ],
'filter': { 'filter': {
'bool': { 'bool': {
'must': [ 'must': [

41
test/unit/fixture/search_with_category_filtering.js

@ -2,32 +2,29 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.street',
'_name': 'fallback.street', 'boost': 5,
'boost': 5, 'must': [
'must': [ {
{ 'match_phrase': {
'match_phrase': { 'address_parts.street': 'street value'
'address_parts.street': 'street value'
}
}
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
} }
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
] }
} }
}, ],
'filter': { 'filter': {
'bool': { 'bool': {
'must': [ 'must': [

41
test/unit/fixture/search_with_source_filtering.js

@ -2,32 +2,29 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.street',
'_name': 'fallback.street', 'boost': 5,
'boost': 5, 'must': [
'must': [ {
{ 'match_phrase': {
'match_phrase': { 'address_parts.street': 'street value'
'address_parts.street': 'street value'
}
}
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
} }
],
'should': [],
'filter': {
'term': {
'layer': 'street'
}
} }
] }
} }
}, ],
'filter': { 'filter': {
'bool': { 'bool': {
'must': [ 'must': [

11
test/unit/fixture/structured_geocoding/boundary_country.json

@ -2,12 +2,9 @@
"query": { "query": {
"function_score": { "function_score": {
"query": { "query": {
"filtered": { "bool": {
"query": { "minimum_should_match": 1,
"bool": { "should": [],
"should": []
}
},
"filter": { "filter": {
"bool": { "bool": {
"must": [ "must": [
@ -59,4 +56,4 @@
], ],
"size": 10, "size": 10,
"track_scores": true "track_scores": true
} }

1596
test/unit/fixture/structured_geocoding/fallback.json

File diff suppressed because it is too large Load Diff

11
test/unit/fixture/structured_geocoding/linguistic_bbox.json

@ -2,12 +2,9 @@
"query": { "query": {
"function_score": { "function_score": {
"query": { "query": {
"filtered": { "bool": {
"query": { "minimum_should_match": 1,
"bool": { "should": [],
"should": []
}
},
"filter": { "filter": {
"bool": { "bool": {
"must": [ "must": [
@ -62,4 +59,4 @@
], ],
"size": 10, "size": 10,
"track_scores": true "track_scores": true
} }

11
test/unit/fixture/structured_geocoding/linguistic_focus.json

@ -2,12 +2,9 @@
"query": { "query": {
"function_score": { "function_score": {
"query": { "query": {
"filtered": { "bool": {
"query": { "minimum_should_match": 1,
"bool": { "should": [],
"should": []
}
},
"filter": { "filter": {
"bool": { "bool": {
"must": [ "must": [
@ -65,4 +62,4 @@
], ],
"size": 10, "size": 10,
"track_scores": true "track_scores": true
} }

9
test/unit/fixture/structured_geocoding/linguistic_focus_bbox.json

@ -2,12 +2,9 @@
"query": { "query": {
"function_score": { "function_score": {
"query": { "query": {
"filtered": { "bool": {
"query": { "minimum_should_match": 1,
"bool": { "should": [],
"should": []
}
},
"filter": { "filter": {
"bool": { "bool": {
"must": [ "must": [

11
test/unit/fixture/structured_geocoding/linguistic_focus_null_island.json

@ -2,12 +2,9 @@
"query": { "query": {
"function_score": { "function_score": {
"query": { "query": {
"filtered": { "bool": {
"query": { "minimum_should_match": 1,
"bool": { "should": [],
"should": []
}
},
"filter": { "filter": {
"bool": { "bool": {
"must": [ "must": [
@ -65,4 +62,4 @@
], ],
"size": 10, "size": 10,
"track_scores": true "track_scores": true
} }

11
test/unit/fixture/structured_geocoding/linguistic_only.json

@ -2,12 +2,9 @@
"query": { "query": {
"function_score": { "function_score": {
"query": { "query": {
"filtered": { "bool": {
"query": { "minimum_should_match": 1,
"bool": { "should": [],
"should": []
}
},
"filter": { "filter": {
"bool": { "bool": {
"must": [ "must": [
@ -51,4 +48,4 @@
], ],
"size": 10, "size": 10,
"track_scores": true "track_scores": true
} }

11
test/unit/fixture/structured_geocoding/linguistic_viewport.json

@ -2,12 +2,9 @@
"query": { "query": {
"function_score": { "function_score": {
"query": { "query": {
"filtered": { "bool": {
"query": { "minimum_should_match": 1,
"bool": { "should": [],
"should": []
}
},
"filter": { "filter": {
"bool": { "bool": {
"must": [ "must": [
@ -51,4 +48,4 @@
], ],
"size": 10, "size": 10,
"track_scores": true "track_scores": true
} }

11
test/unit/fixture/structured_geocoding/linguistic_viewport_min_diagonal.json

@ -2,12 +2,9 @@
"query": { "query": {
"function_score": { "function_score": {
"query": { "query": {
"filtered": { "bool": {
"query": { "minimum_should_match": 1,
"bool": { "should": [],
"should": []
}
},
"filter": { "filter": {
"bool": { "bool": {
"must": [ "must": [
@ -51,4 +48,4 @@
], ],
"size": 10, "size": 10,
"track_scores": true "track_scores": true
} }

50
test/unit/fixture/structured_geocoding/postalcode_only.js

@ -2,39 +2,31 @@ module.exports = {
'query': { 'query': {
'function_score': { 'function_score': {
'query': { 'query': {
'filtered': { 'bool': {
'query': { 'minimum_should_match': 1,
'bool': { 'should': [
'should': [ {
{ 'bool': {
'bool': { '_name': 'fallback.postalcode',
'_name': 'fallback.postalcode', 'must': [
'must': [ {
{ 'multi_match': {
'multi_match': { 'query': 'postalcode value',
'query': 'postalcode value', 'type': 'phrase',
'type': 'phrase', 'fields': [
'fields': [ 'parent.postalcode'
'parent.postalcode' ]
]
}
}
],
'filter': {
'term': {
'layer': 'postalcode'
}
} }
} }
],
'filter': {
'term': {
'layer': 'postalcode'
}
} }
] }
}
},
'filter': {
'bool': {
'must': []
} }
} ]
} }
}, },
'max_boost': 20, 'max_boost': 20,

12
test/unit/fixture/structured_geocoding/with_source_filtering.json

@ -2,12 +2,10 @@
"query": { "query": {
"function_score": { "function_score": {
"query": { "query": {
"filtered": { "bool": {
"query": { "minimum_should_match": 1,
"bool": { "should": [
"should": [] ],
}
},
"filter": { "filter": {
"bool": { "bool": {
"must": [ "must": [
@ -51,4 +49,4 @@
], ],
"size": 20, "size": 20,
"track_scores": true "track_scores": true
} }

84
test/unit/middleware/changeLanguage.js

@ -2,6 +2,7 @@
var fs = require('fs'), var fs = require('fs'),
tmp = require('tmp'), tmp = require('tmp'),
setup = require('../../../middleware/changeLanguage'); setup = require('../../../middleware/changeLanguage');
const proxyquire = require('proxyquire').noCallThru();
// load middleware using the default pelias config // load middleware using the default pelias config
var load = function(){ var load = function(){
@ -144,7 +145,7 @@ module.exports.tests.hit = function(test, common) {
name: { default: 'London' }, name: { default: 'London' },
parent: { parent: {
locality_id: [ 101735809 ], locality_id: [ 101735809 ],
locaity: [ 'London' ] locality: [ 'London' ]
} }
} }
]}; ]};
@ -158,23 +159,23 @@ module.exports.tests.hit = function(test, common) {
cb( null, { cb( null, {
'101750367': { '101750367': {
'names': { 'names': {
'default':'London', 'default':['London'],
'chi':'倫敦', 'chi':['倫敦'],
'spa':'Londres', 'spa':['Londres'],
'eng':'London', 'eng':['London'],
'hin':'लदन', 'hin':['लदन'],
'ara':'لندن', 'ara':['لندن'],
'por':'Londres', 'por':['Londres'],
'ben':'লনডন', 'ben':['লনডন'],
'rus':'Лондон', 'rus':['Лондон'],
'jpn':'ロンドン', 'jpn':['ロンドン'],
'kor':'런던' 'kor':['런던']
} }
}, },
'101735809': { '101735809': {
'names':{ 'names':{
'default':'London', 'default':['London'],
'eng':'London' 'eng':['London']
} }
} }
}); });
@ -195,13 +196,66 @@ module.exports.tests.hit = function(test, common) {
name: { default: 'London' }, name: { default: 'London' },
parent: { parent: {
locality_id: [ 101735809 ], locality_id: [ 101735809 ],
locaity: [ 'London' ] locality: [ 'London' ]
} }
} }
]}); ]});
t.end(); t.end();
}); });
}); });
test('empty array name translation should not change the value', t => {
t.plan(2);
const req = { language: { iso6393: 'ISO3 value' } };
const res = {
data: [
{
layer: 'locality',
name: { default: 'original name' },
parent: {
locality_id: [ 123 ],
locality: [ 'original name' ]
}
}
]
};
const changeLanguage = proxyquire('../../../middleware/changeLanguage', {
'../service/language': {
findById: () => ({
query: (ids, callback) => {
t.deepEquals(ids, ['123']);
callback(null, {
'123': {
'names': {
'ISO3 value':[]
}
}
});
}
})
}
})();
changeLanguage(req, res, () => {
t.deepEqual( res, { data: [
{
layer: 'locality',
name: {
default: 'original name'
},
parent: {
locality_id: [ 123 ],
locality: [ 'original name' ]
}
}
]});
});
});
}; };
module.exports.all = function (tape, common) { module.exports.all = function (tape, common) {

17
test/unit/query/reverse.js

@ -61,6 +61,23 @@ module.exports.tests.query = function(test, common) {
t.end(); t.end();
}); });
// for coarse reverse cases where boundary circle radius isn't used
test('undefined radius set to default radius', function(t) {
var query = generate({
'point.lat': 12.12121,
'point.lon': 21.21212,
'boundary.circle.lat': 12.12121,
'boundary.circle.lon': 21.21212
});
var compiled = JSON.parse( JSON.stringify( query ) );
var expected = '1km';
t.deepEqual(compiled.type, 'reverse', 'query type set');
t.deepEqual(compiled.body.query.bool.filter[0].geo_distance.distance, expected, 'distance set to default boundary circle radius');
t.end();
});
test('boundary.circle lat/lon/radius - overrides point.lat/lon when set', function(t) { test('boundary.circle lat/lon/radius - overrides point.lat/lon when set', function(t) {
var clean = { var clean = {
'point.lat': 29.49136, 'point.lat': 29.49136,

1
test/unit/run.js

@ -64,6 +64,7 @@ var tests = [
require('./sanitizer/_ids'), require('./sanitizer/_ids'),
require('./sanitizer/_iso2_to_iso3'), require('./sanitizer/_iso2_to_iso3'),
require('./sanitizer/_layers'), require('./sanitizer/_layers'),
require('./sanitizer/_location_bias'),
require('./sanitizer/_city_name_standardizer'), require('./sanitizer/_city_name_standardizer'),
require('./sanitizer/_single_scalar_parameters'), require('./sanitizer/_single_scalar_parameters'),
require('./sanitizer/_size'), require('./sanitizer/_size'),

22
test/unit/sanitizer/_geo_reverse.js

@ -84,31 +84,11 @@ module.exports.tests.success_conditions = (test, common) => {
}); });
test('boundary.circle.radius not specified should use default', (t) => {
const raw = {
'point.lat': '12.121212',
'point.lon': '21.212121'
};
const clean = {};
const errorsAndWarnings = sanitize(raw, clean);
t.equals(raw['boundary.circle.lat'], 12.121212);
t.equals(raw['boundary.circle.lon'], 21.212121);
t.equals(raw['boundary.circle.radius'], defaults['boundary:circle:radius'], 'should be from defaults');
t.equals(clean['boundary.circle.lat'], 12.121212);
t.equals(clean['boundary.circle.lon'], 21.212121);
t.equals(clean['boundary.circle.radius'], parseFloat(defaults['boundary:circle:radius']), 'should be same as raw');
t.deepEquals(errorsAndWarnings, { errors: [], warnings: [] });
t.end();
});
}; };
module.exports.all = (tape, common) => { module.exports.all = (tape, common) => {
function test(name, testFunction) { function test(name, testFunction) {
return tape(`SANTIZE _geo_reverse ${name}`, testFunction); return tape(`SANITIZE _geo_reverse ${name}`, testFunction);
} }
for( const testCase in module.exports.tests ){ for( const testCase in module.exports.tests ){

109
test/unit/sanitizer/_location_bias.js

@ -0,0 +1,109 @@
const setup = require('../../../sanitizer/_location_bias');
module.exports.tests = {};
module.exports.tests.setLocationBias = function(test, common) {
test('set focus point', t => {
const defaultParameters = { // specify focus point latitude and longitude
'focus.point.lat': 12.12121212,
'focus.point.lon': 21.21212121
};
const locationBias = setup(defaultParameters);
const raw = {};
const expected = {
'focus.point.lat': 12.12121212,
'focus.point.lon': 21.21212121
};
locationBias(raw, undefined);
t.deepEqual(raw, expected, 'focus point should be set');
t.end();
});
test('undefined raw', t => {
const defaultParameters = {
'focus.point.lat': 12.12121212,
'focus.point.lon': 21.21212121
};
const locationBias = setup(defaultParameters);
locationBias(undefined, undefined);
t.deepEqual(undefined, undefined, 'should be unmodified' );
t.end();
});
test('focusPointLat is undefined', t => {
const defaultParameters = {
'focus.point.lon': 12.2121212
};
const locationBias = setup(defaultParameters);
const raw = {};
const expected = {};
locationBias(raw, undefined);
t.deepEqual(raw, expected, 'should be unmodified' );
t.end();
});
test('focusPointLon is undefined', t => {
const defaultParameters = {
'focus.point.lat': 12.2121212
};
const locationBias = setup(defaultParameters);
const raw = {};
const expected = {};
locationBias(raw, undefined);
t.deepEqual(raw, expected, 'should be unmodified' );
t.end();
});
test('raw has focus.point.lon already', t => {
const defaultParameters = {
'focus.point.lon': 12.2121212,
'focus.point.lat': 12.2121212
};
const locationBias = setup(defaultParameters);
const raw = {
'focus.point.lon': 43.4343434
};
const expected = {
'focus.point.lon': 43.4343434
};
locationBias(raw, undefined);
t.deepEqual(raw, expected, 'should be unmodified' );
t.end();
});
test('raw has focus.point.lat already', t => {
const defaultParameters = {
'focus.point.lon': 12.2121212,
'focus.point.lat': 12.2121212
};
const locationBias = setup(defaultParameters);
const raw = {
'focus.point.lat': 34.3434343
};
const expected = {
'focus.point.lat': 34.3434343
};
locationBias(raw, undefined);
t.deepEqual(raw, expected, 'should be unmodified' );
t.end();
});
};
module.exports.all = (tape, common) => {
function test(name, testFunction) {
return tape(`SANITIZE _location_bias: ${name}`, testFunction);
}
for( var testCase in module.exports.tests ){
module.exports.tests[testCase](test, common);
}
};

121
test/unit/sanitizer/autocomplete.js

@ -1,21 +1,126 @@
var autocomplete = require('../../../sanitizer/autocomplete'); const proxyquire = require('proxyquire').noCallThru();
const _ = require('lodash');
module.exports.tests = {}; module.exports.tests = {};
module.exports.tests.sanitizers = function(test, common) { module.exports.tests.sanitizers = function(test, common) {
test('check sanitizer list', function (t) { test('verify that all sanitizers were called as expected', function(t) {
var expected = [ var called_sanitizers = [];
'singleScalarParameters', 'text', 'tokenizer', 'size', 'layers', 'sources',
'sources_and_layers', 'private', 'geo_autocomplete', 'boundary_country', 'categories' var autocomplete = proxyquire('../../../sanitizer/autocomplete', {
'../sanitizer/_single_scalar_parameters': () => {
called_sanitizers.push('_single_scalar_parameters');
return { errors: [], warnings: [] };
},
'../sanitizer/_text_addressit': () => {
called_sanitizers.push('_text_addressit');
return { errors: [], warnings: [] };
},
'../sanitizer/_tokenizer': () => {
called_sanitizers.push('_tokenizer');
return { errors: [], warnings: [] };
},
'../sanitizer/_size': function() {
if (_.isEqual(_.values(arguments), [10, 10, 10])) {
return () => {
called_sanitizers.push('_size');
return { errors: [], warnings: [] };
};
} else {
throw new Error('incorrect parameters passed to _size');
}
},
'../sanitizer/_targets': (type) => {
if (['layers', 'sources'].indexOf(type) !== -1) {
return () => {
called_sanitizers.push(`_targets/${type}`);
return { errors: [], warnings: [] };
};
}
else {
throw new Error('incorrect parameters passed to _targets');
}
},
'../sanitizer/_sources_and_layers': () => {
called_sanitizers.push('_sources_and_layers');
return { errors: [], warnings: [] };
},
'../sanitizer/_flag_bool': function() {
if (arguments[0] === 'private' && arguments[1] === false) {
return () => {
called_sanitizers.push('_flag_bool');
return { errors: [], warnings: [] };
};
}
else {
throw new Error('incorrect parameters passed to _flag_bool');
}
},
'../sanitizer/_location_bias': (defaultParameters) => {
if (defaultParameters.key === 'value'){
return () => {
called_sanitizers.push('_location_bias');
return { errors: [], warnings: [] };
};
} else {
throw new Error('incorrect parameter passed to _location_bias');
}
},
'../sanitizer/_geo_autocomplete': () => {
called_sanitizers.push('_geo_autocomplete');
return { errors: [], warnings: [] };
},
'../sanitizer/_boundary_country': () => {
called_sanitizers.push('_boundary_country');
return { errors: [], warnings: [] };
},
'../sanitizer/_categories': () => {
called_sanitizers.push('_categories');
return { errors: [], warnings: [] };
},
});
const expected_sanitizers = [
'_single_scalar_parameters',
'_text_addressit',
'_tokenizer',
'_size',
'_targets/layers',
'_targets/sources',
'_sources_and_layers',
'_flag_bool',
'_location_bias',
'_geo_autocomplete',
'_boundary_country',
'_categories'
]; ];
t.deepEqual(Object.keys(autocomplete.sanitizer_list), expected);
t.end(); const req = {};
const res = {};
const middleware = autocomplete.middleware({
defaultParameters: {
key: 'value'
}
});
middleware(req, res, () => {
t.deepEquals(called_sanitizers, expected_sanitizers);
t.end();
});
}); });
}; };
module.exports.all = function (tape, common) { module.exports.all = function (tape, common) {
function test(name, testFunction) { function test(name, testFunction) {
return tape('SANTIZE /autocomplete ' + name, testFunction); return tape('SANITIZE /autocomplete ' + name, testFunction);
} }
for( var testCase in module.exports.tests ){ for( var testCase in module.exports.tests ){

1
test/unit/sanitizer/nearby.js

@ -8,7 +8,6 @@ var defaultClean = { 'point.lat': 0,
'point.lon': 0, 'point.lon': 0,
'boundary.circle.lat': 0, 'boundary.circle.lat': 0,
'boundary.circle.lon': 0, 'boundary.circle.lon': 0,
'boundary.circle.radius': parseFloat(defaults['boundary:circle:radius']),
size: 10, size: 10,
private: false private: false
}; };

1
test/unit/sanitizer/reverse.js

@ -10,7 +10,6 @@ var reverse = require('../../../sanitizer/reverse'),
'point.lon': 0, 'point.lon': 0,
'boundary.circle.lat': 0, 'boundary.circle.lat': 0,
'boundary.circle.lon': 0, 'boundary.circle.lon': 0,
'boundary.circle.radius': parseFloat(defaults['boundary:circle:radius']),
size: 10, size: 10,
private: false private: false
}; };

23
test/unit/sanitizer/search.js

@ -87,7 +87,18 @@ module.exports.tests.sanitize = (test, common) => {
'../sanitizer/_geonames_warnings': () => { '../sanitizer/_geonames_warnings': () => {
called_sanitizers.push('_geonames_warnings'); called_sanitizers.push('_geonames_warnings');
return { errors: [], warnings: [] }; return { errors: [], warnings: [] };
},
'../sanitizer/_location_bias': (defaultParameters) => {
if (defaultParameters.key === 'value'){
return () => {
called_sanitizers.push('_location_bias');
return { errors: [], warnings: [] };
};
} else {
throw new Error('incorrect parameter passed to _location_bias');
}
} }
}); });
const expected_sanitizers = [ const expected_sanitizers = [
@ -101,6 +112,7 @@ module.exports.tests.sanitize = (test, common) => {
'_targets/sources', '_targets/sources',
'_sources_and_layers', '_sources_and_layers',
'_flag_bool', '_flag_bool',
'_location_bias',
'_geo_search', '_geo_search',
'_boundary_country', '_boundary_country',
'_categories', '_categories',
@ -110,17 +122,24 @@ module.exports.tests.sanitize = (test, common) => {
const req = {}; const req = {};
const res = {}; const res = {};
search.middleware(req, res, () => { const middleware = search.middleware({
defaultParameters: {
key: 'value'
}
});
middleware(req, res, () => {
t.deepEquals(called_sanitizers, expected_sanitizers); t.deepEquals(called_sanitizers, expected_sanitizers);
t.end(); t.end();
}); });
}); });
}; };
module.exports.all = (tape, common) => { module.exports.all = (tape, common) => {
function test(name, testFunction) { function test(name, testFunction) {
return tape(`SANTIZE /search ${name}`, testFunction); return tape(`SANITIZE /search ${name}`, testFunction);
} }
for( const testCase in module.exports.tests ){ for( const testCase in module.exports.tests ){

22
test/unit/sanitizer/structured_geocoding.js

@ -83,6 +83,16 @@ module.exports.tests.sanitize = function(test, common) {
called_sanitizers.push('_categories'); called_sanitizers.push('_categories');
return { errors: [], warnings: [] }; return { errors: [], warnings: [] };
}, },
'../sanitizer/_location_bias': function (defaultParameters) {
if (defaultParameters.key === 'value'){
return () => {
called_sanitizers.push('_location_bias');
return { errors: [], warnings: [] };
};
} else {
throw new Error('incorrect parameter passed to _location_bias');
}
}
}); });
var expected_sanitizers = [ var expected_sanitizers = [
@ -96,6 +106,7 @@ module.exports.tests.sanitize = function(test, common) {
'_targets/sources', '_targets/sources',
'_sources_and_layers', '_sources_and_layers',
'_flag_bool', '_flag_bool',
'_location_bias',
'_geo_search', '_geo_search',
'_boundary_country', '_boundary_country',
'_categories' '_categories'
@ -104,17 +115,24 @@ module.exports.tests.sanitize = function(test, common) {
var req = {}; var req = {};
var res = {}; var res = {};
search.middleware(req, res, function(){ const middleware = search.middleware({
defaultParameters: {
key: 'value'
}
});
middleware(req, res, function(){
t.deepEquals(called_sanitizers, expected_sanitizers); t.deepEquals(called_sanitizers, expected_sanitizers);
t.end(); t.end();
}); });
}); });
}; };
module.exports.all = function (tape, common) { module.exports.all = function (tape, common) {
function test(name, testFunction) { function test(name, testFunction) {
return tape('SANTIZE /structured ' + name, testFunction); return tape('SANITIZE /structured ' + name, testFunction);
} }
for( var testCase in module.exports.tests ){ for( var testCase in module.exports.tests ){

102
test/unit/schema.js

@ -12,7 +12,6 @@ module.exports.tests.completely_valid = (test, common) => {
version: 'version value', version: 'version value',
indexName: 'index name value', indexName: 'index name value',
host: 'host value', host: 'host value',
legacyUrl: 'legacyUrl value',
accessLog: 'accessLog value', accessLog: 'accessLog value',
relativeScores: true, relativeScores: true,
localization: { localization: {
@ -26,6 +25,10 @@ module.exports.tests.completely_valid = (test, common) => {
placeholder: { placeholder: {
url: 'http://locahost' url: 'http://locahost'
} }
},
defaultParameters: {
'focus.point.lat': 19,
'focus.point.lon': 91
} }
}, },
esclient: { esclient: {
@ -160,29 +163,6 @@ module.exports.tests.api_validation = (test, common) => {
}); });
test('non-string api.legacyUrl should throw error', (t) => {
[null, 17, {}, [], true].forEach((value) => {
var config = {
api: {
version: 'version value',
indexName: 'index name value',
host: 'host value',
legacyUrl: value
},
esclient: {}
};
const result = Joi.validate(config, schema);
t.equals(result.error.details.length, 1);
t.equals(result.error.details[0].message, '"legacyUrl" must be a string');
});
t.end();
});
test('non-string api.accessLog should throw error', (t) => { test('non-string api.accessLog should throw error', (t) => {
[null, 17, {}, [], true].forEach((value) => { [null, 17, {}, [], true].forEach((value) => {
var config = { var config = {
@ -457,6 +437,80 @@ module.exports.tests.api_validation = (test, common) => {
}); });
test('non-number defaultParameters.focus.point.lat should throw error', (t) => {
[null, 'string', {}, [], false].forEach((value) => {
const config = {
api: {
version: 'version value',
indexName: 'index name value',
host: 'host value',
defaultParameters: {
'focus.point.lat': value
}
},
esclient: {}
};
const result = Joi.validate(config, schema);
t.equals(result.error.details.length, 1);
t.equals(result.error.details[0].message, '"focus.point.lat" must be a number');
});
t.end();
});
test('non-number defaultParameters.focus.point.lon should throw error', (t) => {
[null, 'string', {}, [], false].forEach((value) => {
const config = {
api: {
version: 'version value',
indexName: 'index name value',
host: 'host value',
defaultParameters: {
'focus.point.lon': value
}
},
esclient: {}
};
const result = Joi.validate(config, schema);
t.equals(result.error.details.length, 1);
t.equals(result.error.details[0].message, '"focus.point.lon" must be a number');
});
t.end();
});
test('non-object api.defaultParameters should throw error', (t) => {
[null, 17, false, [], 'string'].forEach((value) => {
var config = {
api: {
version: 'version value',
indexName: 'index name value',
host: 'host value',
defaultParameters: value
},
esclient: {}
};
const result = Joi.validate(config, schema);
t.equals(result.error.details.length, 1);
t.equals(result.error.details[0].message, '"defaultParameters" must be an object');
});
t.end();
});
}; };
module.exports.tests.api_services_validation = (test, common) => { module.exports.tests.api_services_validation = (test, common) => {

Loading…
Cancel
Save