From 82ab899eccbcff1d6af7823eeee3076a29579b26 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 18 Sep 2015 15:26:19 +0200 Subject: [PATCH] progress commit --- middleware/_types.js | 39 +- query/reverse.js | 38 +- query/search.js | 32 +- sanitiser/_boundary_country.js | 26 +- sanitiser/_geo_autocomplete.js | 4 +- sanitiser/_geo_common.js | 176 ++++++--- sanitiser/_geo_reverse.js | 19 +- sanitiser/_geo_search.js | 8 +- test/ciao/autocomplete/null_island.coffee | 5 +- test/ciao/reverse/basic_reverse.coffee | 4 +- .../boundary_circle_invalid_radius.coffee | 38 ++ .../boundary_circle_valid_radius.coffee | 37 ++ .../boundary_country_invalid_alpha2.coffee | 34 ++ .../boundary_country_invalid_alpha3.coffee | 34 ++ .../boundary_country_invalid_iso3166.coffee | 34 ++ .../boundary_country_valid_alpha2.coffee | 33 ++ .../boundary_country_valid_alpha3.coffee | 33 ++ test/ciao/reverse/point_invalid_lat.coffee | 35 ++ test/ciao/reverse/point_invalid_lon.coffee | 35 ++ test/ciao/reverse/point_missing_lat.coffee | 35 ++ test/ciao/reverse/point_missing_lon.coffee | 35 ++ ...island.coffee => point_null_island.coffee} | 8 +- test/ciao/reverse/point_valid_duo.coffee | 34 ++ test/ciao/reverse/size_over_max.coffee | 33 ++ test/ciao/reverse/size_under_min.coffee | 33 ++ test/ciao/reverse/size_valid.coffee | 32 ++ ...undary_circle_invalid_lat_lon_types.coffee | 37 ++ .../boundary_circle_invalid_radius.coffee | 37 ++ .../search/boundary_circle_missing_lat.coffee | 37 ++ .../search/boundary_circle_missing_lon.coffee | 37 ++ .../search/boundary_circle_valid_duo.coffee | 36 ++ .../search/boundary_circle_valid_trio.coffee | 36 ++ .../boundary_country_invalid_alpha2.coffee | 35 ++ .../boundary_country_invalid_alpha3.coffee | 35 ++ .../boundary_country_invalid_iso3166.coffee | 35 ++ .../boundary_country_valid_alpha2.coffee | 34 ++ .../boundary_country_valid_alpha3.coffee | 34 ++ .../boundary_rect_partially_specified.coffee | 38 ++ test/ciao/search/boundary_rect_valid.coffee | 37 ++ .../search/focus_point_invalid_lat.coffee | 36 ++ .../search/focus_point_invalid_lon.coffee | 36 ++ .../search/focus_point_missing_lat.coffee | 36 ++ .../search/focus_point_missing_lon.coffee | 36 ++ ....coffee => focus_point_null_island.coffee} | 6 +- test/ciao/search/focus_point_valid_duo.coffee | 35 ++ test/ciao/search/layers_alias_address.coffee | 35 ++ test/ciao/search/layers_alias_coarse.coffee | 35 ++ test/ciao/search/layers_invalid.coffee | 36 ++ .../search/layers_mix_invalid_valid.coffee | 36 ++ test/ciao/search/layers_multiple.coffee | 35 ++ test/ciao/search/layers_single.coffee | 35 ++ test/ciao/search/privacy_false.coffee | 34 ++ test/ciao/search/privacy_true.coffee | 34 ++ test/ciao/search/size_over_max.coffee | 34 ++ test/ciao/search/size_under_min.coffee | 34 ++ test/ciao/search/size_valid.coffee | 33 ++ test/ciao/search/sources_invalid.coffee | 36 ++ .../sources_layers_invalid_combo.coffee | 37 ++ .../search/sources_layers_valid_combo.coffee | 35 ++ test/ciao/search/sources_multiple.coffee | 35 ++ test/ciao/search/sources_single.coffee | 35 ++ test/unit/query/reverse.js | 45 ++- test/unit/query/search.js | 20 +- test/unit/sanitiser/_boundary_country.js | 14 +- test/unit/sanitiser/_geo_common.js | 354 +++++++++++++++++- test/unit/sanitiser/reverse.js | 11 +- test/unit/sanitiser/search.js | 68 ++-- 67 files changed, 2388 insertions(+), 210 deletions(-) create mode 100644 test/ciao/reverse/boundary_circle_invalid_radius.coffee create mode 100644 test/ciao/reverse/boundary_circle_valid_radius.coffee create mode 100644 test/ciao/reverse/boundary_country_invalid_alpha2.coffee create mode 100644 test/ciao/reverse/boundary_country_invalid_alpha3.coffee create mode 100644 test/ciao/reverse/boundary_country_invalid_iso3166.coffee create mode 100644 test/ciao/reverse/boundary_country_valid_alpha2.coffee create mode 100644 test/ciao/reverse/boundary_country_valid_alpha3.coffee create mode 100644 test/ciao/reverse/point_invalid_lat.coffee create mode 100644 test/ciao/reverse/point_invalid_lon.coffee create mode 100644 test/ciao/reverse/point_missing_lat.coffee create mode 100644 test/ciao/reverse/point_missing_lon.coffee rename test/ciao/reverse/{null_island.coffee => point_null_island.coffee} (83%) create mode 100644 test/ciao/reverse/point_valid_duo.coffee create mode 100644 test/ciao/reverse/size_over_max.coffee create mode 100644 test/ciao/reverse/size_under_min.coffee create mode 100644 test/ciao/reverse/size_valid.coffee create mode 100644 test/ciao/search/boundary_circle_invalid_lat_lon_types.coffee create mode 100644 test/ciao/search/boundary_circle_invalid_radius.coffee create mode 100644 test/ciao/search/boundary_circle_missing_lat.coffee create mode 100644 test/ciao/search/boundary_circle_missing_lon.coffee create mode 100644 test/ciao/search/boundary_circle_valid_duo.coffee create mode 100644 test/ciao/search/boundary_circle_valid_trio.coffee create mode 100644 test/ciao/search/boundary_country_invalid_alpha2.coffee create mode 100644 test/ciao/search/boundary_country_invalid_alpha3.coffee create mode 100644 test/ciao/search/boundary_country_invalid_iso3166.coffee create mode 100644 test/ciao/search/boundary_country_valid_alpha2.coffee create mode 100644 test/ciao/search/boundary_country_valid_alpha3.coffee create mode 100644 test/ciao/search/boundary_rect_partially_specified.coffee create mode 100644 test/ciao/search/boundary_rect_valid.coffee create mode 100644 test/ciao/search/focus_point_invalid_lat.coffee create mode 100644 test/ciao/search/focus_point_invalid_lon.coffee create mode 100644 test/ciao/search/focus_point_missing_lat.coffee create mode 100644 test/ciao/search/focus_point_missing_lon.coffee rename test/ciao/search/{null_island.coffee => focus_point_null_island.coffee} (87%) create mode 100644 test/ciao/search/focus_point_valid_duo.coffee create mode 100644 test/ciao/search/layers_alias_address.coffee create mode 100644 test/ciao/search/layers_alias_coarse.coffee create mode 100644 test/ciao/search/layers_invalid.coffee create mode 100644 test/ciao/search/layers_mix_invalid_valid.coffee create mode 100644 test/ciao/search/layers_multiple.coffee create mode 100644 test/ciao/search/layers_single.coffee create mode 100644 test/ciao/search/privacy_false.coffee create mode 100644 test/ciao/search/privacy_true.coffee create mode 100644 test/ciao/search/size_over_max.coffee create mode 100644 test/ciao/search/size_under_min.coffee create mode 100644 test/ciao/search/size_valid.coffee create mode 100644 test/ciao/search/sources_invalid.coffee create mode 100644 test/ciao/search/sources_layers_invalid_combo.coffee create mode 100644 test/ciao/search/sources_layers_valid_combo.coffee create mode 100644 test/ciao/search/sources_multiple.coffee create mode 100644 test/ciao/search/sources_single.coffee diff --git a/middleware/_types.js b/middleware/_types.js index baad127e..3e604f7b 100644 --- a/middleware/_types.js +++ b/middleware/_types.js @@ -10,25 +10,34 @@ var types_helper = require( '../helper/types' ); function middleware(req, res, next) { req.clean = req.clean || {}; - if (req.clean.hasOwnProperty('types') === false) { - return next(); - } + if (req.clean.hasOwnProperty('types')) { + + try { + var types = types_helper(req.clean.types); + + if ((types instanceof Array) && types.length === 0) { + var err = 'You have specified both the `sources` and `layers` ' + + 'parameters in a combination that will return no results.'; + req.errors.push( err ); + } - try { - var types = types_helper(req.clean.types); + else { + req.clean.type = types; + } - if ((types instanceof Array) && types.length === 0) { - var err = 'You have specified both the `sources` and `layers` ' + - 'parameters in a combination that will return no results.'; - res.status(400); // 400 Bad Request - return next(err); } - req.clean.type = types; - } - catch (err) { - // this means there were no types specified - delete req.clean.types; + // @todo: refactor this flow, it is confusing as `types_helper()` can throw + // with an error "clean_types should not be null or undefined" which is + // not returned to the user yet the return value CAN trigger a user error. + // I would have liked to throw for BOTH cases and then handle the users errors + // inside the 'catch' but this is not possible. + // also: why are we deleting things from $clean? + catch (err) { + // this means there were no types specified + delete req.clean.types; + } + } next(); diff --git a/query/reverse.js b/query/reverse.js index 2ee283e3..9401f916 100644 --- a/query/reverse.js +++ b/query/reverse.js @@ -24,7 +24,8 @@ function generateQuery( clean ){ // set defaults vs.set({ - 'size': 1 + 'size': 1, + 'boundary:circle:radius': '500km' }); // set size @@ -32,30 +33,33 @@ function generateQuery( clean ){ vs.var( 'size', clean.size ); } - // set radius, default to 500km if not specified in request - var radius = 500; - if (clean.hasOwnProperty('boundary.circle.radius')) { - radius = clean['boundary.circle.radius']; - } - - // focus point centroid - if( check.number(clean['point.lat']) && check.number(clean['point.lon']) ){ + // focus point to score by distance + if( check.number(clean['point.lat']) && + check.number(clean['point.lon']) ){ vs.set({ - // focus point to score by distance 'focus:point:lat': clean['point.lat'], - 'focus:point:lon': clean['point.lon'], + 'focus:point:lon': clean['point.lon'] + }); + } - // bounding circle - 'boundary:circle:lat': clean['point.lat'], - 'boundary:circle:lon': clean['point.lon'], - 'boundary:circle:radius': radius + 'km' + // bounding circle + // note: the sanitizers will take care of the case + // where point.lan/point.lon are provided in the + // absense of boundary.circle.lat/boundary.circle.lon + if( check.number(clean['boundary.circle.lat']) && + check.number(clean['boundary.circle.lon']) && + check.number(clean['boundary.circle.radius']) ){ + vs.set({ + 'boundary:circle:lat': clean['boundary.circle.lat'], + 'boundary:circle:lon': clean['boundary.circle.lon'], + 'boundary:circle:radius': clean['boundary.circle.radius'] + 'km' }); } // boundary country - if( clean.boundary && clean.boundary.country ){ + if( check.string(clean['boundary.country']) ){ vs.set({ - 'boundary:country': clean.boundary.country + 'boundary:country': clean['boundary.country'] }); } diff --git a/query/search.js b/query/search.js index 9dcf0273..a74cf8ce 100644 --- a/query/search.js +++ b/query/search.js @@ -59,7 +59,8 @@ function generateQuery( clean ){ } // focus point - if( check.number(clean['focus.point.lat']) && check.number(clean['focus.point.lon']) ){ + if( check.number(clean['focus.point.lat']) && + check.number(clean['focus.point.lon']) ){ vs.set({ 'focus:point:lat': clean['focus.point.lat'], 'focus:point:lon': clean['focus.point.lon'] @@ -78,27 +79,36 @@ function generateQuery( clean ){ } // boundary rect - if( clean.bbox ){ + if( check.number(clean['boundary.rect.min_lat']) && + check.number(clean['boundary.rect.max_lat']) && + check.number(clean['boundary.rect.min_lon']) && + check.number(clean['boundary.rect.max_lon']) ){ vs.set({ - 'boundary:rect:top': clean.bbox.top, - 'boundary:rect:right': clean.bbox.right, - 'boundary:rect:bottom': clean.bbox.bottom, - 'boundary:rect:left': clean.bbox.left + 'boundary:rect:top': clean['boundary.rect.min_lat'], + 'boundary:rect:right': clean['boundary.rect.max_lon'], + 'boundary:rect:bottom': clean['boundary.rect.max_lat'], + 'boundary:rect:left': clean['boundary.rect.min_lon'] }); } // boundary circle // @todo: change these to the correct request variable names - if( clean.boundary && clean.boundary.circle ){ + if( check.number(clean['boundary.circle.lat']) && + check.number(clean['boundary.circle.lon']) ){ vs.set({ - 'boundary:circle:lat': clean.boundary.circle.lat, - 'boundary:circle:lon': clean.boundary.circle.lon, - 'boundary:circle:radius': clean.boundary.circle.radius + 'm' + 'boundary:circle:lat': clean['boundary.circle.lat'], + 'boundary:circle:lon': clean['boundary.circle.lon'] }); + + if( check.number(clean['boundary.circle.radius']) ){ + vs.set({ + 'boundary:circle:radius': Math.round( clean['boundary.circle.radius'] ) + 'km' + }); + } } // boundary country - if( clean['boundary.country'] ){ + if( check.string(clean['boundary.country']) ){ vs.set({ 'boundary:country': clean['boundary.country'] }); diff --git a/sanitiser/_boundary_country.js b/sanitiser/_boundary_country.js index 6376e434..ef965c2c 100644 --- a/sanitiser/_boundary_country.js +++ b/sanitiser/_boundary_country.js @@ -5,37 +5,37 @@ function sanitize(raw, clean) { // error & warning messages var messages = { errors: [], warnings: [] }; - // init clean.boundary (if not already init) - clean.boundary = clean.boundary || {}; + // target input param + var country = raw['boundary.country']; - if (check.assigned(raw['boundary.country'])) { - var country = raw['boundary.country']; + // param 'boundary.country' is optional and should not + // error when simply not set by the user + if (check.assigned(country)){ - if (!check.string(country)) { + // must be valid string + if (!check.unemptyString(country)) { messages.errors.push('boundary.country is not a string'); - delete clean.boundary.country; } + + // must be a valid ISO 3166 code else if (!containsIsoCode(country.toUpperCase())) { messages.errors.push(country + ' is not a valid ISO2/ISO3 country code'); - delete clean.boundary.country; } + + // valid ISO 3166 country code, set alpha3 code on 'clean.boundary.country' else { // the only way for boundary.country to be assigned is if input is // a string and a known ISO2 or ISO3 - clean.boundary.country = iso3166.to3(country.toUpperCase()); + clean['boundary.country'] = iso3166.to3(country.toUpperCase()); } - - } else { - delete clean.boundary.country; } return messages; - } function containsIsoCode(isoCode) { return iso3166.list().some(function(row) { - return row.alpha2 === isoCode || row.alpha3 === isoCode; + return row.alpha2 === isoCode || row.alpha3 === isoCode; }); } diff --git a/sanitiser/_geo_autocomplete.js b/sanitiser/_geo_autocomplete.js index 4a2d1144..b053e4b7 100644 --- a/sanitiser/_geo_autocomplete.js +++ b/sanitiser/_geo_autocomplete.js @@ -8,8 +8,8 @@ module.exports = function sanitize( raw, clean ){ var messages = { errors: [], warnings: [] }; try { - 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_coord( 'focus.point.lat', clean, raw['focus.point.lat'], LAT_LON_IS_REQUIRED ); + geo_common.sanitize_coord( 'focus.point.lon', clean, raw['focus.point.lon'], LAT_LON_IS_REQUIRED ); } catch (err) { messages.errors.push( err.message ); diff --git a/sanitiser/_geo_common.js b/sanitiser/_geo_common.js index 2ba50240..b88e9453 100644 --- a/sanitiser/_geo_common.js +++ b/sanitiser/_geo_common.js @@ -5,89 +5,157 @@ var util = require('util'), check = require('check-types'); /** - * Parse and validate bbox parameter - * bbox = bottom_left lon, bottom_left lat, top_right lon, top_right lat - * bbox = left, bottom, right, top - * bbox = min Longitude, min Latitude, max Longitude, max Latitude + * Parse and validate rect parameter * - * @param {object} raw + * @param {string} key_prefix * @param {object} clean + * @param {object} raw + * @param {bool} bbox_is_required */ -function sanitize_bbox( raw, clean ) { - if( !check.unemptyString( raw.bbox ) ) { - return; - } +function sanitize_rect( key_prefix, clean, raw, bbox_is_required ) { - var bboxArr = raw.bbox.split( ',' ); + // the names we use to define the corners of the rect + var mandatoryProps = [ 'min_lat', 'max_lat', 'min_lon', 'max_lon' ]; - if( Array.isArray( bboxArr ) && bboxArr.length === 4 ) { - var bbox = bboxArr.map(parseFloat); - - if (bbox.some(isNaN)) { - return; + // count up how many fields the user actually specified + var totalFieldsSpecified = 0; + mandatoryProps.forEach( function( prop ){ + if( raw.hasOwnProperty( key_prefix + '.' + prop ) ){ + totalFieldsSpecified++; } + }); - clean.bbox = { - right: Math.max( bbox[0], bbox[2] ), - top: Math.max( bbox[1], bbox[3] ), - left: Math.min( bbox[0], bbox[2] ), - bottom: Math.min( bbox[1], bbox[3] ) - }; + // all fields specified + if( 4 === totalFieldsSpecified ) { + // reuse the coord sanitizer and set required:true so we get a fatal error if + // any one of the corners is not specified. + sanitize_coord( key_prefix + '.min_lat', clean, raw[ key_prefix + '.min_lat' ], true ); + sanitize_coord( key_prefix + '.max_lat', clean, raw[ key_prefix + '.max_lat' ], true ); + sanitize_coord( key_prefix + '.min_lon', clean, raw[ key_prefix + '.min_lon' ], true ); + sanitize_coord( key_prefix + '.max_lon', clean, raw[ key_prefix + '.max_lon' ], true ); + } + // fields only partially specified + else if( totalFieldsSpecified > 0 ){ + var format1 = 'missing rect param \'%s\' requires all of: \'%s\' to be present'; + throw new Error( util.format( format1, key_prefix, mandatoryProps.join('\',\'') ) ); + } + // fields required, eg. ( totalFieldsSpecified === 0 && bbox_is_required === true ) + else if( bbox_is_required ){ + var format2 = 'missing rect param \'%s\' requires all of: \'%s\' to be present'; + throw new Error( util.format( format2, key_prefix, mandatoryProps.join('\',\'') ) ); } } /** - * Validate lat,lon values + * Parse and validate circle parameter * - * @param {string} coord lat|lon + * @param {string} key_prefix * @param {object} clean - * @param {string} param - * @param {bool} latlon_is_required + * @param {object} raw + * @param {bool} circle_is_required */ -function sanitize_coord( coord, clean, param, latlon_is_required ) { - var value = parseFloat( param ); - if ( !isNaN( value ) ) { - clean[coord] = value; +function sanitize_circle( key_prefix, clean, raw, circle_is_required ) { + + // the names we use to define the centroid + var mandatoryProps = [ 'lat', 'lon' ]; + + // count up how many fields the user actually specified + var totalFieldsSpecified = 0; + mandatoryProps.forEach( function( prop ){ + if( raw.hasOwnProperty( key_prefix + '.' + prop ) ){ + totalFieldsSpecified++; + } + }); + + // all fields specified + if( 2 === totalFieldsSpecified ) { + // reuse the coord sanitizer and set required:true so we get a fatal error if + // any one of the coords is not specified. + sanitize_coord( key_prefix + '.lat', clean, raw[ key_prefix + '.lat' ], true ); + sanitize_coord( key_prefix + '.lon', clean, raw[ key_prefix + '.lon' ], true ); + + if( check.assigned( raw[ key_prefix + '.radius' ] ) ){ + sanitize_coord( key_prefix + '.radius', clean, raw[ key_prefix + '.radius' ], true ); + } } - else if (latlon_is_required) { - throw new Error( util.format( 'missing param \'%s\'', coord ) ); + // fields only partially specified + else if( totalFieldsSpecified > 0 ){ + var format1 = 'missing circle param \'%s\' requires all of: \'%s\' to be present'; + throw new Error( util.format( format1, key_prefix, mandatoryProps.join('\',\'') ) ); + } + // radius was specified without lat or lon + else if( raw.hasOwnProperty( key_prefix + '.radius' ) ){ + var format2 = 'missing circle param \'%s\' requires all of: \'%s\' to be present'; + throw new Error( util.format( format2, key_prefix, mandatoryProps.join('\',\'') ) ); + } + // fields required, eg. ( totalFieldsSpecified === 0 && bbox_is_required === true ) + else if( circle_is_required ){ + var format3 = 'missing circle param \'%s\' requires all of: \'%s\' to be present'; + throw new Error( util.format( format3, key_prefix, mandatoryProps.join('\',\'') ) ); } } /** - * Validate circle geometry values + * Parse and validate point parameter * + * @param {string} key_prefix * @param {object} clean - * @param {object} params - * @param {bool} is_required - * @param {bool} all_required + * @param {object} raw + * @param {bool} point_is_required */ -function sanitize_boundary_circle( clean, params, is_required, all_required ) { - var props = { - lat: 'boundary.circle.lat', - lon: 'boundary.circle.lon', - rad: 'boundary.circle.radius' - }; +function sanitize_point( key_prefix, clean, raw, point_is_required ) { - // get values for each property - sanitize_coord(props.lat, clean, params['boundary.circle.lat'], all_required && is_required); - sanitize_coord(props.lon, clean, params['boundary.circle.lon'], all_required && is_required); - sanitize_coord(props.rad, clean, params['boundary.circle.radius'], all_required && is_required); + // the names we use to define the point + var mandatoryProps = [ 'lat', 'lon' ]; + + // count up how many fields the user actually specified + var totalFieldsSpecified = 0; + mandatoryProps.forEach( function( prop ){ + if( raw.hasOwnProperty( key_prefix + '.' + prop ) ){ + totalFieldsSpecified++; + } + }); - // if all are required, check if some are set but not all, throw an error if missing - if (all_required && - (clean.hasOwnProperty(props.lat) || clean.hasOwnProperty(props.lon) || clean.hasOwnProperty(props.rad)) && - !(clean.hasOwnProperty(props.lat) && clean.hasOwnProperty(props.lon) && clean.hasOwnProperty(props.rad))) { - throw new Error('missing part of circle: needs lat,lon,radius'); + // all fields specified + if( 2 === totalFieldsSpecified ) { + // reuse the coord sanitizer and set required:true so we get a fatal error if + // any one of the coords is not specified. + sanitize_coord( key_prefix + '.lat', clean, raw[ key_prefix + '.lat' ], true ); + sanitize_coord( key_prefix + '.lon', clean, raw[ key_prefix + '.lon' ], true ); } + // fields only partially specified + else if( totalFieldsSpecified > 0 ){ + var format1 = 'missing point param \'%s\' requires all of: \'%s\' to be present'; + throw new Error( util.format( format1, key_prefix, mandatoryProps.join('\',\'') ) ); + } + // fields required, eg. ( totalFieldsSpecified === 0 && bbox_is_required === true ) + else if( point_is_required ){ + var format2 = 'missing point param \'%s\' requires all of: \'%s\' to be present'; + throw new Error( util.format( format2, key_prefix, mandatoryProps.join('\',\'') ) ); + } +} - if (is_required && !(clean.hasOwnProperty(props.lat) || clean.hasOwnProperty(props.lon) || clean.hasOwnProperty(props.rad))) { - throw new Error('missing param boundary.circle: should be a trio of lat,lon,radius'); +/** + * Validate lat,lon values + * + * @param {string} key + * @param {object} clean + * @param {string} param + * @param {bool} latlon_is_required + */ +function sanitize_coord( key, clean, param, latlon_is_required ) { + var value = parseFloat( param ); + if ( !isNaN( value ) ) { + clean[key] = value; + } + else if (latlon_is_required) { + throw new Error( util.format( 'missing param \'%s\'', key ) ); } } module.exports = { - sanitize_bbox: sanitize_bbox, + sanitize_rect: sanitize_rect, sanitize_coord: sanitize_coord, - sanitize_boundary_circle: sanitize_boundary_circle + sanitize_circle: sanitize_circle, + sanitize_point: sanitize_point }; diff --git a/sanitiser/_geo_reverse.js b/sanitiser/_geo_reverse.js index d97ca1c3..4b5ee959 100644 --- a/sanitiser/_geo_reverse.js +++ b/sanitiser/_geo_reverse.js @@ -11,19 +11,18 @@ module.exports = function sanitize( raw, clean ){ var messages = { errors: [], warnings: [] }; try { - geo_common.sanitize_coord( 'point.lat', clean, raw['point.lat'], LAT_LON_IS_REQUIRED ); - geo_common.sanitize_coord( 'point.lon', clean, raw['point.lon'], LAT_LON_IS_REQUIRED ); + geo_common.sanitize_point( 'point', clean, raw, LAT_LON_IS_REQUIRED ); - // remove both if only one is set - // @todo: clean this up! - if( !clean.hasOwnProperty('point.lat') || !clean.hasOwnProperty('point.lon') ){ - delete clean['point.lat']; - delete clean['point.lon']; + // this hack is to allow point.lat/point.lon to be used interchanagbly + // with boundary.circle.lat/boundary.circle/lon + if( !clean.hasOwnProperty('boundary.circle.lat') && clean.hasOwnProperty('point.lat') ){ + raw['boundary.circle.lat'] = clean['point.lat']; + } + if( !clean.hasOwnProperty('boundary.circle.lon') && clean.hasOwnProperty('point.lon') ){ + raw['boundary.circle.lon'] = clean['point.lon']; } - // 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, raw, CIRCLE_IS_REQUIRED, CIRCLE_MUST_BE_COMPLETE); + geo_common.sanitize_circle( 'boundary.circle', clean, raw, CIRCLE_IS_REQUIRED ); } catch (err) { messages.errors.push( err.message ); diff --git a/sanitiser/_geo_search.js b/sanitiser/_geo_search.js index 5280efd0..badeec52 100644 --- a/sanitiser/_geo_search.js +++ b/sanitiser/_geo_search.js @@ -1,5 +1,7 @@ var geo_common = require ('./_geo_common'); var LAT_LON_IS_REQUIRED = false; +var RECT_IS_REQUIRED = false; +var CIRCLE_IS_REQUIRED = false; // validate inputs, convert types and apply defaults module.exports = function sanitize( raw, clean ){ @@ -8,9 +10,9 @@ module.exports = function sanitize( raw, clean ){ var messages = { errors: [], warnings: [] }; try { - geo_common.sanitize_coord( 'focus.point.lat', clean, raw['focus.point.lat'], LAT_LON_IS_REQUIRED ); - geo_common.sanitize_coord( 'focus.point.lon', clean, raw['focus.point.lon'], LAT_LON_IS_REQUIRED ); - geo_common.sanitize_bbox(raw, clean); + geo_common.sanitize_point( 'focus.point', clean, raw, LAT_LON_IS_REQUIRED ); + geo_common.sanitize_rect( 'boundary.rect', clean, raw, RECT_IS_REQUIRED ); + geo_common.sanitize_circle( 'boundary.circle', clean, raw, CIRCLE_IS_REQUIRED ); } catch (err) { messages.errors.push( err.message ); diff --git a/test/ciao/autocomplete/null_island.coffee b/test/ciao/autocomplete/null_island.coffee index ad229069..10331700 100644 --- a/test/ciao/autocomplete/null_island.coffee +++ b/test/ciao/autocomplete/null_island.coffee @@ -29,6 +29,7 @@ should.not.exist json.geocoding.errors should.not.exist json.geocoding.warnings #? inputs -json.geocoding.query['lat'].should.eql 0 -json.geocoding.query['lon'].should.eql 0 +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['focus.point.lat'].should.eql 0 +json.geocoding.query['focus.point.lon'].should.eql 0 json.geocoding.query['size'].should.eql 10 \ No newline at end of file diff --git a/test/ciao/reverse/basic_reverse.coffee b/test/ciao/reverse/basic_reverse.coffee index d4d708ed..3b5cb4cc 100644 --- a/test/ciao/reverse/basic_reverse.coffee +++ b/test/ciao/reverse/basic_reverse.coffee @@ -29,6 +29,6 @@ should.not.exist json.geocoding.errors should.not.exist json.geocoding.warnings #? inputs -json.geocoding.query['lat'].should.eql 1 -json.geocoding.query['lon'].should.eql 2 +json.geocoding.query['point.lat'].should.eql 1 +json.geocoding.query['point.lon'].should.eql 2 json.geocoding.query['size'].should.eql 10 \ No newline at end of file diff --git a/test/ciao/reverse/boundary_circle_invalid_radius.coffee b/test/ciao/reverse/boundary_circle_invalid_radius.coffee new file mode 100644 index 00000000..3259f6b2 --- /dev/null +++ b/test/ciao/reverse/boundary_circle_invalid_radius.coffee @@ -0,0 +1,38 @@ + +#> bounding circle +path: '/v1/reverse?point.lat=40.744243&point.lon=-73.990342&boundary.circle.radius=foo' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing param \'boundary.circle.radius\'' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['point.lat'].should.eql 40.744243 +json.geocoding.query['point.lon'].should.eql -73.990342 +json.geocoding.query['boundary.circle.lat'].should.eql 40.744243 +json.geocoding.query['boundary.circle.lon'].should.eql -73.990342 +should.not.exist json.geocoding.query['boundary.circle.radius'] \ No newline at end of file diff --git a/test/ciao/reverse/boundary_circle_valid_radius.coffee b/test/ciao/reverse/boundary_circle_valid_radius.coffee new file mode 100644 index 00000000..1664be63 --- /dev/null +++ b/test/ciao/reverse/boundary_circle_valid_radius.coffee @@ -0,0 +1,37 @@ + +#> bounding circle +path: '/v1/reverse?point.lat=40.744243&point.lon=-73.990342&boundary.circle.radius=999.9' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['point.lat'].should.eql 40.744243 +json.geocoding.query['point.lon'].should.eql -73.990342 +json.geocoding.query['boundary.circle.lat'].should.eql 40.744243 +json.geocoding.query['boundary.circle.lon'].should.eql -73.990342 +json.geocoding.query['boundary.circle.radius'].should.eql 999.9 \ No newline at end of file diff --git a/test/ciao/reverse/boundary_country_invalid_alpha2.coffee b/test/ciao/reverse/boundary_country_invalid_alpha2.coffee new file mode 100644 index 00000000..5f6e6a13 --- /dev/null +++ b/test/ciao/reverse/boundary_country_invalid_alpha2.coffee @@ -0,0 +1,34 @@ + +#> bounding country +path: '/v1/reverse?point.lat=1&point.lon=1&boundary.country=ZZ' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'ZZ is not a valid ISO2/ISO3 country code' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['boundary.country'] \ No newline at end of file diff --git a/test/ciao/reverse/boundary_country_invalid_alpha3.coffee b/test/ciao/reverse/boundary_country_invalid_alpha3.coffee new file mode 100644 index 00000000..3ef9e841 --- /dev/null +++ b/test/ciao/reverse/boundary_country_invalid_alpha3.coffee @@ -0,0 +1,34 @@ + +#> bounding country +path: '/v1/reverse?point.lat=1&point.lon=1&boundary.country=ZZZ' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'ZZZ is not a valid ISO2/ISO3 country code' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['boundary.country'] \ No newline at end of file diff --git a/test/ciao/reverse/boundary_country_invalid_iso3166.coffee b/test/ciao/reverse/boundary_country_invalid_iso3166.coffee new file mode 100644 index 00000000..05130a9b --- /dev/null +++ b/test/ciao/reverse/boundary_country_invalid_iso3166.coffee @@ -0,0 +1,34 @@ + +#> bounding country +path: '/v1/reverse?point.lat=1&point.lon=1&boundary.country=FOOBAR' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'FOOBAR is not a valid ISO2/ISO3 country code' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['boundary.country'] \ No newline at end of file diff --git a/test/ciao/reverse/boundary_country_valid_alpha2.coffee b/test/ciao/reverse/boundary_country_valid_alpha2.coffee new file mode 100644 index 00000000..47716352 --- /dev/null +++ b/test/ciao/reverse/boundary_country_valid_alpha2.coffee @@ -0,0 +1,33 @@ + +#> bounding country +path: '/v1/reverse?point.lat=1&point.lon=1&boundary.country=US' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['boundary.country'].should.eql 'USA' \ No newline at end of file diff --git a/test/ciao/reverse/boundary_country_valid_alpha3.coffee b/test/ciao/reverse/boundary_country_valid_alpha3.coffee new file mode 100644 index 00000000..e3f02d8f --- /dev/null +++ b/test/ciao/reverse/boundary_country_valid_alpha3.coffee @@ -0,0 +1,33 @@ + +#> bounding country +path: '/v1/reverse?point.lat=1&point.lon=1&boundary.country=USA' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['boundary.country'].should.eql 'USA' \ No newline at end of file diff --git a/test/ciao/reverse/point_invalid_lat.coffee b/test/ciao/reverse/point_invalid_lat.coffee new file mode 100644 index 00000000..3f085880 --- /dev/null +++ b/test/ciao/reverse/point_invalid_lat.coffee @@ -0,0 +1,35 @@ + +#> point +path: '/v1/reverse?point.lat=foo&point.lon=-73.990342' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing param \'point.lat\'' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['point.lat'] +should.not.exist json.geocoding.query['point.lon'] \ No newline at end of file diff --git a/test/ciao/reverse/point_invalid_lon.coffee b/test/ciao/reverse/point_invalid_lon.coffee new file mode 100644 index 00000000..e7e6b436 --- /dev/null +++ b/test/ciao/reverse/point_invalid_lon.coffee @@ -0,0 +1,35 @@ + +#> point +path: '/v1/reverse?point.lat=40.744243&point.lon=' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing param \'point.lon\'' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['point.lat'].should.eql 40.744243 +should.not.exist json.geocoding.query['point.lon'] \ No newline at end of file diff --git a/test/ciao/reverse/point_missing_lat.coffee b/test/ciao/reverse/point_missing_lat.coffee new file mode 100644 index 00000000..649a5db6 --- /dev/null +++ b/test/ciao/reverse/point_missing_lat.coffee @@ -0,0 +1,35 @@ + +#> point +path: '/v1/reverse?point.lon=-73.990342' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing point param \'point\' requires all of: \'lat\',\'lon\' to be present' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['point.lat'] +should.not.exist json.geocoding.query['point.lon'] \ No newline at end of file diff --git a/test/ciao/reverse/point_missing_lon.coffee b/test/ciao/reverse/point_missing_lon.coffee new file mode 100644 index 00000000..e28f2a1b --- /dev/null +++ b/test/ciao/reverse/point_missing_lon.coffee @@ -0,0 +1,35 @@ + +#> point +path: '/v1/reverse?point.lat=40.744243' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing point param \'point\' requires all of: \'lat\',\'lon\' to be present' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['point.lat'] +should.not.exist json.geocoding.query['point.lon'] \ No newline at end of file diff --git a/test/ciao/reverse/null_island.coffee b/test/ciao/reverse/point_null_island.coffee similarity index 83% rename from test/ciao/reverse/null_island.coffee rename to test/ciao/reverse/point_null_island.coffee index 5189a152..6540a571 100644 --- a/test/ciao/reverse/null_island.coffee +++ b/test/ciao/reverse/point_null_island.coffee @@ -1,5 +1,5 @@ -#> null island +#> point null island path: '/v1/reverse?point.lat=0&point.lon=0' #? 200 ok @@ -29,6 +29,6 @@ should.not.exist json.geocoding.errors should.not.exist json.geocoding.warnings #? inputs -json.geocoding.query['lat'].should.eql 0 -json.geocoding.query['lon'].should.eql 0 -json.geocoding.query['size'].should.eql 10 \ No newline at end of file +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['point.lat'].should.eql 0 +json.geocoding.query['point.lon'].should.eql 0 \ No newline at end of file diff --git a/test/ciao/reverse/point_valid_duo.coffee b/test/ciao/reverse/point_valid_duo.coffee new file mode 100644 index 00000000..63e77f88 --- /dev/null +++ b/test/ciao/reverse/point_valid_duo.coffee @@ -0,0 +1,34 @@ + +#> point +path: '/v1/reverse?point.lat=40.744243&point.lon=-73.990342' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['point.lat'].should.eql 40.744243 +json.geocoding.query['point.lon'].should.eql -73.990342 \ No newline at end of file diff --git a/test/ciao/reverse/size_over_max.coffee b/test/ciao/reverse/size_over_max.coffee new file mode 100644 index 00000000..846b9b40 --- /dev/null +++ b/test/ciao/reverse/size_over_max.coffee @@ -0,0 +1,33 @@ + +#> set size +path: '/v1/reverse?point.lat=1&point.lon=1&size=999' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.exist json.geocoding.warnings +json.geocoding.warnings.should.eql [ 'out-of-range integer \'size\', using MAX_SIZE' ] + +#? inputs +json.geocoding.query['size'].should.eql 40 \ No newline at end of file diff --git a/test/ciao/reverse/size_under_min.coffee b/test/ciao/reverse/size_under_min.coffee new file mode 100644 index 00000000..a39b5320 --- /dev/null +++ b/test/ciao/reverse/size_under_min.coffee @@ -0,0 +1,33 @@ + +#> set size +path: '/v1/reverse?point.lat=1&point.lon=1&size=0' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.exist json.geocoding.warnings +json.geocoding.warnings.should.eql [ 'out-of-range integer \'size\', using MIN_SIZE' ] + +#? inputs +json.geocoding.query['size'].should.eql 1 \ No newline at end of file diff --git a/test/ciao/reverse/size_valid.coffee b/test/ciao/reverse/size_valid.coffee new file mode 100644 index 00000000..5fb7c7bf --- /dev/null +++ b/test/ciao/reverse/size_valid.coffee @@ -0,0 +1,32 @@ + +#> set size +path: '/v1/reverse?point.lat=1&point.lon=1&size=3' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['size'].should.eql 3 \ No newline at end of file diff --git a/test/ciao/search/boundary_circle_invalid_lat_lon_types.coffee b/test/ciao/search/boundary_circle_invalid_lat_lon_types.coffee new file mode 100644 index 00000000..0a4ba5ec --- /dev/null +++ b/test/ciao/search/boundary_circle_invalid_lat_lon_types.coffee @@ -0,0 +1,37 @@ + +#> bounding circle +path: '/v1/search?text=a&boundary.circle.lat=foo&boundary.circle.lon=bar' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing param \'boundary.circle.lat\'' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['boundary.circle.lat'] +should.not.exist json.geocoding.query['boundary.circle.lon'] +should.not.exist json.geocoding.query['boundary.circle.radius'] \ No newline at end of file diff --git a/test/ciao/search/boundary_circle_invalid_radius.coffee b/test/ciao/search/boundary_circle_invalid_radius.coffee new file mode 100644 index 00000000..d73b99d2 --- /dev/null +++ b/test/ciao/search/boundary_circle_invalid_radius.coffee @@ -0,0 +1,37 @@ + +#> bounding circle +path: '/v1/search?text=a&boundary.circle.lat=40.744243&boundary.circle.lon=-73.990342&boundary.circle.radius=foo' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing param \'boundary.circle.radius\'' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['boundary.circle.lat'].should.eql 40.744243 +json.geocoding.query['boundary.circle.lon'].should.eql -73.990342 +should.not.exist json.geocoding.query['boundary.circle.radius'] \ No newline at end of file diff --git a/test/ciao/search/boundary_circle_missing_lat.coffee b/test/ciao/search/boundary_circle_missing_lat.coffee new file mode 100644 index 00000000..ccc7dcc0 --- /dev/null +++ b/test/ciao/search/boundary_circle_missing_lat.coffee @@ -0,0 +1,37 @@ + +#> bounding circle +path: '/v1/search?text=a&boundary.circle.lon=-73.990342&boundary.circle.radius=100' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing circle param \'boundary.circle\' requires all of: \'lat\',\'lon\' to be present' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['boundary.circle.lat'] +should.not.exist json.geocoding.query['boundary.circle.lon'] +should.not.exist json.geocoding.query['boundary.circle.radius'] \ No newline at end of file diff --git a/test/ciao/search/boundary_circle_missing_lon.coffee b/test/ciao/search/boundary_circle_missing_lon.coffee new file mode 100644 index 00000000..63a1d794 --- /dev/null +++ b/test/ciao/search/boundary_circle_missing_lon.coffee @@ -0,0 +1,37 @@ + +#> bounding circle +path: '/v1/search?text=a&boundary.circle.lat=40.744243&boundary.circle.radius=100' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing circle param \'boundary.circle\' requires all of: \'lat\',\'lon\' to be present' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['boundary.circle.lat'] +should.not.exist json.geocoding.query['boundary.circle.lon'] +should.not.exist json.geocoding.query['boundary.circle.radius'] \ No newline at end of file diff --git a/test/ciao/search/boundary_circle_valid_duo.coffee b/test/ciao/search/boundary_circle_valid_duo.coffee new file mode 100644 index 00000000..251f32ec --- /dev/null +++ b/test/ciao/search/boundary_circle_valid_duo.coffee @@ -0,0 +1,36 @@ + +#> bounding circle +path: '/v1/search?text=a&boundary.circle.lat=40.744243&boundary.circle.lon=-73.990342' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['boundary.circle.lat'].should.eql 40.744243 +json.geocoding.query['boundary.circle.lon'].should.eql -73.990342 +should.not.exist json.geocoding.query['boundary.circle.radius'] \ No newline at end of file diff --git a/test/ciao/search/boundary_circle_valid_trio.coffee b/test/ciao/search/boundary_circle_valid_trio.coffee new file mode 100644 index 00000000..08a13294 --- /dev/null +++ b/test/ciao/search/boundary_circle_valid_trio.coffee @@ -0,0 +1,36 @@ + +#> bounding circle +path: '/v1/search?text=a&boundary.circle.lat=40.744243&boundary.circle.lon=-73.990342&boundary.circle.radius=100' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['boundary.circle.lat'].should.eql 40.744243 +json.geocoding.query['boundary.circle.lon'].should.eql -73.990342 +json.geocoding.query['boundary.circle.radius'].should.eql 100 \ No newline at end of file diff --git a/test/ciao/search/boundary_country_invalid_alpha2.coffee b/test/ciao/search/boundary_country_invalid_alpha2.coffee new file mode 100644 index 00000000..06c73b6a --- /dev/null +++ b/test/ciao/search/boundary_country_invalid_alpha2.coffee @@ -0,0 +1,35 @@ + +#> bounding country +path: '/v1/search?text=a&boundary.country=ZZ' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'ZZ is not a valid ISO2/ISO3 country code' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['boundary.country'] \ No newline at end of file diff --git a/test/ciao/search/boundary_country_invalid_alpha3.coffee b/test/ciao/search/boundary_country_invalid_alpha3.coffee new file mode 100644 index 00000000..bd518281 --- /dev/null +++ b/test/ciao/search/boundary_country_invalid_alpha3.coffee @@ -0,0 +1,35 @@ + +#> bounding country +path: '/v1/search?text=a&boundary.country=ZZZ' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'ZZZ is not a valid ISO2/ISO3 country code' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['boundary.country'] \ No newline at end of file diff --git a/test/ciao/search/boundary_country_invalid_iso3166.coffee b/test/ciao/search/boundary_country_invalid_iso3166.coffee new file mode 100644 index 00000000..9f8c9d6b --- /dev/null +++ b/test/ciao/search/boundary_country_invalid_iso3166.coffee @@ -0,0 +1,35 @@ + +#> bounding country +path: '/v1/search?text=a&boundary.country=FOOBAR' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'FOOBAR is not a valid ISO2/ISO3 country code' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['boundary.country'] \ No newline at end of file diff --git a/test/ciao/search/boundary_country_valid_alpha2.coffee b/test/ciao/search/boundary_country_valid_alpha2.coffee new file mode 100644 index 00000000..45187ff5 --- /dev/null +++ b/test/ciao/search/boundary_country_valid_alpha2.coffee @@ -0,0 +1,34 @@ + +#> bounding country +path: '/v1/search?text=a&boundary.country=US' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['boundary.country'].should.eql 'USA' \ No newline at end of file diff --git a/test/ciao/search/boundary_country_valid_alpha3.coffee b/test/ciao/search/boundary_country_valid_alpha3.coffee new file mode 100644 index 00000000..9b15d6ac --- /dev/null +++ b/test/ciao/search/boundary_country_valid_alpha3.coffee @@ -0,0 +1,34 @@ + +#> bounding country +path: '/v1/search?text=a&boundary.country=USA' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['boundary.country'].should.eql 'USA' \ No newline at end of file diff --git a/test/ciao/search/boundary_rect_partially_specified.coffee b/test/ciao/search/boundary_rect_partially_specified.coffee new file mode 100644 index 00000000..c00e77bc --- /dev/null +++ b/test/ciao/search/boundary_rect_partially_specified.coffee @@ -0,0 +1,38 @@ + +#> bounding rectangle +path: '/v1/search?text=a&boundary.rect.min_lat=-40.659' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing rect param \'boundary.rect\' requires all of: \'min_lat\',\'max_lat\',\'min_lon\',\'max_lon\' to be present' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['boundary.rect.min_lat'] +should.not.exist json.geocoding.query['boundary.rect.max_lat'] +should.not.exist json.geocoding.query['boundary.rect.min_lon'] +should.not.exist json.geocoding.query['boundary.rect.max_lon'] \ No newline at end of file diff --git a/test/ciao/search/boundary_rect_valid.coffee b/test/ciao/search/boundary_rect_valid.coffee new file mode 100644 index 00000000..efb2cc4a --- /dev/null +++ b/test/ciao/search/boundary_rect_valid.coffee @@ -0,0 +1,37 @@ + +#> bounding rectangle +path: '/v1/search?text=a&boundary.rect.min_lat=-40.659&boundary.rect.max_lat=-41.614&boundary.rect.min_lon=174.612&boundary.rect.max_lon=176.333' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['boundary.rect.min_lat'].should.eql -40.659 +json.geocoding.query['boundary.rect.max_lat'].should.eql -41.614 +json.geocoding.query['boundary.rect.min_lon'].should.eql 174.612 +json.geocoding.query['boundary.rect.max_lon'].should.eql 176.333 \ No newline at end of file diff --git a/test/ciao/search/focus_point_invalid_lat.coffee b/test/ciao/search/focus_point_invalid_lat.coffee new file mode 100644 index 00000000..39df4df6 --- /dev/null +++ b/test/ciao/search/focus_point_invalid_lat.coffee @@ -0,0 +1,36 @@ + +#> focus point +path: '/v1/search?text=a&focus.point.lat=foo&focus.point.lon=-73.990342' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing param \'focus.point.lat\'' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['focus.point.lat'] +should.not.exist json.geocoding.query['focus.point.lon'] \ No newline at end of file diff --git a/test/ciao/search/focus_point_invalid_lon.coffee b/test/ciao/search/focus_point_invalid_lon.coffee new file mode 100644 index 00000000..da69a8fc --- /dev/null +++ b/test/ciao/search/focus_point_invalid_lon.coffee @@ -0,0 +1,36 @@ + +#> focus point +path: '/v1/search?text=a&focus.point.lat=40.744243&focus.point.lon=' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing param \'focus.point.lon\'' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['focus.point.lat'].should.eql 40.744243 +should.not.exist json.geocoding.query['focus.point.lon'] \ No newline at end of file diff --git a/test/ciao/search/focus_point_missing_lat.coffee b/test/ciao/search/focus_point_missing_lat.coffee new file mode 100644 index 00000000..0a730f41 --- /dev/null +++ b/test/ciao/search/focus_point_missing_lat.coffee @@ -0,0 +1,36 @@ + +#> focus point +path: '/v1/search?text=a&focus.point.lon=-73.990342' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing point param \'focus.point\' requires all of: \'lat\',\'lon\' to be present' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['focus.point.lat'] +should.not.exist json.geocoding.query['focus.point.lon'] \ No newline at end of file diff --git a/test/ciao/search/focus_point_missing_lon.coffee b/test/ciao/search/focus_point_missing_lon.coffee new file mode 100644 index 00000000..e712764c --- /dev/null +++ b/test/ciao/search/focus_point_missing_lon.coffee @@ -0,0 +1,36 @@ + +#> focus point +path: '/v1/search?text=a&focus.point.lat=40.744243' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'missing point param \'focus.point\' requires all of: \'lat\',\'lon\' to be present' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['focus.point.lat'] +should.not.exist json.geocoding.query['focus.point.lon'] \ No newline at end of file diff --git a/test/ciao/search/null_island.coffee b/test/ciao/search/focus_point_null_island.coffee similarity index 87% rename from test/ciao/search/null_island.coffee rename to test/ciao/search/focus_point_null_island.coffee index e620dc80..9d829a0e 100644 --- a/test/ciao/search/null_island.coffee +++ b/test/ciao/search/focus_point_null_island.coffee @@ -1,5 +1,5 @@ -#> null island +#> focus point null island path: '/v1/search?text=a&focus.point.lat=0&focus.point.lon=0' #? 200 ok @@ -31,5 +31,5 @@ should.not.exist json.geocoding.warnings #? inputs json.geocoding.query['text'].should.eql 'a' json.geocoding.query['size'].should.eql 10 -json.geocoding.query['lat'].should.eql 0 -json.geocoding.query['lon'].should.eql 0 \ No newline at end of file +json.geocoding.query['focus.point.lat'].should.eql 0 +json.geocoding.query['focus.point.lon'].should.eql 0 \ No newline at end of file diff --git a/test/ciao/search/focus_point_valid_duo.coffee b/test/ciao/search/focus_point_valid_duo.coffee new file mode 100644 index 00000000..4522c8a6 --- /dev/null +++ b/test/ciao/search/focus_point_valid_duo.coffee @@ -0,0 +1,35 @@ + +#> focus point +path: '/v1/search?text=a&focus.point.lat=40.744243&focus.point.lon=-73.990342' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['focus.point.lat'].should.eql 40.744243 +json.geocoding.query['focus.point.lon'].should.eql -73.990342 \ No newline at end of file diff --git a/test/ciao/search/layers_alias_address.coffee b/test/ciao/search/layers_alias_address.coffee new file mode 100644 index 00000000..c7c58472 --- /dev/null +++ b/test/ciao/search/layers_alias_address.coffee @@ -0,0 +1,35 @@ + +#> layer alias +path: '/v1/search?text=a&layers=address' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query.types['from_layers'].should.eql ["osmaddress","openaddresses"] +json.geocoding.query['type'].should.eql ["osmaddress","openaddresses"] \ No newline at end of file diff --git a/test/ciao/search/layers_alias_coarse.coffee b/test/ciao/search/layers_alias_coarse.coffee new file mode 100644 index 00000000..262be88e --- /dev/null +++ b/test/ciao/search/layers_alias_coarse.coffee @@ -0,0 +1,35 @@ + +#> layer alias +path: '/v1/search?text=a&layers=coarse' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query.types['from_layers'].should.eql ["admin0","admin1","admin2","neighborhood","locality","local_admin"] +json.geocoding.query['type'].should.eql ["admin0","admin1","admin2","neighborhood","locality","local_admin"] \ No newline at end of file diff --git a/test/ciao/search/layers_invalid.coffee b/test/ciao/search/layers_invalid.coffee new file mode 100644 index 00000000..babe7ca6 --- /dev/null +++ b/test/ciao/search/layers_invalid.coffee @@ -0,0 +1,36 @@ + +#> layer alias +path: '/v1/search?text=a&layers=notlayer' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ '\'notlayer\' is an invalid layers parameter. Valid options: venue,address,country,region,county,locality,localadmin,neighbourhood,coarse' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['types'] +should.not.exist json.geocoding.query['type'] \ No newline at end of file diff --git a/test/ciao/search/layers_mix_invalid_valid.coffee b/test/ciao/search/layers_mix_invalid_valid.coffee new file mode 100644 index 00000000..a496bdb7 --- /dev/null +++ b/test/ciao/search/layers_mix_invalid_valid.coffee @@ -0,0 +1,36 @@ + +#> layer alias +path: '/v1/search?text=a&layers=country,notlayer' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ '\'notlayer\' is an invalid layers parameter. Valid options: venue,address,country,region,county,locality,localadmin,neighbourhood,coarse' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['types'] +should.not.exist json.geocoding.query['type'] \ No newline at end of file diff --git a/test/ciao/search/layers_multiple.coffee b/test/ciao/search/layers_multiple.coffee new file mode 100644 index 00000000..db83fed7 --- /dev/null +++ b/test/ciao/search/layers_multiple.coffee @@ -0,0 +1,35 @@ + +#> layer alias +path: '/v1/search?text=a&layers=country,region' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query.types['from_layers'].should.eql ["admin0","admin1"] +json.geocoding.query['type'].should.eql ["admin0","admin1"] \ No newline at end of file diff --git a/test/ciao/search/layers_single.coffee b/test/ciao/search/layers_single.coffee new file mode 100644 index 00000000..b0d130eb --- /dev/null +++ b/test/ciao/search/layers_single.coffee @@ -0,0 +1,35 @@ + +#> layer alias +path: '/v1/search?text=a&layers=country' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query.types['from_layers'].should.eql ["admin0"] +json.geocoding.query['type'].should.eql ["admin0"] \ No newline at end of file diff --git a/test/ciao/search/privacy_false.coffee b/test/ciao/search/privacy_false.coffee new file mode 100644 index 00000000..20c1fac9 --- /dev/null +++ b/test/ciao/search/privacy_false.coffee @@ -0,0 +1,34 @@ + +#> accept privacy var +path: '/v1/search?text=a&private=false' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['private'].should.eql false \ No newline at end of file diff --git a/test/ciao/search/privacy_true.coffee b/test/ciao/search/privacy_true.coffee new file mode 100644 index 00000000..f8c3a523 --- /dev/null +++ b/test/ciao/search/privacy_true.coffee @@ -0,0 +1,34 @@ + +#> accept privacy var +path: '/v1/search?text=a&private=true' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query['private'].should.eql true \ No newline at end of file diff --git a/test/ciao/search/size_over_max.coffee b/test/ciao/search/size_over_max.coffee new file mode 100644 index 00000000..94a1db76 --- /dev/null +++ b/test/ciao/search/size_over_max.coffee @@ -0,0 +1,34 @@ + +#> set size +path: '/v1/search?text=a&size=999' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.exist json.geocoding.warnings +json.geocoding.warnings.should.eql [ 'out-of-range integer \'size\', using MAX_SIZE' ] + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 40 \ No newline at end of file diff --git a/test/ciao/search/size_under_min.coffee b/test/ciao/search/size_under_min.coffee new file mode 100644 index 00000000..a3c46db3 --- /dev/null +++ b/test/ciao/search/size_under_min.coffee @@ -0,0 +1,34 @@ + +#> set size +path: '/v1/search?text=a&size=0' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.exist json.geocoding.warnings +json.geocoding.warnings.should.eql [ 'out-of-range integer \'size\', using MIN_SIZE' ] + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 1 \ No newline at end of file diff --git a/test/ciao/search/size_valid.coffee b/test/ciao/search/size_valid.coffee new file mode 100644 index 00000000..a4bb1dcf --- /dev/null +++ b/test/ciao/search/size_valid.coffee @@ -0,0 +1,33 @@ + +#> set size +path: '/v1/search?text=a&size=3' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 3 \ No newline at end of file diff --git a/test/ciao/search/sources_invalid.coffee b/test/ciao/search/sources_invalid.coffee new file mode 100644 index 00000000..9f346faf --- /dev/null +++ b/test/ciao/search/sources_invalid.coffee @@ -0,0 +1,36 @@ + +#> sources filter +path: '/v1/search?text=a&sources=openstreetmap,notasource' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ '\'notasource\' is an invalid sources parameter. Valid options: gn,geonames,oa,openaddresses,qs,quattroshapes,osm,openstreetmap' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +should.not.exist json.geocoding.query['types'] +should.not.exist json.geocoding.query['type'] \ No newline at end of file diff --git a/test/ciao/search/sources_layers_invalid_combo.coffee b/test/ciao/search/sources_layers_invalid_combo.coffee new file mode 100644 index 00000000..ce388de7 --- /dev/null +++ b/test/ciao/search/sources_layers_invalid_combo.coffee @@ -0,0 +1,37 @@ + +#> sources and layers specified (invalid combo) +path: '/v1/search?text=a&sources=quattroshapes&layers=address' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.exist json.geocoding.errors +json.geocoding.errors.should.eql [ 'You have specified both the `sources` and `layers` parameters in a combination that will return no results.' ] + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query.types['from_layers'].should.eql ["osmaddress","openaddresses"] +json.geocoding.query.types['from_sources'].should.eql ["admin0","admin1","admin2","neighborhood","locality","local_admin"] +should.not.exist json.geocoding.query['type'] \ No newline at end of file diff --git a/test/ciao/search/sources_layers_valid_combo.coffee b/test/ciao/search/sources_layers_valid_combo.coffee new file mode 100644 index 00000000..6e11c9c7 --- /dev/null +++ b/test/ciao/search/sources_layers_valid_combo.coffee @@ -0,0 +1,35 @@ + +#> sources and layers specified +path: '/v1/search?text=a&sources=openaddresses&layers=address' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query.types['from_layers'].should.eql ["osmaddress","openaddresses"] +json.geocoding.query['type'].should.eql ["openaddresses"] \ No newline at end of file diff --git a/test/ciao/search/sources_multiple.coffee b/test/ciao/search/sources_multiple.coffee new file mode 100644 index 00000000..fa32183f --- /dev/null +++ b/test/ciao/search/sources_multiple.coffee @@ -0,0 +1,35 @@ + +#> sources filter +path: '/v1/search?text=a&sources=openstreetmap,geonames' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query.types['from_sources'].should.eql ["osmaddress","osmnode","osmway","geoname"] +json.geocoding.query['type'].should.eql ["osmaddress","osmnode","osmway","geoname"] \ No newline at end of file diff --git a/test/ciao/search/sources_single.coffee b/test/ciao/search/sources_single.coffee new file mode 100644 index 00000000..a32ad0a7 --- /dev/null +++ b/test/ciao/search/sources_single.coffee @@ -0,0 +1,35 @@ + +#> sources filter +path: '/v1/search?text=a&sources=openstreetmap' + +#? 200 ok +response.statusCode.should.be.equal 200 +response.should.have.header 'charset', 'utf8' +response.should.have.header 'content-type', 'application/json; charset=utf-8' + +#? valid geocoding block +should.exist json.geocoding +should.exist json.geocoding.version +should.exist json.geocoding.attribution +should.exist json.geocoding.query +should.exist json.geocoding.engine +should.exist json.geocoding.engine.name +should.exist json.geocoding.engine.author +should.exist json.geocoding.engine.version +should.exist json.geocoding.timestamp + +#? valid geojson +json.type.should.be.equal 'FeatureCollection' +json.features.should.be.instanceof Array + +#? expected errors +should.not.exist json.geocoding.errors + +#? expected warnings +should.not.exist json.geocoding.warnings + +#? inputs +json.geocoding.query['text'].should.eql 'a' +json.geocoding.query['size'].should.eql 10 +json.geocoding.query.types['from_sources'].should.eql ["osmaddress","osmnode","osmway"] +json.geocoding.query['type'].should.eql ["osmaddress","osmnode","osmway"] \ No newline at end of file diff --git a/test/unit/query/reverse.js b/test/unit/query/reverse.js index cb5e7513..7a2f9d07 100644 --- a/test/unit/query/reverse.js +++ b/test/unit/query/reverse.js @@ -12,7 +12,11 @@ module.exports.tests.interface = function(test, common) { module.exports.tests.query = function(test, common) { test('valid query', function(t) { var query = generate({ - 'point.lat': 29.49136, 'point.lon': -82.50622 + 'point.lat': 29.49136, + 'point.lon': -82.50622, + 'boundary.circle.lat': 29.49136, + 'boundary.circle.lon': -82.50622, + 'boundary.circle.radius': 500 }); var compiled = JSON.parse( JSON.stringify( query ) ); @@ -22,9 +26,13 @@ module.exports.tests.query = function(test, common) { t.end(); }); - test('valid query', function(t) { + test('valid query - null island', function(t) { var query = generate({ - 'point.lat': 0, 'point.lon': 0 + 'point.lat': 0, + 'point.lon': 0, + 'boundary.circle.lat': 0, + 'boundary.circle.lon': 0, + 'boundary.circle.radius': 500 }); var compiled = JSON.parse( JSON.stringify( query ) ); @@ -36,29 +44,36 @@ module.exports.tests.query = function(test, common) { test('valid query with radius', function(t) { var query = generate({ - 'point.lat': 29.49136, 'point.lon': -82.50622, 'boundary.circle.radius': 123 + 'point.lat': 29.49136, + 'point.lon': -82.50622, + 'boundary.circle.lat': 29.49136, + 'boundary.circle.lon': -82.50622, + 'boundary.circle.radius': 123 }); - var compiled = JSON.parse( JSON.stringify( query )).query.filtered.filter.bool.must[0].geo_distance.distance; + var compiled = JSON.parse( JSON.stringify( query ) ); var expected = '123km'; - t.deepEqual(compiled, expected, 'distance set to boundary circle radius'); + t.deepEqual(compiled.query.filtered.filter.bool.must[0].geo_distance.distance, expected, 'distance set to boundary circle radius'); t.end(); }); - test('valid query with boundary.circle lat/lon/radius', function(t) { + test('boundary.circle lat/lon/radius - overrides point.lat/lon when set', function(t) { var clean = { 'point.lat': 29.49136, 'point.lon': -82.50622, 'boundary.circle.lat': 111, - 'boundary.circle.long': 333 + 'boundary.circle.lon': 333, + 'boundary.circle.radius': 500 }; var query = generate(clean); + var compiled = JSON.parse( JSON.stringify( query ) ); - var compiled = JSON.parse( JSON.stringify( query )).query.filtered.filter.bool.must[0].geo_distance.center_point; - var expected = { lat: clean['point.lat'], lon: clean['point.lon'] }; + // this should not equal `point.lat` and `point.lon` as it was explitely specified + var expected = { lat: clean['boundary.circle.lat'], lon: clean['boundary.circle.lon'] }; + var centroid = compiled.query.filtered.filter.bool.must[0].geo_distance.center_point; - t.deepEqual(compiled, expected, 'point.lat/lon overrides boundary.circle.lat/lon'); + t.deepEqual(centroid, expected, 'boundary.circle/lon overrides point.lat/lon'); t.end(); }); @@ -78,8 +93,12 @@ module.exports.tests.query = function(test, common) { test('valid boundary.country reverse search', function(t) { var query = generate({ - 'point.lat': 29.49136, 'point.lon': -82.50622, - boundary: { country: 'ABC' } + 'point.lat': 29.49136, + 'point.lon': -82.50622, + 'boundary.circle.lat': 29.49136, + 'boundary.circle.lon': -82.50622, + 'boundary.circle.radius': 500, + 'boundary.country': 'ABC' }); var compiled = JSON.parse( JSON.stringify( query ) ); diff --git a/test/unit/query/search.js b/test/unit/query/search.js index 7da298dd..e236eaa7 100644 --- a/test/unit/query/search.js +++ b/test/unit/query/search.js @@ -17,12 +17,10 @@ module.exports.tests.query = function(test, common) { var query = generate({ text: 'test', size: 10, 'focus.point.lat': 29.49136, 'focus.point.lon': -82.50622, - bbox: { - top: 47.47, - right: -61.84, - bottom: 11.51, - left: -103.16 - }, + 'boundary.rect.min_lat': 47.47, + 'boundary.rect.max_lon': -61.84, + 'boundary.rect.max_lat': 11.51, + 'boundary.rect.min_lon': -103.16, layers: ['test'] }); @@ -37,12 +35,10 @@ module.exports.tests.query = function(test, common) { test('valid search + bbox', function(t) { var query = generate({ text: 'test', size: 10, - bbox: { - top: 47.47, - right: -61.84, - bottom: 11.51, - left: -103.16 - }, + 'boundary.rect.min_lat': 47.47, + 'boundary.rect.max_lon': -61.84, + 'boundary.rect.max_lat': 11.51, + 'boundary.rect.min_lon': -103.16, layers: ['test'] }); diff --git a/test/unit/sanitiser/_boundary_country.js b/test/unit/sanitiser/_boundary_country.js index 2a2e9e48..db6a0e20 100644 --- a/test/unit/sanitiser/_boundary_country.js +++ b/test/unit/sanitiser/_boundary_country.js @@ -7,7 +7,7 @@ module.exports.tests.sanitize_boundary_country = function(test, common) { var raw = { }; var clean = {}; var errorsAndWarnings = sanitize(raw, clean); - t.equals(clean.boundary.country, undefined, 'should be undefined'); + t.equals(clean['boundary.country'], undefined, 'should be undefined'); t.deepEquals(errorsAndWarnings, { errors: [], warnings: [] }, 'no warnings or errors'); t.end(); }); @@ -16,7 +16,7 @@ module.exports.tests.sanitize_boundary_country = function(test, common) { var raw = { 'boundary.country': undefined }; var clean = {}; var errorsAndWarnings = sanitize(raw, clean); - t.equals(clean.boundary.country, undefined, 'should be undefined'); + t.equals(clean['boundary.country'], undefined, 'should be undefined'); t.deepEquals(errorsAndWarnings, { errors: [], warnings: [] }, 'no warnings or errors'); t.end(); }); @@ -25,7 +25,7 @@ module.exports.tests.sanitize_boundary_country = function(test, common) { var raw = { 'boundary.country': ['this isn\'t a string primitive'] }; var clean = {}; var errorsAndWarnings = sanitize(raw, clean); - t.equals(clean.boundary.country, undefined, 'should be undefined'); + t.equals(clean['boundary.country'], undefined, 'should be undefined'); t.deepEquals(errorsAndWarnings, { errors: ['boundary.country is not a string'], warnings: [] }, 'non-string country warning'); t.end(); }); @@ -34,7 +34,7 @@ module.exports.tests.sanitize_boundary_country = function(test, common) { var raw = { 'boundary.country': 'aq' }; var clean = {}; var errorsAndWarnings = sanitize(raw, clean); - t.equals(clean.boundary.country, 'ATA', 'should be uppercased ISO3'); + t.equals(clean['boundary.country'], 'ATA', 'should be uppercased ISO3'); t.deepEquals(errorsAndWarnings, { errors: [], warnings: [] }, 'no warnings or errors'); t.end(); }); @@ -43,7 +43,7 @@ module.exports.tests.sanitize_boundary_country = function(test, common) { var raw = { 'boundary.country': 'aTa' }; var clean = {}; var errorsAndWarnings = sanitize(raw, clean); - t.equals(clean.boundary.country, 'ATA', 'should be uppercased ISO3'); + t.equals(clean['boundary.country'], 'ATA', 'should be uppercased ISO3'); t.deepEquals(errorsAndWarnings, { errors: [], warnings: [] }, 'no warnings or errors'); t.end(); }); @@ -52,7 +52,7 @@ module.exports.tests.sanitize_boundary_country = function(test, common) { var raw = { 'boundary.country': 'zq' }; var clean = {}; var errorsAndWarnings = sanitize(raw, clean); - t.equals(clean.boundary.country, undefined, 'should be undefined'); + t.equals(clean['boundary.country'], undefined, 'should be undefined'); t.deepEquals(errorsAndWarnings, { errors: ['zq is not a valid ISO2/ISO3 country code'], warnings: [] }, 'country not found warning`'); t.end(); }); @@ -61,7 +61,7 @@ module.exports.tests.sanitize_boundary_country = function(test, common) { var raw = { 'boundary.country': 'zqx' }; var clean = {}; var errorsAndWarnings = sanitize(raw, clean); - t.equals(clean.boundary.country, undefined, 'should be undefined'); + t.equals(clean['boundary.country'], undefined, 'should be undefined'); t.deepEquals(errorsAndWarnings, { errors: ['zqx is not a valid ISO2/ISO3 country code'], warnings: [] }, 'country not found warning`'); t.end(); }); diff --git a/test/unit/sanitiser/_geo_common.js b/test/unit/sanitiser/_geo_common.js index 8771e72c..47ae29fe 100644 --- a/test/unit/sanitiser/_geo_common.js +++ b/test/unit/sanitiser/_geo_common.js @@ -4,14 +4,212 @@ module.exports.tests = {}; module.exports.tests.interface = function(test, common) { test('valid interface', function(t) { - t.equal(typeof sanitize.sanitize_bbox, 'function', 'sanitize_bbox is a valid function'); + t.equal(typeof sanitize.sanitize_rect, 'function', 'sanitize_rect is a valid function'); t.equal(typeof sanitize.sanitize_coord, 'function', 'sanitize_coord is a valid function'); - t.equal(typeof sanitize.sanitize_boundary_circle, 'function', 'sanitize_boundary_circle is a valid function'); + t.equal(typeof sanitize.sanitize_circle, 'function', 'sanitize_circle is a valid function'); + t.equal(typeof sanitize.sanitize_point, 'function', 'sanitize_point is a valid function'); t.end(); }); }; -module.exports.tests.sanitize = function(test, common) { +module.exports.tests.coord = function(test, common) { + test('valid coord', function (t) { + var clean = {}; + var params = { + 'foo': -40.659 + }; + var mandatory = false; + + sanitize.sanitize_coord( 'foo', clean, params.foo, mandatory ); + t.equal(clean.foo, params.foo); + t.end(); + }); + + test('invalid coord', function (t) { + var clean = {}; + var params = { + 'foo': 'bar' + }; + var mandatory = false; + + sanitize.sanitize_coord( 'foo', clean, params.foo, mandatory ); + t.equal(clean.foo, undefined, 'not set'); + t.end(); + }); + + test('nothing specified', function (t) { + var clean = {}; + var params = {}; + var mandatory = false; + + t.doesNotThrow( function(){ + sanitize.sanitize_coord( 'foo', clean, params.foo, mandatory ); + }); + t.end(); + }); + + test('nothing specified - mandatory', function (t) { + var clean = {}; + var params = {}; + var mandatory = true; + + t.throws( function(){ + sanitize.sanitize_coord( 'foo', clean, params.foo, mandatory ); + }); + t.end(); + }); + +}; + +module.exports.tests.point = function(test, common) { + test('valid point duo', function (t) { + var clean = {}; + var params = { + 'foo.bar.lat': 11, + 'foo.bar.lon': 22 + }; + var mandatory = false; + + sanitize.sanitize_point( 'foo.bar', clean, params, mandatory ); + t.equal(clean['foo.bar.lat'], params['foo.bar.lat'], 'lat approved'); + t.equal(clean['foo.bar.lon'], params['foo.bar.lon'], 'lon approved'); + t.end(); + }); + + test('invalid point, lat only', function (t) { + var clean = {}; + var params = { + 'foo.bar.lat': 11 + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_point( 'foo.bar', clean, params, mandatory ); + }); + t.end(); + }); + + test('invalid point, lon only', function (t) { + var clean = {}; + var params = { + 'foo.bar.lon': 22, + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_point( 'foo.bar', clean, params, mandatory ); + }); + t.end(); + }); + + test('invalid lat value specified', function (t) { + var clean = {}; + var params = { + 'foo.bar.lat': 'foobar', + 'foo.bar.lon': 22, + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_point( 'foo.bar', clean, params, mandatory ); + }); + t.end(); + }); + + test('invalid lon value specified', function (t) { + var clean = {}; + var params = { + 'foo.bar.lat': 11, + 'foo.bar.lon': 'foobar' + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_point( 'foo.bar', clean, params, mandatory ); + }); + t.end(); + }); + + test('nothing specified', function (t) { + var clean = {}; + var params = {}; + var mandatory = false; + + t.doesNotThrow( function(){ + sanitize.sanitize_point( 'foo.bar', clean, params, mandatory ); + }); + t.end(); + }); + + test('nothing specified - mandatory', function (t) { + var clean = {}; + var params = {}; + var mandatory = true; + + t.throws( function(){ + sanitize.sanitize_point( 'foo.bar', clean, params, mandatory ); + }); + t.end(); + }); +}; + +module.exports.tests.rect = function(test, common) { + test('valid rect quad', function (t) { + var clean = {}; + var params = { + 'boundary.rect.min_lat': -40.659, + 'boundary.rect.max_lat': -41.614, + 'boundary.rect.min_lon': 174.612, + 'boundary.rect.max_lon': 176.333 + }; + var mandatory = false; + + sanitize.sanitize_rect( 'boundary.rect', clean, params, mandatory ); + t.equal(clean['boundary.rect.min_lat'], params['boundary.rect.min_lat'], 'min_lat approved'); + t.equal(clean['boundary.rect.max_lat'], params['boundary.rect.max_lat'], 'min_lat approved'); + t.equal(clean['boundary.rect.min_lon'], params['boundary.rect.min_lon'], 'min_lat approved'); + t.equal(clean['boundary.rect.max_lon'], params['boundary.rect.max_lon'], 'min_lat approved'); + t.end(); + }); + + test('invalid rect - partially specified', function (t) { + var clean = {}; + var params = { + 'boundary.rect.min_lat': -40.659 + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_rect( 'boundary.rect', clean, params, mandatory ); + }); + t.end(); + }); + + test('nothing specified', function (t) { + var clean = {}; + var params = {}; + var mandatory = false; + + t.doesNotThrow( function(){ + sanitize.sanitize_rect( 'boundary.rect', clean, params, mandatory ); + }); + t.end(); + }); + + test('nothing specified - mandatory', function (t) { + var clean = {}; + var params = {}; + var mandatory = true; + + t.throws( function(){ + sanitize.sanitize_rect( 'boundary.rect', clean, params, mandatory ); + }); + t.end(); + }); + +}; + +module.exports.tests.circle = function(test, common) { test('valid circle trio', function (t) { var clean = {}; var params = { @@ -19,26 +217,160 @@ module.exports.tests.sanitize = function(test, common) { 'boundary.circle.lon': 22, 'boundary.circle.radius': 33 }; - var is_required = true; - var all_required = true; + var mandatory = false; - sanitize.sanitize_boundary_circle(clean, params, is_required, all_required); + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); t.equal(clean['boundary.circle.lat'], params['boundary.circle.lat'], 'lat approved'); t.equal(clean['boundary.circle.lon'], params['boundary.circle.lon'], 'lon approved'); t.equal(clean['boundary.circle.radius'], params['boundary.circle.radius'], 'radius approved'); t.end(); }); - test('valid circle, radius only, all not required', function (t) { + test('valid circle duo', function (t) { + var clean = {}; + var params = { + 'boundary.circle.lat': 11, + 'boundary.circle.lon': 22 + }; + var mandatory = false; + + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + t.equal(clean['boundary.circle.lat'], params['boundary.circle.lat'], 'lat approved'); + t.equal(clean['boundary.circle.lon'], params['boundary.circle.lon'], 'lon approved'); + t.end(); + }); + + test('invalid circle, lat only', function (t) { + var clean = {}; + var params = { + 'boundary.circle.lat': 11, + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + }); + t.end(); + }); + + test('invalid circle, lon only', function (t) { + var clean = {}; + var params = { + 'boundary.circle.lon': 22, + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + }); + t.end(); + }); + + test('invalid circle, radius only', function (t) { var clean = {}; var params = { 'boundary.circle.radius': 33 }; - var is_required = true; - var all_required = false; + var mandatory = false; - sanitize.sanitize_boundary_circle(clean, params, is_required, all_required); - t.equal(clean['boundary.circle.radius'], params['boundary.circle.radius'], 'radius approved'); + t.throws( function(){ + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + }); + t.end(); + }); + + test('invalid circle, lon and radius only', function (t) { + var clean = {}; + var params = { + 'boundary.circle.lon': 22, + 'boundary.circle.radius': 33 + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + }); + t.end(); + }); + + test('invalid circle, lat and radius only', function (t) { + var clean = {}; + var params = { + 'boundary.circle.lat': 11, + 'boundary.circle.radius': 33 + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + }); + t.end(); + }); + + test('invalid lat value specified', function (t) { + var clean = {}; + var params = { + 'boundary.circle.lat': 'foobar', + 'boundary.circle.lon': 22, + 'boundary.circle.radius': 33 + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + }); + t.end(); + }); + + test('invalid lon value specified', function (t) { + var clean = {}; + var params = { + 'boundary.circle.lat': 11, + 'boundary.circle.lon': 'foobar', + 'boundary.circle.radius': 33 + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + }); + t.end(); + }); + + test('invalid radius value specified', function (t) { + var clean = {}; + var params = { + 'boundary.circle.lat': 11, + 'boundary.circle.lon': 22, + 'boundary.circle.radius': 'foobar' + }; + var mandatory = false; + + t.throws( function(){ + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + }); + t.end(); + }); + + test('nothing specified', function (t) { + var clean = {}; + var params = {}; + var mandatory = false; + + t.doesNotThrow( function(){ + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + }); + t.end(); + }); + + test('nothing specified - mandatory', function (t) { + var clean = {}; + var params = {}; + var mandatory = true; + + t.throws( function(){ + sanitize.sanitize_circle( 'boundary.circle', clean, params, mandatory ); + }); t.end(); }); }; diff --git a/test/unit/sanitiser/reverse.js b/test/unit/sanitiser/reverse.js index 02adaaef..759aef28 100644 --- a/test/unit/sanitiser/reverse.js +++ b/test/unit/sanitiser/reverse.js @@ -6,17 +6,18 @@ var reverse = require('../../../sanitiser/reverse'), middleware = reverse.middleware, defaultError = 'missing param \'lat\'', defaultClean = { 'point.lat': 0, + 'point.lon': 0, + 'boundary.circle.lat': 0, + 'boundary.circle.lon': 0, types: { }, - 'point.lon': 0, size: 10, - private: false, - boundary: { } + private: false }; // these are the default values you would expect when no input params are specified. // @todo: why is this different from $defaultClean? -var emptyClean = { boundary: {}, private: false, size: 10, types: {} }; +var emptyClean = { private: false, size: 10, types: {} }; module.exports.tests = {}; @@ -101,7 +102,7 @@ module.exports.tests.sanitize_lon = function(test, common) { var req = { query: { 'point.lat': 0, 'point.lon': lon } }; // @todo: why is lat set? - var expected = { boundary: {}, 'point.lat': 0, private: false, size: 10, types: {} }; + var expected = { 'point.lat': 0, private: false, size: 10, types: {} }; sanitize(req, function(){ t.equal(req.errors[0], 'missing param \'point.lon\'', 'longitude is a required field'); t.deepEqual(req.clean, expected, 'clean only has default values set'); diff --git a/test/unit/sanitiser/search.js b/test/unit/sanitiser/search.js index 9d8579e5..daa2f7ea 100644 --- a/test/unit/sanitiser/search.js +++ b/test/unit/sanitiser/search.js @@ -1,11 +1,12 @@ -var search = require('../../../sanitiser/search'), +var extend = require('extend'), + search = require('../../../sanitiser/search'), parser = require('../../../helper/query_parser'), sanitize = search.sanitize, middleware = search.middleware, defaultError = 'invalid param \'text\': text length, must be >0'; // these are the default values you would expect when no input params are specified. // @todo: why is this different from $defaultClean? -var emptyClean = { boundary: {}, private: false, size: 10, types: {} }; +var emptyClean = { private: false, size: 10, types: {} }; module.exports.tests = {}; @@ -166,8 +167,9 @@ module.exports.tests.sanitize_optional_geo = function(test, common) { var req = { query: { text: 'test', 'focus.point.lon': 0 } }; sanitize(req, function(){ var expected_lon = 0; - t.equal(req.errors[0], undefined, 'no error'); - t.deepEqual(req.clean['focus.point.lon'], expected_lon, 'clean set correctly (without any lat)'); + t.equal(req.errors[0], 'missing point param \'focus.point\' requires all of: \'lat\',\'lon\' to be present'); + t.equal(req.clean['focus.point.lat'], undefined); + t.equal(req.clean['focus.point.lon'], undefined); }); t.end(); }); @@ -175,14 +177,28 @@ module.exports.tests.sanitize_optional_geo = function(test, common) { var req = { query: { text: 'test', 'focus.point.lat': 0 } }; sanitize(req, function(){ var expected_lat = 0; - t.equal(req.errors[0], undefined, 'no error'); - t.deepEqual(req.clean['focus.point.lat'], expected_lat, 'clean set correctly (without any lon)'); + t.equal(req.errors[0], 'missing point param \'focus.point\' requires all of: \'lat\',\'lon\' to be present'); + t.equal(req.clean['focus.point.lat'], undefined); + t.equal(req.clean['focus.point.lon'], undefined); }); t.end(); }); }; -module.exports.tests.sanitize_bbox = function(test, common) { +module.exports.tests.sanitize_bounding_rect = function(test, common) { + + // convernience function to avoid refactoring the succict geojson bbox + // fixtures in to the more verbose bounding.rect format. + var mapGeoJsonBboxFormatToBoundingRectFormat = function( bbox ){ + var split = bbox.split(','); + return { + 'boundary.rect.min_lon': split[0], + 'boundary.rect.max_lat': split[1], + 'boundary.rect.max_lon': split[2], + 'boundary.rect.min_lat': split[3] + }; + }; + var bboxes = { invalid: [ '91;-181,-91,181', // invalid - semicolon between coordinates @@ -192,7 +208,8 @@ module.exports.tests.sanitize_bbox = function(test, common) { '91, -181, -91', // invalid - missing a coordinate '123,12', // invalid - missing coordinates '' // invalid - empty param - ], + ].map(mapGeoJsonBboxFormatToBoundingRectFormat), + valid: [ '-179,90,34,-80', // valid top_right lon/lat, bottom_left lon/lat '0,0,0,0', @@ -207,34 +224,33 @@ module.exports.tests.sanitize_bbox = function(test, common) { '-181,91,181,-91', '91, -181,-91,11', '91, -11,-91,181' - ] - + ].map(mapGeoJsonBboxFormatToBoundingRectFormat) }; - test('invalid bbox', function(t) { + + test('invalid bounding rect', function(t) { bboxes.invalid.forEach( function( bbox ){ - var req = { query: { text: 'test', bbox: bbox } }; + var req = { query: { text: 'test' } }; + extend( req.query, bbox ); sanitize(req, function(){ - t.equal(req.errors[0], undefined, 'no error'); - t.equal(req.clean.bbox, undefined, 'falling back on 50km distance from centroid'); + t.equal(req.clean['boundary.rect.min_lon'], undefined); + t.equal(req.clean['boundary.rect.max_lat'], undefined); + t.equal(req.clean['boundary.rect.max_lon'], undefined); + t.equal(req.clean['boundary.rect.min_lat'], undefined); + t.equal(req.errors.length, 1, 'bounding error'); }); }); t.end(); }); - test('valid bbox', function(t) { + test('valid bounding rect', function(t) { bboxes.valid.forEach( function( bbox ){ - var req = { query: { text: 'test', bbox: bbox } }; + var req = { query: { text: 'test' } }; + extend( req.query, bbox ); sanitize(req, function(){ - var bboxArray = bbox.split(',').map(function(i) { - return parseInt(i, 10); - }); - var expected_bbox = { - right: Math.max(bboxArray[0], bboxArray[2]), - top: Math.max(bboxArray[1], bboxArray[3]), - left: Math.min(bboxArray[0], bboxArray[2]), - bottom: Math.min(bboxArray[1], bboxArray[3]) - }; t.equal(req.errors[0], undefined, 'no error'); - t.deepEqual(req.clean.bbox, expected_bbox, 'clean set correctly (' + bbox + ')'); + t.equal(req.clean['boundary.rect.min_lon'], parseFloat(bbox['boundary.rect.min_lon'])); + t.equal(req.clean['boundary.rect.max_lat'], parseFloat(bbox['boundary.rect.max_lat'])); + t.equal(req.clean['boundary.rect.max_lon'], parseFloat(bbox['boundary.rect.max_lon'])); + t.equal(req.clean['boundary.rect.min_lat'], parseFloat(bbox['boundary.rect.min_lat'])); }); }); t.end();