├── .dockerignore
├── .github
└── workflows
│ ├── _test.yml
│ ├── pull_request.yml
│ └── push.yml
├── .gitignore
├── .jshintignore
├── .jshintrc
├── .npmrc
├── Dockerfile
├── LICENSE
├── README.md
├── app.js
├── bin
├── generate-docs
├── start
└── units
├── controller
├── coarse_reverse.js
├── libpostal.js
├── markdownToHtml.js
├── place.js
├── placeholder.js
├── predicates
│ ├── hasParsedTextProperties.js
│ ├── hasRequestErrors.js
│ ├── hasRequestParameter.js
│ ├── hasResponseData.js
│ ├── hasResultsAtLayers.js
│ ├── isAdminOnlyAnalysis.js
│ ├── isCoarseReverse.js
│ ├── isOnlyNonAdminLayers.js
│ ├── isPeliasParse.js
│ ├── isRequestLayersAnyAddressRelated.js
│ ├── isRequestSourcesIncludesWhosOnFirst.js
│ ├── isRequestSourcesOnlyWhosOnFirst.js
│ └── isRequestSourcesUndefined.js
├── search.js
├── status.js
└── structured_libpostal.js
├── helper
├── TypeMapping.js
├── debug.js
├── decode_gid.js
├── diffPlaces.js
├── fieldValue.js
├── geojsonify.js
├── geojsonify_place_details.js
├── iso3166.js
├── logging.js
├── placeTypes.js
├── stackTraceLine.js
├── type_mapping.js
├── type_mapping_discovery.js
└── unicode.js
├── index.js
├── middleware
├── 404.js
├── 500.js
├── access_log.js
├── accuracy.js
├── applyOverrides.js
├── assignLabels.js
├── changeLanguage.js
├── confidenceScore.js
├── confidenceScoreFallback.js
├── confidenceScoreReverse.js
├── cors.js
├── dedupe.js
├── distance.js
├── expandDocument.js
├── geocodeJSON.js
├── headers.js
├── interpolate.js
├── jsonp.js
├── localNamingConventions.js
├── mapFields.js
├── normalizeParentIds.js
├── options.js
├── parseBBox.js
├── requestLanguage.js
├── robots.js
├── sendJSON.js
├── sizeCalculator.js
├── sortResponseData.js
├── trimByGranularity.js
└── trimByGranularityStructured.js
├── package.json
├── public
├── apiDoc.md
└── attribution.md
├── query
├── address_search_using_ids.js
├── autocomplete.js
├── autocomplete_defaults.js
├── reverse.js
├── reverse_defaults.js
├── search.js
├── search_defaults.js
├── search_pelias_parser.js
├── structured_geocoding.js
├── text_parser.js
├── text_parser_pelias.js
└── view
│ ├── admin_multi_match_first.js
│ ├── admin_multi_match_last.js
│ ├── boost_sources_and_layers.js
│ ├── focus_point_distance_filter.js
│ ├── helper.js
│ ├── max_character_count_layer_filter.js
│ ├── ngrams_last_token_only.js
│ ├── ngrams_last_token_only_multi.js
│ ├── ngrams_strict.js
│ └── phrase_first_tokens_only.js
├── routes
├── default.js
└── v1.js
├── sanitizer
├── PeliasParameterError.js
├── PeliasServiceError.js
├── PeliasTimeoutError.js
├── _address_layer_filter.js
├── _boundary_country.js
├── _boundary_gid.js
├── _categories.js
├── _city_name_standardizer.js
├── _debug.js
├── _default_parameters.js
├── _flag_bool.js
├── _geo_autocomplete.js
├── _geo_common.js
├── _geo_reverse.js
├── _geo_search.js
├── _geonames_deprecation.js
├── _geonames_warnings.js
├── _groups.js
├── _ids.js
├── _iso2_to_iso3.js
├── _request_language.js
├── _single_scalar_parameters.js
├── _size.js
├── _sources_and_layers.js
├── _synthesize_analysis.js
├── _targets.js
├── _text.js
├── _text_pelias_parser.js
├── _tokenizer.js
├── autocomplete.js
├── defer_to_pelias_parser.js
├── nearby.js
├── place.js
├── reverse.js
├── sanitizeAll.js
├── search.js
├── structured_geocoding.js
└── wrap.js
├── schema.js
├── service
├── configurations
│ ├── Interpolation.js
│ ├── Language.js
│ ├── Libpostal.js
│ ├── PlaceHolder.js
│ └── PointInPolygon.js
├── mget.js
└── search.js
└── test
├── ciao.json
├── ciao
├── 404.coffee
├── CORS
│ ├── headers_GET.coffee
│ └── headers_OPTIONS.coffee
├── autocomplete
│ ├── boundary_gid_invalid.coffee
│ ├── boundary_gid_valid.coffee
│ ├── boundary_rect_valid.coffee
│ ├── focus_point_invalid_lat.coffee
│ ├── focus_point_invalid_lon.coffee
│ ├── focus_point_missing_lat.coffee
│ ├── focus_point_missing_lon.coffee
│ ├── focus_point_null_island.coffee
│ ├── focus_point_valid_duo.coffee
│ ├── language_default.coffee
│ ├── language_header_invalid.coffee
│ ├── language_header_valid.coffee
│ ├── language_querystring_invalid.coffee
│ ├── language_querystring_valid.coffee
│ ├── layers_alias_address.coffee
│ ├── layers_alias_coarse.coffee
│ ├── layers_invalid.coffee
│ ├── layers_mix_invalid_valid.coffee
│ ├── layers_multiple.coffee
│ ├── layers_single.coffee
│ ├── no_params.coffee
│ ├── non_scalar_parameter_array.coffee
│ ├── non_scalar_parameter_object.coffee
│ ├── size_not_default.coffee
│ ├── sources_invalid.coffee
│ ├── sources_layers_invalid_combo.coffee
│ ├── sources_layers_valid_combo.coffee
│ ├── sources_multiple.coffee
│ ├── sources_single.coffee
│ ├── text_invalid.coffee
│ └── text_valid.coffee
├── index.coffee
├── place
│ ├── basic_place.coffee
│ ├── language_default.coffee
│ ├── language_header_invalid.coffee
│ ├── language_header_valid.coffee
│ ├── language_querystring_invalid.coffee
│ ├── language_querystring_valid.coffee
│ └── missing_id.coffee
├── reverse
│ ├── basic_reverse.coffee
│ ├── boundary_circle_invalid_radius.coffee
│ ├── boundary_circle_valid_radius.coffee
│ ├── boundary_circle_valid_radius_coarse.coffee
│ ├── boundary_country_invalid_alpha2.coffee
│ ├── boundary_country_invalid_alpha3.coffee
│ ├── boundary_country_invalid_iso3166.coffee
│ ├── boundary_country_valid_alpha2.coffee
│ ├── boundary_country_valid_alpha3.coffee
│ ├── boundary_gid_invalid.coffee
│ ├── boundary_gid_valid.coffee
│ ├── duplicate_parameter_name.coffee
│ ├── language_default.coffee
│ ├── language_header_invalid.coffee
│ ├── language_header_valid.coffee
│ ├── language_querystring_invalid.coffee
│ ├── language_querystring_valid.coffee
│ ├── layers_alias_address.coffee
│ ├── layers_alias_coarse.coffee
│ ├── layers_invalid.coffee
│ ├── layers_mix_invalid_valid.coffee
│ ├── layers_multiple.coffee
│ ├── layers_single.coffee
│ ├── non_scalar_parameter_array.coffee
│ ├── non_scalar_parameter_object.coffee
│ ├── point_invalid_lat.coffee
│ ├── point_invalid_lon.coffee
│ ├── point_missing_lat.coffee
│ ├── point_missing_lon.coffee
│ ├── point_null_island.coffee
│ ├── point_valid_duo.coffee
│ ├── privacy_false.coffee
│ ├── privacy_true.coffee
│ ├── size_over_max.coffee
│ ├── size_under_min.coffee
│ ├── size_valid.coffee
│ ├── sources_invalid.coffee
│ ├── sources_layers_invalid_combo.coffee
│ ├── sources_layers_valid_combo.coffee
│ ├── sources_multiple.coffee
│ └── sources_single.coffee
└── search
│ ├── address_parsing.coffee
│ ├── boundary_circle_invalid_lat_lon_types.coffee
│ ├── boundary_circle_invalid_radius.coffee
│ ├── boundary_circle_missing_lat.coffee
│ ├── boundary_circle_missing_lon.coffee
│ ├── boundary_circle_valid_duo.coffee
│ ├── boundary_circle_valid_trio.coffee
│ ├── boundary_country_invalid_alpha2.coffee
│ ├── boundary_country_invalid_alpha3.coffee
│ ├── boundary_country_invalid_iso3166.coffee
│ ├── boundary_country_valid_alpha2.coffee
│ ├── boundary_country_valid_alpha3.coffee
│ ├── boundary_gid_invalid.coffee
│ ├── boundary_gid_valid.coffee
│ ├── boundary_rect_partially_specified.coffee
│ ├── boundary_rect_valid.coffee
│ ├── focus_point_invalid_lat.coffee
│ ├── focus_point_invalid_lon.coffee
│ ├── focus_point_missing_lat.coffee
│ ├── focus_point_missing_lon.coffee
│ ├── focus_point_null_island.coffee
│ ├── focus_point_valid_duo.coffee
│ ├── language_default.coffee
│ ├── language_header_invalid.coffee
│ ├── language_header_valid.coffee
│ ├── language_querystring_invalid.coffee
│ ├── language_querystring_valid.coffee
│ ├── layers_alias_address.coffee
│ ├── layers_alias_coarse.coffee
│ ├── layers_invalid.coffee
│ ├── layers_mix_invalid_valid.coffee
│ ├── layers_multiple.coffee
│ ├── layers_single.coffee
│ ├── no_params.coffee
│ ├── non_scalar_parameter_array.coffee
│ ├── non_scalar_parameter_object.coffee
│ ├── privacy_false.coffee
│ ├── privacy_true.coffee
│ ├── size_over_max.coffee
│ ├── size_under_min.coffee
│ ├── size_valid.coffee
│ ├── sources_invalid.coffee
│ ├── sources_layers_invalid_combo.coffee
│ ├── sources_layers_valid_combo.coffee
│ ├── sources_multiple.coffee
│ ├── sources_single.coffee
│ ├── text_invalid.coffee
│ └── text_valid.coffee
├── ciao_test_data.js
├── test-pelias-config.json
└── unit
├── app.js
├── controller
├── coarse_reverse.js
├── index.js
├── libpostal.js
├── place.js
├── placeholder.js
├── predicates
│ ├── hasParsedTextProperties.js
│ ├── hasRequestErrors.js
│ ├── hasRequestParameter.js
│ ├── hasResponseData.js
│ ├── hasResultsAtLayers.js
│ ├── isAdminOnlyAnalysis.js
│ ├── isCoarseReverse.js
│ ├── isOnlyNonAdminLayers.js
│ ├── isPeliasParse.js
│ ├── isRequestLayersAnyAddressRelated.js
│ ├── isRequestSourcesIncludesWhosOnFirst.js
│ ├── isRequestSourcesOnlyWhosOnFirst.js
│ └── isRequestSourcesUndefined.js
├── search.js
└── structured_libpostal.js
├── fixture
├── autocomplete_boundary_country.js
├── autocomplete_boundary_gid.js
├── autocomplete_custom_boosts.json
├── autocomplete_linguistic_bbox_san_francisco.js
├── autocomplete_linguistic_circle_san_francisco.js
├── autocomplete_linguistic_final_token.js
├── autocomplete_linguistic_focus.js
├── autocomplete_linguistic_focus_null_island.js
├── autocomplete_linguistic_multiple_tokens.js
├── autocomplete_linguistic_multiple_tokens_complete_numeric.js
├── autocomplete_linguistic_one_char_token.js
├── autocomplete_linguistic_only.js
├── autocomplete_linguistic_three_char_token.js
├── autocomplete_linguistic_two_char_token.js
├── autocomplete_linguistic_with_admin.js
├── autocomplete_single_character_street.js
├── autocomplete_with_category_filtering.js
├── autocomplete_with_layer_filtering.js
├── autocomplete_with_source_filtering.js
├── dedupe_elasticsearch_custom_layer_results.js
├── dedupe_elasticsearch_nonascii_results.js
├── dedupe_elasticsearch_results.js
├── dedupe_only_postalcode_differs.js
├── search_boundary_country.js
├── search_boundary_country_multi.js
├── search_boundary_gid.js
├── search_fallback.js
├── search_fallback_postalcode_only.js
├── search_linguistic_bbox.js
├── search_linguistic_focus.js
├── search_linguistic_focus_bbox.js
├── search_linguistic_focus_null_island.js
├── search_linguistic_only.js
├── search_pelias_parser_boundary_country.js
├── search_pelias_parser_boundary_gid.js
├── search_pelias_parser_full_address.js
├── search_pelias_parser_linguistic_bbox.js
├── search_pelias_parser_linguistic_focus.js
├── search_pelias_parser_linguistic_focus_bbox.js
├── search_pelias_parser_linguistic_focus_null_island.js
├── search_pelias_parser_linguistic_only.js
├── search_pelias_parser_partial_address.js
├── search_pelias_parser_regions_address.js
├── search_pelias_parser_with_category_filtering.js
├── search_pelias_parser_with_source_filtering.js
├── search_with_category_filtering.js
├── search_with_custom_boosts.json
└── search_with_source_filtering.js
├── helper
├── TypeMapping.js
├── debug.js
├── decode_gid.js
├── diffPlaces.js
├── fieldValue.js
├── geojsonify.js
├── geojsonify_place_details.js
├── iso3166.js
├── logging.js
├── stackTraceLine.js
├── type_mapping.js
└── unicode.js
├── middleware
├── access_log.js
├── accuracy.js
├── applyOverrides.js
├── assignLabels.js
├── changeLanguage.js
├── confidenceScore.js
├── confidenceScoreFallback.js
├── confidenceScoreReverse.js
├── dedupe.js
├── distance.js
├── interpolate.js
├── localNamingConventions.js
├── mapFields.js
├── normalizeParentIds.js
├── parseBBox.js
├── requestLanguage.js
├── sendJSON.js
├── sizeCalculator.js
├── sortResponseData.js
├── trimByGranularity.js
└── trimByGranularityStructured.js
├── query
├── MockQuery.js
├── address_search_using_ids.js
├── autocomplete.js
├── autocomplete_defaults.js
├── autocomplete_token_matching_permutations.js
├── autocomplete_with_custom_boosts.js
├── reverse.js
├── reverse_defaults.js
├── search.js
├── search_defaults.js
├── search_pelias_parser.js
├── search_with_custom_boosts.js
├── structured_geocoding.js
├── text_parser.js
└── view
│ ├── boost_sources_and_layers.js
│ └── max_character_count_layer_filter.js
├── run.js
├── sanitizer
├── _address_layer_filter.js
├── _boundary_country.js
├── _boundary_gid.js
├── _categories.js
├── _city_name_standardizer.js
├── _debug.js
├── _default_parameters.js
├── _flag_bool.js
├── _geo_common.js
├── _geo_reverse.js
├── _geonames_deprecation.js
├── _geonames_warnings.js
├── _groups.js
├── _ids.js
├── _iso2_to_iso3.js
├── _layers.js
├── _request_language.js
├── _single_scalar_parameters.js
├── _size.js
├── _sources.js
├── _sources_and_layers.js
├── _synthesize_analysis.js
├── _text.js
├── _text_pelias_parser.js
├── _tokenizer.js
├── _truthy.js
├── autocomplete.js
├── defer_to_pelias_parser.js
├── nearby.js
├── place.js
├── reverse.js
├── sanitizeAll.js
├── search.js
├── structured_geocoding.js
└── wrap.js
├── schema.js
└── service
├── configurations
├── Interpolation.js
├── Language.js
├── Libpostal.js
├── PlaceHolder.js
└── PointInPolygon.js
├── mget.js
└── search.js
/.dockerignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules/
31 |
32 | # Typescript v1 declaration files
33 | typings/
34 |
35 | # Optional npm cache directory
36 | .npm
37 |
38 | # Optional eslint cache
39 | .eslintcache
40 |
41 | # Optional REPL history
42 | .node_repl_history
43 |
44 | # Output of 'npm pack'
45 | *.tgz
46 |
47 | # Yarn Integrity file
48 | .yarn-integrity
49 |
50 | # Git
51 | .git
52 |
--------------------------------------------------------------------------------
/.github/workflows/_test.yml:
--------------------------------------------------------------------------------
1 | name: Unit Tests
2 | on: workflow_call
3 | jobs:
4 | unit-tests:
5 | runs-on: '${{ matrix.os }}'
6 | strategy:
7 | matrix:
8 | os:
9 | - ubuntu-22.04
10 | node-version: [ 18.x, 20.x, 22.x ]
11 | steps:
12 | - uses: actions/checkout@v4
13 | - name: 'Install node.js ${{ matrix.node-version }}'
14 | uses: actions/setup-node@v4
15 | with:
16 | node-version: '${{ matrix.node-version }}'
17 | - name: Run unit tests
18 | run: |
19 | [[ -f ./bin/ci-setup ]] && ./bin/ci-setup
20 | npm install
21 | npm run ci
22 |
--------------------------------------------------------------------------------
/.github/workflows/pull_request.yml:
--------------------------------------------------------------------------------
1 | name: Continuous Integration
2 | on: pull_request
3 | jobs:
4 | unit-tests:
5 | # only run this job for forks
6 | if: github.event.pull_request.head.repo.full_name != github.repository
7 | uses: ./.github/workflows/_test.yml
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | .idea
4 | *.log
5 | reports
6 | pids
7 | pelias.json
8 |
--------------------------------------------------------------------------------
/.jshintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | reports
4 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "curly": true,
4 | "eqeqeq": true,
5 | "esversion": "2022",
6 | "freeze": true,
7 | "immed": true,
8 | "indent": 2,
9 | "latedef": false,
10 | "newcap": true,
11 | "noarg": true,
12 | "noempty": true,
13 | "nonbsp": true,
14 | "nonew": true,
15 | "plusplus": false,
16 | "quotmark": "single",
17 | "undef": true,
18 | "unused": false,
19 | "maxparams": 4,
20 | "maxdepth": 4,
21 | "maxlen": 140
22 | }
23 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # base image
2 | FROM pelias/baseimage
3 | USER pelias
4 |
5 | # change working dir
6 | ENV WORKDIR /code/pelias/api
7 | RUN mkdir -p ${WORKDIR}
8 | WORKDIR ${WORKDIR}
9 |
10 | # copy package.json first to prevent npm install being rerun when only code changes
11 | COPY ./package.json ${WORKDIR}
12 | RUN npm install
13 |
14 | COPY . ${WORKDIR}
15 |
16 | # only allow containers to succeed if tests pass
17 | RUN npm test
18 |
19 | # start service
20 | CMD [ "./bin/start" ]
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Pelias Contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | var app = require('express')();
2 |
3 | var peliasConfig = require( 'pelias-config' ).generate(require('./schema'));
4 |
5 | if( peliasConfig.api.accessLog ){
6 | app.use( require( './middleware/access_log' ).createAccessLogger( peliasConfig.api.accessLog ) );
7 | }
8 |
9 | /** ----------------------- pre-processing-middleware ----------------------- **/
10 |
11 | app.use( require('./middleware/headers') );
12 | app.use( require('./middleware/cors') );
13 | app.use( require('./middleware/robots') );
14 | app.use( require('./middleware/options') );
15 | app.use( require('./middleware/jsonp') );
16 |
17 | /** ----------------------- routes ----------------------- **/
18 |
19 |
20 | var defaultRoutes = require('./routes/default');
21 | defaultRoutes.addRoutes(app);
22 |
23 | var v1 = require('./routes/v1');
24 | v1.addRoutes(app, peliasConfig);
25 |
26 | /** ----------------------- error middleware ----------------------- **/
27 |
28 | app.use( require('./middleware/404') );
29 | app.use( require('./middleware/500') );
30 |
31 | module.exports = app;
32 |
--------------------------------------------------------------------------------
/bin/generate-docs:
--------------------------------------------------------------------------------
1 | #!/bin/bash -ex
2 |
3 | rm -r docs || true
4 |
5 | curl -s http://localhost:3100/v1 > /dev/null || die "Pelias server does not appear to be running \
6 | on http://localhost:3100, run npm start in another window before generating docs."
7 |
8 | cd test/ciao
9 | node ../../node_modules/ciao/bin/ciao -c ../ciao.json . -d ../../docs
10 |
--------------------------------------------------------------------------------
/bin/start:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | exec node index.js
3 |
--------------------------------------------------------------------------------
/bin/units:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # run tests with pipefail to avoid false passes
4 | # see https://github.com/pelias/pelias/issues/744
5 | set -euo pipefail
6 |
7 | PELIAS_CONFIG=./test/test-pelias-config.json node --trace-uncaught test/unit/run.js | npx tap-dot
8 |
--------------------------------------------------------------------------------
/controller/markdownToHtml.js:
--------------------------------------------------------------------------------
1 | const markdown = require('markdown').markdown;
2 | const fs = require('fs');
3 |
4 | function setup(peliasConfig, markdownFile) {
5 |
6 | // read markdown
7 | const md = fs.readFileSync(markdownFile, 'utf8').trim();
8 |
9 | // convert to HTML
10 | const html = `
11 |
12 |
13 |
14 |
15 | Pelias Geocoder
16 |
17 |
18 |
19 | ${markdown.toHTML(md)}
20 |
21 | `.trim();
22 |
23 | // send HTML
24 | return function controller(req, res) {
25 | res.send(html);
26 | };
27 | }
28 |
29 | module.exports = setup;
30 |
--------------------------------------------------------------------------------
/controller/predicates/hasParsedTextProperties.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 |
3 | // "arguments" is only available in long-form function declarations, cannot be shortened to fat arrow syntax
4 | // potential improvement: inject set operator to allow for any/all functionality
5 | module.exports = {
6 | all: function() {
7 | // save off property names for future reference
8 | const properties = _.values(arguments);
9 |
10 | // return true if ALL of the supplied properties are in clean.parsed_text
11 | return request => _.isEmpty(
12 | _.difference(
13 | _.values(properties),
14 | _.keys(_.get(request, ['clean', 'parsed_text'], {}))
15 | )
16 | );
17 |
18 | },
19 | any: function() {
20 | // save off property names for future reference
21 | const properties = _.values(arguments);
22 |
23 | // return true if ANY of the supplied properties are in clean.parsed_text
24 | return request => !_.isEmpty(
25 | _.intersection(
26 | _.values(properties),
27 | _.keys(_.get(request, ['clean', 'parsed_text'], {}))
28 | )
29 | );
30 |
31 | }
32 |
33 | };
34 |
--------------------------------------------------------------------------------
/controller/predicates/hasRequestErrors.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:has_request_errors');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 |
6 | module.exports = (req, res) => {
7 | const has_request_errors = _.get(req, 'errors', []).length > 0;
8 | debugLog.push(req, () => ({
9 | reply: has_request_errors,
10 | stack_trace: stackTraceLine()
11 | }));
12 | return has_request_errors;
13 | };
14 |
--------------------------------------------------------------------------------
/controller/predicates/hasRequestParameter.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:has_request_parameter');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 |
6 | // returns true IFF req.clean has a key with the supplied name AND a non-empty value
7 | module.exports = (parameter) => (req, res) => {
8 | const value = _.get(req, ['clean', parameter]);
9 | const has_request_parameter = _.isNumber(value) || !_.isEmpty(value);
10 |
11 | debugLog.push(req, () => ({
12 | reply: {[parameter]: has_request_parameter},
13 | stack_trace: stackTraceLine()
14 | }));
15 |
16 | return has_request_parameter;
17 | };
18 |
--------------------------------------------------------------------------------
/controller/predicates/hasResponseData.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:has_response_data');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 |
6 | module.exports = (request, response) => {
7 | const has_response_data = _.get(response, 'data', []).length > 0;
8 | debugLog.push(request, () => ({
9 | reply: has_response_data,
10 | stack_trace: stackTraceLine()
11 | }));
12 | return has_response_data;
13 | };
14 |
--------------------------------------------------------------------------------
/controller/predicates/hasResultsAtLayers.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:has_results_at_layers');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 | // returns a function that returns true if any result.layer is in any of the
6 | // supplied layers using array intersection
7 |
8 | // example usage: determining if the response contains only admin results
9 |
10 | module.exports = (layers) => {
11 | return (request, response) => {
12 | const has_results_at_layers = !_.isEmpty(
13 | _.intersection(
14 | // convert layers to an array if it isn't already one
15 | _.castArray(layers),
16 | // pull all the layer properties into an array
17 | _.map(response.data, _.property('layer'))
18 | ));
19 |
20 | debugLog.push(request, () => ({
21 | reply: {[layers]: has_results_at_layers},
22 | stack_trace: stackTraceLine()
23 | }));
24 | return has_results_at_layers;
25 | };
26 |
27 | };
28 |
--------------------------------------------------------------------------------
/controller/predicates/isAdminOnlyAnalysis.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:is_admin_only_analysis');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 |
6 | module.exports = (request, response) => {
7 | if (!request.clean.hasOwnProperty('parsed_text')) {
8 | debugLog.push(request, false + ' (no parsed_text)');
9 | return false;
10 | }
11 |
12 | // return true only if all non-admin properties of parsed_text are empty
13 | const is_admin_only_analysis = ['unit', 'housenumber', 'street', 'query', 'category', 'postalcode'].every((prop) => {
14 | return _.isEmpty(request.clean.parsed_text[prop]);
15 | });
16 |
17 | debugLog.push(request, () => ({
18 | reply: is_admin_only_analysis,
19 | stack_trace: stackTraceLine()
20 | }));
21 | return is_admin_only_analysis;
22 | };
23 |
--------------------------------------------------------------------------------
/controller/predicates/isCoarseReverse.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:is_coarse_reverse');
4 | const non_coarse_layers = ['address', 'street', 'venue'];
5 | const stackTraceLine = require('../../helper/stackTraceLine');
6 |
7 | module.exports = (req, res) => {
8 | // returns true if layers is undefined, empty, or contains 'address', 'street', or 'venue'
9 | const is_coarse_reverse = !_.isEmpty(req.clean.layers) &&
10 | _.isEmpty(_.intersection(req.clean.layers, non_coarse_layers));
11 | debugLog.push(req, () => ({
12 | reply: is_coarse_reverse,
13 | stack_trace: stackTraceLine()
14 | }));
15 | return is_coarse_reverse;
16 | };
17 |
--------------------------------------------------------------------------------
/controller/predicates/isOnlyNonAdminLayers.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:is_only_non_admin_layers');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 |
6 | // return true IFF req.clean.layers is empty OR there are non-venue/address/street layers
7 | module.exports = (req, res) => {
8 | const is_only_non_admin_layers = !_.isEmpty(_.get(req, 'clean.layers', [])) &&
9 | _.isEmpty(_.difference(req.clean.layers, ['venue', 'address', 'street']));
10 |
11 | debugLog.push(req, () => ({
12 | reply: is_only_non_admin_layers,
13 | stack_trace: stackTraceLine()
14 | }));
15 | return is_only_non_admin_layers;
16 | };
17 |
--------------------------------------------------------------------------------
/controller/predicates/isPeliasParse.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:is_pelias_parse');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 |
6 | // returns true IFF req.clean.parser is pelias
7 | module.exports = (req, res) => {
8 | const is_pelias_parse = _.get(req, 'clean.parser') === 'pelias';
9 | debugLog.push(req, () => ({
10 | reply: is_pelias_parse,
11 | stack_trace: stackTraceLine()
12 | }));
13 | return is_pelias_parse;
14 | };
15 |
--------------------------------------------------------------------------------
/controller/predicates/isRequestLayersAnyAddressRelated.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:is_request_layers_any_address_related');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 |
6 | // return true if any layers allowed by the query are related to an address query
7 | // this includes address and street but NOT venue, postalcode, admin, and custom layers
8 | module.exports = (req, res) => {
9 | const address_related_layers = ['address', 'street'];
10 |
11 | const request_layers = _.get(req, 'clean.layers', []);
12 | let result;
13 |
14 | // handle case where no layers are specified
15 | if (request_layers.length === 0) {
16 | result = true;
17 | } else {
18 | const request_address_related_layers = _.intersection(request_layers, address_related_layers);
19 | result = request_address_related_layers.length > 0;
20 | }
21 |
22 | debugLog.push(req, () => ({
23 | reply: result,
24 | stack_trace: stackTraceLine()
25 | }));
26 |
27 | return result;
28 | };
29 |
--------------------------------------------------------------------------------
/controller/predicates/isRequestSourcesIncludesWhosOnFirst.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:is_request_sources_includes_whosonfirst');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 |
6 | // returns true IFF 'whosonfirst' is included in the requested sources
7 | module.exports = (req, res) => {
8 | const is_request_sources_includes_whosonfirst = _.get(req, 'clean.sources', []).includes(
9 | 'whosonfirst'
10 | );
11 | debugLog.push(req, () => ({
12 | reply: is_request_sources_includes_whosonfirst,
13 | stack_trace: stackTraceLine()
14 | }));
15 | return is_request_sources_includes_whosonfirst;
16 | };
17 |
--------------------------------------------------------------------------------
/controller/predicates/isRequestSourcesOnlyWhosOnFirst.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:is_request_sources_only_whosonfirst');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 |
6 | // returns true IFF 'whosonfirst' is the only requested source
7 | module.exports = (req, res) => {
8 | const is_request_sources_only_whosonfirst = _.isEqual(
9 | _.get(req, 'clean.sources', []),
10 | ['whosonfirst']
11 | );
12 | debugLog.push(req, () => ({
13 | reply: is_request_sources_only_whosonfirst,
14 | stack_trace: stackTraceLine()
15 | }));
16 | return is_request_sources_only_whosonfirst;
17 | };
18 |
--------------------------------------------------------------------------------
/controller/predicates/isRequestSourcesUndefined.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const Debug = require('../../helper/debug');
3 | const debugLog = new Debug('controller:predicates:is_request_sources_undefined');
4 | const stackTraceLine = require('../../helper/stackTraceLine');
5 |
6 | // returns true IFF there are no requested sources
7 | module.exports = (req, res) => {
8 | const is_request_sources_undefined = _.isEmpty(
9 | _.get(req, 'clean.sources')
10 | );
11 | debugLog.push(req, () => ({
12 | reply: is_request_sources_undefined,
13 | stack_trace: stackTraceLine()
14 | }));
15 | return is_request_sources_undefined;
16 | };
17 |
--------------------------------------------------------------------------------
/controller/status.js:
--------------------------------------------------------------------------------
1 | module.exports = function controller( req, res, next) {
2 | res.send('status: ok');
3 | };
4 |
--------------------------------------------------------------------------------
/helper/debug.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 |
3 | class Debug {
4 | constructor(moduleName) {
5 | this.name = moduleName || 'unnamed module';
6 | }
7 |
8 | static isEnabled(req) {
9 | return _.get(req, 'clean.enableDebug') === true;
10 | }
11 |
12 | static validMessage(msg) {
13 | return _.isString(msg) && !_.isEmpty(msg);
14 | }
15 |
16 | push(req, value) {
17 | if (!Debug.isEnabled(req)) { return; }
18 |
19 | if (!_.isArray(req.debug)) { req.debug = []; }
20 |
21 | if (_.isFunction(value)) {
22 | req.debug.push({ [this.name]: value() });
23 | } else {
24 | req.debug.push({ [this.name]: value });
25 | }
26 | }
27 |
28 | beginTimer(req, message) {
29 | if (!Debug.isEnabled(req)) { return; }
30 |
31 | if (Debug.validMessage(message)) {
32 | this.push(req, `Timer Began. ${message}`);
33 | } else {
34 | this.push(req, `Timer Began.`);
35 | }
36 |
37 | return Date.now();
38 | }
39 |
40 | stopTimer(req, timer, message) {
41 | if (!Debug.isEnabled(req)) { return; }
42 |
43 | // measure elapsed duration
44 | const elapsed = _.isFinite(timer) ? (Date.now() - timer) : -1;
45 |
46 | if (Debug.validMessage(message)) {
47 | this.push(req, `Timer Stopped. ${elapsed} ms. ${message}`);
48 | } else {
49 | this.push(req, `Timer Stopped. ${elapsed} ms`);
50 | }
51 | }
52 | }
53 |
54 | module.exports = Debug;
55 |
--------------------------------------------------------------------------------
/helper/decode_gid.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 |
3 | // helper method to decode a GID from a string
4 | // for additional validation see sanitizer/_ids.js
5 |
6 | function decodeGID(gid) {
7 | const parts = gid.split(':');
8 |
9 | if ( parts.length < 3 ) {
10 | return;
11 | }
12 |
13 | const source = parts[0].toLowerCase();
14 | const layer = parts[1].toLowerCase();
15 |
16 | // empty strings and other invalid values are expected to be handled by the caller
17 | return {
18 | source: source,
19 | layer: layer,
20 | id: parts.slice(2).join(':'),
21 | };
22 | }
23 |
24 | module.exports = decodeGID;
25 |
--------------------------------------------------------------------------------
/helper/fieldValue.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 |
3 | function getStringValue(property) {
4 | // numeric value, cast to string
5 | if (_.isNumber(property)) {
6 | return _.toString(property);
7 | }
8 |
9 | // isEmpty check works for all types of values: strings, arrays, objects
10 | if (_.isEmpty(property)) {
11 | return '';
12 | }
13 |
14 | if (_.isString(property)) {
15 | return property;
16 | }
17 |
18 | // array value, take first item in array (at this time only used for admin & name values)
19 | if (_.isArray(property)) {
20 | return property[0];
21 | }
22 |
23 | return _.toString(property);
24 | }
25 |
26 | function getArrayValue(property) {
27 | // numeric value, cast to array
28 | if (_.isNumber(property)) {
29 | return [property];
30 | }
31 |
32 | // isEmpty check works for all types of values: strings, arrays, objects
33 | if (_.isEmpty(property)) {
34 | return [];
35 | }
36 |
37 | if (_.isArray(property)) {
38 | return property;
39 | }
40 |
41 | return [property];
42 | }
43 |
44 | module.exports.getStringValue = getStringValue;
45 | module.exports.getArrayValue = getArrayValue;
46 |
--------------------------------------------------------------------------------
/helper/logging.js:
--------------------------------------------------------------------------------
1 | var fieldsToRemove = ['text', 'focus.point.lat', 'focus.point.lon',
2 | 'boundary.circle.lat', 'boundary.circle.lon', 'point.lat', 'point.lon'];
3 |
4 | function isDNT(req) {
5 | if (!req.headers) {
6 | return false;
7 | }
8 | return req.headers.DNT || req.headers.dnt || req.headers.do_not_track;
9 | }
10 |
11 | function removeFields(query) {
12 | fieldsToRemove.forEach(function(field) {
13 | if (query[field]) {
14 | query[field] = '[removed]';
15 | }
16 | });
17 |
18 | return query;
19 | }
20 |
21 | module.exports = {
22 | isDNT: isDNT,
23 | removeFields: removeFields
24 | };
25 |
--------------------------------------------------------------------------------
/helper/placeTypes.js:
--------------------------------------------------------------------------------
1 | // a list of administrative placetypes
2 | // TODO: turn this into configuration (https://github.com/pelias/api/issues/1161)
3 | module.exports = [
4 | 'ocean',
5 | 'marinearea',
6 | 'continent',
7 | 'empire',
8 | 'country',
9 | 'dependency',
10 | 'macroregion',
11 | 'region',
12 | 'macrocounty',
13 | 'county',
14 | 'localadmin',
15 | 'locality',
16 | 'borough',
17 | 'neighbourhood',
18 | 'postalcode'
19 | ];
20 |
--------------------------------------------------------------------------------
/helper/stackTraceLine.js:
--------------------------------------------------------------------------------
1 | module.exports = () => {
2 | const stack = new Error().stack.split('\n');
3 | let targetLine;
4 |
5 | stack.forEach((line) => {
6 | if(line.indexOf('at controller') !== -1) {
7 | targetLine = line.trim();
8 | }
9 | });
10 | return targetLine;
11 | };
12 |
--------------------------------------------------------------------------------
/helper/type_mapping.js:
--------------------------------------------------------------------------------
1 | const TypeMapping = require('./TypeMapping');
2 |
3 | // instantiate a singleton type mapping
4 | // loading normal defaults from pelias-config happens now
5 | // updating that config from Elasticsearch happens later
6 | // before the webserver is started
7 | var tm = new TypeMapping();
8 | tm.loadFromConfig();
9 |
10 | // export singleton
11 | module.exports = tm;
12 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const logger = require('pelias-logger').get('api');
2 | const type_mapping = require('./helper/type_mapping');
3 |
4 | const app = require('./app'),
5 | port = ( process.env.PORT || 3100 ),
6 | host = ( process.env.HOST || undefined );
7 |
8 | let server;
9 |
10 | // load Elasticsearch type mappings before starting web server
11 | type_mapping.load(() => {
12 | server = app.listen( port, host, () => {
13 | // ask server for the actual address and port its listening on
14 | const listenAddress = server.address();
15 | logger.info( `pelias is now running on http://${listenAddress.address}:${listenAddress.port}` );
16 | });
17 | });
18 |
19 | function exitHandler() {
20 | logger.info('Pelias API shutting down');
21 |
22 | server.close();
23 | }
24 |
25 | process.on('SIGINT', exitHandler);
26 | process.on('SIGTERM', exitHandler);
27 |
--------------------------------------------------------------------------------
/middleware/404.js:
--------------------------------------------------------------------------------
1 | // handle not found errors
2 | function middleware(req, res) {
3 | res.header('Cache-Control','public');
4 | res.status(404).json({ error: 'not found: invalid path' });
5 | }
6 |
7 | module.exports = middleware;
8 |
--------------------------------------------------------------------------------
/middleware/500.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const logger = require('pelias-logger').get('api');
3 |
4 | // handle application errors
5 | function middleware(err, req, res) {
6 |
7 | logger.error( 'Error: `%s`. Stack trace: `%s`.', err, err.stack );
8 |
9 | if( res.statusCode < 400 ){
10 | logger.info( 'status code changed from', res.statusCode, 'to 500' );
11 | res.status(500);
12 | }
13 |
14 | // set error message
15 | const error = (err && err.message) ? err.message : err;
16 | let msg = 'internal server error';
17 | if (_.isString(error) && !_.isEmpty(error)) {
18 | msg = error;
19 | }
20 |
21 | // send response
22 | res.header('Cache-Control','public');
23 | res.json({ error: msg });
24 | }
25 |
26 | module.exports = middleware;
27 |
--------------------------------------------------------------------------------
/middleware/applyOverrides.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const logger = require('pelias-logger').get('api');
3 | const codec = require('pelias-model').codec;
4 |
5 | function setup() {
6 | return applyOverrides;
7 | }
8 |
9 | function applyOverrides(req, res, next) {
10 | // do nothing if no result data set
11 | if (!res || !res.data) {
12 | return next();
13 | }
14 |
15 | res.data = res.data.map(overrideOneRecord);
16 |
17 | next();
18 | }
19 |
20 | /*
21 | * Rename the fields in one record
22 | */
23 | function overrideOneRecord(place) {
24 | if (_.has(place, 'addendum.override')) {
25 | try {
26 | const overrideData = codec.decode(place.addendum.override);
27 | place = _.merge(place, overrideData);
28 | } catch (err) {
29 | logger.error('Invalid addendum override json string:', place.addendum);
30 | }
31 |
32 | delete place.addendum.override;
33 |
34 | if (_.isEmpty(place.addendum)) {
35 | delete place.addendum;
36 | }
37 | }
38 | return place;
39 | }
40 |
41 | module.exports = setup;
42 |
--------------------------------------------------------------------------------
/middleware/assignLabels.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 |
3 | const defaultLabelGenerator = require('pelias-labels');
4 |
5 | function setup(labelGenerator) {
6 | function middleware(req, res, next) {
7 | return assignLabel(req, res, next, labelGenerator || defaultLabelGenerator);
8 | }
9 |
10 | return middleware;
11 | }
12 |
13 | function assignLabel(req, res, next, labelGenerator) {
14 |
15 | // do nothing if there's nothing to process
16 | if (!res || !res.data) {
17 | return next();
18 | }
19 |
20 | res.data.forEach(function (result) {
21 | result.label = labelGenerator(result, _.get(req, 'clean.lang.iso6393'));
22 | });
23 |
24 | next();
25 | }
26 |
27 | module.exports = setup;
28 |
--------------------------------------------------------------------------------
/middleware/cors.js:
--------------------------------------------------------------------------------
1 | function middleware(req, res, next){
2 | res.header('Access-Control-Allow-Origin', '*');
3 | res.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
4 | res.header('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
5 | next();
6 | }
7 |
8 | module.exports = middleware;
9 |
--------------------------------------------------------------------------------
/middleware/distance.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const geolib = require('geolib');
3 |
4 | function setup(prefix) {
5 | return function (req, res, next) {
6 | const opts = {
7 | prefix: prefix || 'point.'
8 | };
9 | return computeDistances(req, res, next, opts);
10 | };
11 | }
12 |
13 | function computeDistances(req, res, next, opts) {
14 |
15 | // do nothing if no result data set
16 | if (!res || !res.data) {
17 | return next();
18 | }
19 |
20 | if (!(_.isFinite(req.clean[opts.prefix + 'lat']) &&
21 | _.isFinite(req.clean[opts.prefix + 'lon']))) {
22 | return next();
23 | }
24 |
25 | var point = {
26 | latitude: req.clean[opts.prefix + 'lat'],
27 | longitude: req.clean[opts.prefix + 'lon']
28 | };
29 |
30 | res.data.forEach(function (place) {
31 | // the result of getDistance is in meters, so convert to kilometers
32 | place.distance = geolib.getDistance(
33 | point,
34 | { latitude: place.center_point.lat, longitude: place.center_point.lon }
35 | ) / 1000;
36 | });
37 |
38 | next();
39 | }
40 |
41 |
42 | module.exports = setup;
43 |
--------------------------------------------------------------------------------
/middleware/headers.js:
--------------------------------------------------------------------------------
1 | var pkg = require('../package');
2 |
3 | function middleware(req, res, next){
4 | res.header('Charset','utf8');
5 | res.header('Cache-Control','public');
6 | res.header('Server', 'Pelias/'+pkg.version);
7 | res.header('X-Powered-By', 'pelias');
8 | next();
9 | }
10 |
11 | module.exports = middleware;
12 |
--------------------------------------------------------------------------------
/middleware/jsonp.js:
--------------------------------------------------------------------------------
1 | function middleware(req, res, next){
2 |
3 | // store old json function
4 | var json = res.json.bind(res);
5 |
6 | // replace with jsonp aware function
7 | res.json = function( data ){
8 |
9 | // jsonp
10 | if( req.query && req.query.callback ){
11 | res.header('Content-type','application/javascript');
12 | return res.send( req.query.callback + '('+ JSON.stringify( data ) + ');' );
13 | }
14 |
15 | // regular json
16 | res.header('Content-type','application/json');
17 | return json( data );
18 | };
19 |
20 | next();
21 | }
22 |
23 | module.exports = middleware;
--------------------------------------------------------------------------------
/middleware/options.js:
--------------------------------------------------------------------------------
1 | /**
2 | this functionality is required by CORS as the browser will send an
3 | HTTP OPTIONS request before performing the CORS request.
4 |
5 | if the OPTIONS request returns a non-200 status code then the
6 | transaction will fail.
7 | **/
8 |
9 | function middleware(req, res, next){
10 | if( req.method === 'OPTIONS' ){
11 | res.sendStatus(200);
12 | } else {
13 | next();
14 | }
15 | }
16 |
17 | module.exports = middleware;
18 |
--------------------------------------------------------------------------------
/middleware/parseBBox.js:
--------------------------------------------------------------------------------
1 | var logger = require('pelias-logger').get('api');
2 |
3 | /**
4 | * Parses the bounding box property in docs, if one is found
5 | */
6 |
7 | function setup() {
8 | return function (req, res, next) {
9 | // do nothing if no result data set
10 | if (!res || !res.data) {
11 | return next();
12 | }
13 |
14 | res.data = res.data.map(parseBBox);
15 |
16 | next();
17 | };
18 | }
19 |
20 | /*
21 | * Parse the bbox property and form an object
22 | */
23 | function parseBBox(place) {
24 |
25 | if (place && place.bounding_box) {
26 | try {
27 | place.bounding_box = JSON.parse(place.bounding_box);
28 | }
29 | catch (err) {
30 | logger.error('Invalid bounding_box json string:', place);
31 | delete place.bounding_box;
32 | }
33 | }
34 |
35 | return place;
36 | }
37 |
38 | module.exports = setup;
39 |
--------------------------------------------------------------------------------
/middleware/robots.js:
--------------------------------------------------------------------------------
1 | // Prevent search engines from attempting to index the API
2 | // https://developers.google.com/search/reference/robots_meta_tag#xrobotstag
3 |
4 | function middleware(req, res, next) {
5 | res.header('X-Robots-Tag', 'none');
6 | next();
7 | }
8 |
9 | module.exports = middleware;
--------------------------------------------------------------------------------
/middleware/sizeCalculator.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 |
3 | var SIZE_PADDING = 2;
4 |
5 | var DEFAULT_MIN_QUERY_SIZE = 20;
6 |
7 | /**
8 | * Utility for calculating query result size
9 | * incorporating padding for dedupe process
10 | */
11 | function setup(min_size) {
12 | if (min_size === undefined) {
13 | min_size = DEFAULT_MIN_QUERY_SIZE;
14 | }
15 |
16 | return function setQuerySize(req, res, next) {
17 | if (_.isUndefined(req.clean) || _.isUndefined(req.clean.size)) {
18 | return next();
19 | }
20 |
21 | req.clean.querySize = calculateSize(req.clean.size, min_size);
22 | next();
23 | };
24 | }
25 |
26 | /**
27 | * Add padding or set to 1
28 | *
29 | * @param {number} cleanSize
30 | * @returns {number}
31 | */
32 | function calculateSize(cleanSize, min_size) {
33 | return Math.max(min_size, cleanSize * SIZE_PADDING);
34 | }
35 |
36 | module.exports = setup;
37 |
--------------------------------------------------------------------------------
/middleware/sortResponseData.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const logger = require('pelias-logger').get('api');
3 |
4 | function setup(comparator, should_execute) {
5 | function middleware(req, res, next) {
6 | // bail early if req/res don't pass conditions for execution or there's no data to sort
7 | if (!should_execute(req, res) || _.isEmpty(res.data)) {
8 | return next();
9 | }
10 |
11 | // capture the pre-sort order
12 | const presort_order = res.data.map(_.property('_id'));
13 |
14 | // stable operates on array in place
15 | res.data.sort(comparator(req.clean));
16 |
17 | // capture the post-sort order
18 | const postsort_order = res.data.map(_.property('_id'));
19 |
20 | // log it for debugging purposes
21 | logger.debug([
22 | `req.clean: ${JSON.stringify(req.clean)}`,
23 | `pre-sort: [${presort_order}]`,
24 | `post-sort: [${postsort_order}]`
25 | ].join(', '));
26 |
27 | next();
28 | }
29 |
30 | return middleware;
31 |
32 | }
33 |
34 | module.exports = setup;
35 |
--------------------------------------------------------------------------------
/public/apiDoc.md:
--------------------------------------------------------------------------------
1 | # Pelias API
2 | ### Version: [1.0](https://github.com/pelias/api/releases)
3 |
4 | ## [View our documentation on GitHub](https://github.com/pelias/documentation/)
5 |
--------------------------------------------------------------------------------
/public/attribution.md:
--------------------------------------------------------------------------------
1 | # Pelias API
2 | ### Version: [1.0](https://github.com/pelias/api/releases)
3 |
4 | ## Attribution
5 | * Geocoding by [Pelias](https://pelias.io).
6 | * Data from
7 | * [OpenStreetMap](http://www.openstreetmap.org/copyright) © OpenStreetMap contributors under [ODbL](http://opendatacommons.org/licenses/odbl/). Also see the [OSM Geocoding Guidelines](https://wiki.osmfoundation.org/wiki/Licence/Community_Guidelines/Geocoding_-_Guideline) for acceptable use.
8 | * [OpenAddresses](http://openaddresses.io) under [various public-domain and share-alike licenses](http://results.openaddresses.io/)
9 | * [GeoNames](http://www.geonames.org/) under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/)
10 | * [WhosOnFirst](https://www.whosonfirst.org/) under [various CC-BY or CC-0 equivalent licenses](https://whosonfirst.org/docs/licenses/)
11 |
--------------------------------------------------------------------------------
/query/view/focus_point_distance_filter.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const type_mapping = require('../../helper/type_mapping');
3 |
4 | module.exports = function( vs ) {
5 |
6 | if ( !vs.isset('input:name') ||
7 | !vs.isset('centroid:field') ||
8 | !vs.isset('focus:point:lat') ||
9 | !vs.isset('focus:point:lon') ) {
10 | return null;
11 | }
12 |
13 | const text_length = vs.var('input:name').get().length;
14 |
15 | if (text_length > 8) {
16 | return null;
17 | }
18 |
19 | const all_layers_except_address_and_street = _.without(type_mapping.layers, 'address', 'street');
20 |
21 | const length_to_distance_mapping = {
22 | 1: '100km',
23 | 2: '200km',
24 | 3: '400km',
25 | 4: '600km',
26 | 5: '900km',
27 | 6: '1200km',
28 | 7: '1600km',
29 | 8: '2000km'
30 | };
31 |
32 | const query = {
33 | bool: {
34 | minimum_should_match: 1,
35 | should: [{
36 | terms: {
37 | layer: all_layers_except_address_and_street
38 | }
39 | },{
40 | geo_distance: {
41 | distance: length_to_distance_mapping[text_length],
42 | distance_type: 'plane',
43 | [vs.var('centroid:field')]: {
44 | lat: vs.var('focus:point:lat'),
45 | lon: vs.var('focus:point:lon')
46 | }
47 | }
48 | }]
49 | }
50 | };
51 |
52 | return query;
53 | };
54 |
--------------------------------------------------------------------------------
/query/view/helper.js:
--------------------------------------------------------------------------------
1 | function toMultiFields(baseField, suffix) {
2 | return [baseField, toSingleField(baseField, suffix)];
3 | }
4 |
5 | function toSingleField(baseField, suffix) {
6 | // baseField looks like phrase.default or name.default; suffix looks like en, fr....
7 | const parts = baseField.split('.');
8 | parts[parts.length - 1] = suffix;
9 | return parts.join('.');
10 | }
11 |
12 | module.exports = { toMultiFields, toSingleField };
--------------------------------------------------------------------------------
/query/view/ngrams_last_token_only.js:
--------------------------------------------------------------------------------
1 | var peliasQuery = require('pelias-query'),
2 | ngrams_strict = require('./ngrams_strict');
3 | /**
4 | Ngrams view which trims the 'input:name' and only uses the LAST TOKEN.
5 |
6 | eg. if the input was "100 foo str", then 'input:name' would only be 'str'
7 | note: it is assumed that the rest of the input is matched using another view.
8 |
9 | code notes: this view makes a copy of the $vs object in order to change their
10 | values without mutating the original values, which may be expected in their
11 | unaltered form by other views.
12 | **/
13 |
14 | module.exports = function( vs ){
15 |
16 | // get a copy of the *tokens_incomplete* tokens produced from the input:name
17 | var tokens = vs.var('input:name:tokens_incomplete').get();
18 |
19 | // no valid tokens to use, fail now, don't render this view.
20 | if( !tokens || tokens.length < 1 ){ return null; }
21 |
22 | // make a copy Vars so we don't mutate the original
23 | var vsCopy = new peliasQuery.Vars( vs.export() );
24 |
25 | // set the 'name' variable in the copy to only the last token
26 | vsCopy.var('input:name').set( tokens.join(' ') );
27 |
28 | // return the view rendered using the copy
29 | return {
30 | 'constant_score': {
31 | 'filter': ngrams_strict( vsCopy )
32 | }
33 | };
34 | };
35 |
--------------------------------------------------------------------------------
/query/view/ngrams_strict.js:
--------------------------------------------------------------------------------
1 | const peliasQuery = require('pelias-query');
2 | const toMultiFields = require('./helper').toMultiFields;
3 |
4 | /**
5 | Ngrams view with the additional properties to enable:
6 | type:phrase -> tokens MUST appear in the same order in BOTH query and index
7 | operator:and -> ALL tokens are mandatory, missing any single token will cause
8 | a query failure.
9 | **/
10 |
11 | module.exports = function( vs ){
12 |
13 | // validate required params
14 | if( !vs.isset('phrase:slop') ){
15 | return null;
16 | }
17 |
18 | vs.var('multi_match:ngrams_strict:input', vs.var('input:name').get());
19 | vs.var('multi_match:ngrams_strict:fields', toMultiFields(vs.var('ngram:field').get(), vs.var('lang').get()));
20 |
21 | vs.var('multi_match:ngrams_strict:analyzer', vs.var('ngram:analyzer').get());
22 | vs.var('multi_match:ngrams_strict:slop', vs.var('phrase:slop').get());
23 | vs.var('multi_match:ngrams_strict:boost', vs.var('ngram:boost').get());
24 |
25 | return peliasQuery.view.leaf.multi_match('ngrams_strict')(vs);
26 | };
27 |
--------------------------------------------------------------------------------
/query/view/phrase_first_tokens_only.js:
--------------------------------------------------------------------------------
1 | const peliasQuery = require('pelias-query');
2 | const toMultiFields = require('./helper').toMultiFields;
3 |
4 | /**
5 | Phrase view which trims the 'input:name' and uses ALL BUT the last token.
6 |
7 | eg. if the input was "100 foo str", then 'input:name' would only be '100 foo'
8 | note: it is assumed that the rest of the input is matched using another view.
9 | **/
10 |
11 | module.exports = function( vs ){
12 | const view_name = 'first_tokens_only';
13 | // get a copy of the *complete* tokens produced from the input:name
14 | const tokens = vs.var('input:name:tokens_complete').get();
15 |
16 | // no valid tokens to use, fail now, don't render this view.
17 | if( !tokens || tokens.length < 1 ){ return null; }
18 |
19 | // set the 'input' variable to all but the last token
20 | vs.var(`multi_match:${view_name}:input`).set( tokens.join(' ') );
21 | vs.var(`multi_match:${view_name}:fields`).set(toMultiFields(vs.var('phrase:field').get(), vs.var('lang').get()));
22 |
23 | vs.var(`multi_match:${view_name}:analyzer`).set(vs.var('phrase:analyzer').get());
24 | vs.var(`multi_match:${view_name}:boost`).set(vs.var('phrase:boost').get());
25 | vs.var(`multi_match:${view_name}:slop`).set(vs.var('phrase:slop').get());
26 |
27 | return peliasQuery.view.leaf.multi_match(view_name)( vs );
28 | };
29 |
--------------------------------------------------------------------------------
/routes/default.js:
--------------------------------------------------------------------------------
1 | // set up routes that are outside any particular API version
2 | function addRoutes(app) {
3 | function redirectToV1(req, res, next) {
4 | res.redirect(301, '/v1');
5 | }
6 |
7 | // default root URL traffic to V1 root
8 | // which has a link to the readme and other helpful info
9 | app.get('/', redirectToV1);
10 | }
11 |
12 | module.exports.addRoutes = addRoutes;
13 |
--------------------------------------------------------------------------------
/sanitizer/PeliasParameterError.js:
--------------------------------------------------------------------------------
1 | class PeliasParameterError extends Error {
2 | constructor(message = '') {
3 | super(message);
4 | }
5 |
6 | toString() {
7 | return this.message;
8 | }
9 |
10 | toJSON() {
11 | return this.message;
12 | }
13 | }
14 |
15 | module.exports = PeliasParameterError;
16 |
--------------------------------------------------------------------------------
/sanitizer/PeliasServiceError.js:
--------------------------------------------------------------------------------
1 | class PeliasServiceError extends Error {
2 | constructor(message = '') {
3 | super(message);
4 | }
5 |
6 | toString() {
7 | return this.message;
8 | }
9 |
10 | toJSON() {
11 | return this.message;
12 | }
13 | }
14 |
15 | module.exports = PeliasServiceError;
16 |
--------------------------------------------------------------------------------
/sanitizer/PeliasTimeoutError.js:
--------------------------------------------------------------------------------
1 | // Error subclass for timeouts contacting Pelias services
2 | class PeliasTimeoutError extends Error {
3 | constructor(message = '') {
4 | super(message);
5 | }
6 |
7 | toString() {
8 | return this.message;
9 | }
10 |
11 | toJSON() {
12 | return this.message;
13 | }
14 | }
15 |
16 | module.exports = PeliasTimeoutError;
17 |
--------------------------------------------------------------------------------
/sanitizer/_boundary_gid.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 |
3 | function _sanitize(raw, clean) {
4 | // error & warning messages
5 | var messages = { errors: [], warnings: [] };
6 |
7 | // target input param
8 | var boundary_gid = raw['boundary.gid'];
9 |
10 | // param 'boundary.gid' is optional and should not
11 | // error when simply not set by the user
12 | // must be valid string
13 | if (!_.isNil(boundary_gid)) {
14 | if (!_.isString(boundary_gid) || _.isEmpty(boundary_gid)) {
15 | messages.errors.push('boundary.gid is not a string');
16 | }
17 | else {
18 | // boundary gid should take the form of source:layer:id,
19 | // or source:layer:type:id for OpenStreetMap ids
20 | var fields = boundary_gid.split(':').filter(function(x) {
21 | // keep only non-empty values
22 | return x !== '';
23 | });
24 | if ( _.inRange(fields.length, 3, 5) ) {
25 | clean['boundary.gid'] = fields.slice(2).join(':');
26 | }
27 | else {
28 | messages.errors.push(boundary_gid + ' does not follow source:layer:id format');
29 | }
30 | }
31 | }
32 |
33 | return messages;
34 | }
35 |
36 | function _expected(){
37 | return [{ name: 'boundary.gid' }];
38 | }
39 |
40 | module.exports = () => ({
41 | sanitize: _sanitize,
42 | expected: _expected
43 | });
44 |
--------------------------------------------------------------------------------
/sanitizer/_geo_autocomplete.js:
--------------------------------------------------------------------------------
1 | var geo_common = require ('./_geo_common');
2 | var LAT_LON_IS_REQUIRED = false;
3 | var RECT_IS_REQUIRED = false;
4 | var CIRCLE_IS_REQUIRED = false;
5 |
6 | // validate inputs, convert types and apply defaults
7 | function _sanitize( raw, clean ){
8 |
9 | // error & warning messages
10 | var messages = { errors: [], warnings: [] };
11 |
12 | try {
13 | geo_common.sanitize_point( 'focus.point', clean, raw, LAT_LON_IS_REQUIRED );
14 | geo_common.sanitize_rect( 'boundary.rect', clean, raw, RECT_IS_REQUIRED );
15 | geo_common.sanitize_circle( 'boundary.circle', clean, raw, CIRCLE_IS_REQUIRED );
16 | }
17 | catch (err) {
18 | messages.errors.push( err.message );
19 | }
20 |
21 | return messages;
22 | }
23 |
24 | function _expected(){
25 | return [
26 | { name: 'focus.point.lat' },
27 | { name: 'focus.point.lon' },
28 | { name: 'boundary.circle.lon'},
29 | { name: 'boundary.circle.lat'},
30 | { name: 'boundary.circle.radius'},
31 | { name: 'boundary.rect.min_lat' },
32 | { name: 'boundary.rect.max_lat' },
33 | { name: 'boundary.rect.min_lon' },
34 | { name: 'boundary.rect.max_lon' }];
35 | }
36 |
37 | module.exports = () => ({
38 | sanitize: _sanitize,
39 | expected: _expected
40 | });
41 |
--------------------------------------------------------------------------------
/sanitizer/_geo_search.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const geo_common = require ('./_geo_common');
3 |
4 | const LAT_LON_IS_REQUIRED = false;
5 | const RECT_IS_REQUIRED = false;
6 | const CIRCLE_IS_REQUIRED = false;
7 |
8 | // validate inputs, convert types and apply defaults
9 | function _sanitize( raw, clean ){
10 |
11 | // error & warning messages
12 | var messages = { errors: [], warnings: [] };
13 |
14 | try {
15 | geo_common.sanitize_point( 'focus.point', clean, raw, LAT_LON_IS_REQUIRED );
16 | geo_common.sanitize_rect( 'boundary.rect', clean, raw, RECT_IS_REQUIRED );
17 | geo_common.sanitize_circle( 'boundary.circle', clean, raw, CIRCLE_IS_REQUIRED );
18 | }
19 | catch (err) {
20 | messages.errors.push( err.message );
21 | }
22 |
23 | return messages;
24 | }
25 |
26 | function _expected(){
27 | return [
28 | { name: 'focus.point.lat' },
29 | { name: 'focus.point.lon' },
30 | { name: 'boundary.circle.lon'},
31 | { name: 'boundary.circle.lat'},
32 | { name: 'boundary.circle.radius'},
33 | { name: 'boundary.rect.min_lat' },
34 | { name: 'boundary.rect.max_lat' },
35 | { name: 'boundary.rect.min_lon' },
36 | { name: 'boundary.rect.max_lon' }];
37 | }
38 |
39 | module.exports = () => ({
40 | sanitize: _sanitize,
41 | expected: _expected
42 | });
43 |
--------------------------------------------------------------------------------
/sanitizer/_geonames_deprecation.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 |
3 | /**
4 | * Now that we have the pip-service, we have stopped supporting returning Geonames for coarse reverse.
5 | *
6 | * However, until the `/nearby` endpoint is finalized, we still want to support Geonames for
7 | * _non-coarse_ reverse.
8 | **/
9 |
10 | const coarse_reverse_message ='coarse /reverse does not support geonames. See https://github.com/pelias/pelias/issues/675 for more info';
11 |
12 | function _sanitize( raw, clean ) {
13 | // error & warning messages
14 | const messages = { errors: [], warnings: [] };
15 |
16 | // return taking no action unless this is a coarse-only reverse request
17 | const non_coarse_layers = ['address', 'street', 'venue'];
18 | const is_coarse_reverse = !_.isEmpty(clean.layers) &&
19 | _.isEmpty(_.intersection(clean.layers, non_coarse_layers));
20 | if (!is_coarse_reverse) {
21 | return messages;
22 | }
23 |
24 | if (_.isEqual(clean.sources, ['geonames']) || _.isEqual(clean.sources, ['gn'])) {
25 | messages.errors.push(coarse_reverse_message);
26 |
27 | } else if (_.includes(clean.sources, 'geonames') || _.includes(clean.sources, 'gn')) {
28 | clean.sources = _.without(clean.sources, 'geonames', 'gn');
29 | messages.warnings.push(coarse_reverse_message);
30 | }
31 |
32 | return messages;
33 |
34 | }
35 |
36 | module.exports = () => ({
37 | sanitize: _sanitize
38 | });
39 |
--------------------------------------------------------------------------------
/sanitizer/_geonames_warnings.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 |
3 | const non_admin_fields = ['housenumber', 'street', 'query', 'category'];
4 |
5 | function hasAnyNonAdminFields(parsed_text) {
6 | return !_.isEmpty(
7 | _.intersection(
8 | _.keys(parsed_text),
9 | non_admin_fields));
10 | }
11 |
12 | function _sanitize( raw, clean ){
13 | // error & warning messages
14 | const messages = { errors: [], warnings: [] };
15 |
16 | // bail early if analysis isn't admin-only
17 | if (_.isUndefined(clean.parsed_text) || hasAnyNonAdminFields(clean.parsed_text)) {
18 | return messages;
19 | }
20 |
21 | // the analysis is admin-only, so add errors or warnings if geonames was requested
22 | if (_.isEqual(clean.sources, ['geonames'])) {
23 | // if requested sources is only geonames, return an error
24 | messages.errors.push('input contains only administrative area data, ' +
25 | 'no results will be returned when sources=geonames');
26 |
27 | } else if (_.includes(clean.sources, 'geonames')) {
28 | // if there are other sources besides geonames, return an warning
29 | messages.warnings.push('input contains only administrative area data, ' +
30 | 'geonames results will not be returned');
31 |
32 | }
33 |
34 | return messages;
35 | }
36 |
37 | module.exports = () => ({
38 | sanitize: _sanitize
39 | });
40 |
--------------------------------------------------------------------------------
/sanitizer/_iso2_to_iso3.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const iso3166 = require('../helper/iso3166');
3 |
4 | // this sanitizer exists solely to convert an ISO2 country value to ISO3
5 | // eg - 'TH' -> 'THA'
6 | // this can go away once altnames imports ISO2 country values from WOF
7 | function _sanitize( raw, clean ){
8 | // error & warning messages
9 | const messages = { errors: [], warnings: [] };
10 |
11 | if (clean.hasOwnProperty('parsed_text') && iso3166.isISO2Code(clean.parsed_text.country)) {
12 | clean.parsed_text.country = iso3166.convertISO2ToISO3(clean.parsed_text.country);
13 | }
14 |
15 | return messages;
16 | }
17 |
18 | // export function
19 | module.exports = () => ({
20 | sanitize: _sanitize
21 | });
22 |
--------------------------------------------------------------------------------
/sanitizer/_request_language.js:
--------------------------------------------------------------------------------
1 | // this sanitizer exists solely to allow `lang` as a request parameter
2 | function _sanitize( raw, clean ){
3 | // error & warning messages
4 | return { errors: [], warnings: [] };
5 | }
6 |
7 | function _expected(){
8 | return [{ 'name': 'lang' }];
9 | }
10 |
11 | // export function
12 | module.exports = () => ({
13 | sanitize: _sanitize,
14 | expected: _expected
15 | });
16 |
--------------------------------------------------------------------------------
/sanitizer/_single_scalar_parameters.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 |
3 | // validate inputs
4 | function _sanitize( raw, clean ){
5 | // error & warning messages
6 | var messages = { errors: [], warnings: [] };
7 |
8 | Object.keys(raw).forEach(key => {
9 | if (_.isArray(raw[key])) {
10 | messages.errors.push('\'' + key + '\' parameter can only have one value');
11 | delete raw[key];
12 | } else if (_.isObject(raw[key])) {
13 | messages.errors.push('\'' + key + '\' parameter must be a scalar');
14 | delete raw[key];
15 | }
16 | });
17 |
18 | return messages;
19 | }
20 |
21 | // export function
22 | module.exports = () => ({
23 | sanitize: _sanitize
24 | });
25 |
--------------------------------------------------------------------------------
/sanitizer/_text.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash');
2 | const unicode = require('../helper/unicode');
3 | const MAX_TEXT_LENGTH = 140;
4 |
5 | // ref: https://en.wikipedia.org/wiki/Quotation_mark
6 | const QUOTES = `"'«»‘’‚‛“”„‟‹›⹂「」『』〝〞〟﹁﹂﹃﹄"'「」`;
7 |
8 | // validate texts, convert types and apply defaults
9 | function _sanitize( raw, clean ){
10 |
11 | // error & warning messages
12 | const messages = { errors: [], warnings: [] };
13 |
14 | // normalize unicode marks
15 | let text = unicode.normalize(raw.text);
16 |
17 | // remove superfluous whitespace and quotes
18 | text = _.trim(_.trim(text), QUOTES);
19 |
20 | // validate input 'text'
21 | if( !_.isString(text) || _.isEmpty(text) ){
22 | messages.errors.push(`invalid param 'text': text length, must be >0`);
23 | } else {
24 | if( text.length > MAX_TEXT_LENGTH ){
25 | messages.warnings.push(`param 'text' truncated to ${MAX_TEXT_LENGTH} characters`);
26 | text = text.substring(0, MAX_TEXT_LENGTH);
27 | }
28 | clean.text = text;
29 | }
30 |
31 | return messages;
32 | }
33 |
34 | function _expected(){
35 | return [{ name: 'text' }];
36 | }
37 | // export function
38 | module.exports = () => ({
39 | sanitize: _sanitize,
40 | expected: _expected
41 | });
42 |
--------------------------------------------------------------------------------
/sanitizer/place.js:
--------------------------------------------------------------------------------
1 | var sanitizeAll = require('../sanitizer/sanitizeAll');
2 |
3 | /**
4 | * a list of query-string parameters groups for this endpoint
5 | * which will be replaced with default values if unset.
6 | *
7 | * note: all parameters in each group MUST be unset in the req
8 | * and a replacement available in the defaults for them to be replaced.
9 | *
10 | * the idea being that it makes sense for some parameters to be
11 | * treated as a cohesive group (such as lat/lon pairs), if one or
12 | * the other is missing then we don't make modifications.
13 | */
14 | const paramGroups = [
15 | ['gid'],
16 | ['categories']
17 | ];
18 |
19 | module.exports.middleware = (_api_pelias_config) => {
20 | var sanitizers = {
21 | defaultParameters: require('../sanitizer/_default_parameters')(_api_pelias_config.defaultParameters, paramGroups),
22 | singleScalarParameters: require('../sanitizer/_single_scalar_parameters')(),
23 | debug: require('../sanitizer/_debug')(_api_pelias_config.exposeInternalDebugTools),
24 | ids: require('../sanitizer/_ids')(),
25 | private: require('../sanitizer/_flag_bool')('private', false),
26 | categories: require('../sanitizer/_categories')(true),
27 | request_language: require('../sanitizer/_request_language')()
28 | };
29 |
30 | return function(req, res, next){
31 | sanitizeAll.runAllChecks(req, sanitizers);
32 | next();
33 | };
34 | };
35 |
--------------------------------------------------------------------------------
/sanitizer/wrap.js:
--------------------------------------------------------------------------------
1 | /**
2 | normalize co-ordinates that lie outside of the normal ranges.
3 |
4 | longitude wrapping simply requires adding +- 360 to the value until it comes
5 | in to range.
6 |
7 | for the latitude values we need to flip the longitude whenever the latitude
8 | crosses a pole.
9 | **/
10 |
11 |
12 | function wrap( lat, lon ){
13 |
14 | var point = { lat: lat, lon: lon };
15 | var quadrant = Math.floor( Math.abs(lat) / 90) % 4;
16 | var pole = ( lat > 0 ) ? 90 : -90;
17 | var offset = lat % 90;
18 |
19 | switch( quadrant ){
20 | case 0:
21 | point.lat = offset;
22 | break;
23 | case 1:
24 | point.lat = pole - offset;
25 | point.lon += 180;
26 | break;
27 | case 2:
28 | point.lat = -offset;
29 | point.lon += 180;
30 | break;
31 | case 3:
32 | point.lat = -pole + offset;
33 | break;
34 | }
35 |
36 | if( point.lon > 180 || point.lon <= -180 ){
37 | point.lon -= Math.floor(( point.lon + 180 ) / 360) * 360;
38 | }
39 |
40 | return point;
41 | }
42 |
43 | module.exports = wrap;
44 |
--------------------------------------------------------------------------------
/service/configurations/Language.js:
--------------------------------------------------------------------------------
1 | const url = require('url');
2 |
3 | const _ = require('lodash');
4 |
5 | const ServiceConfiguration = require('pelias-microservice-wrapper').ServiceConfiguration;
6 |
7 | class Language extends ServiceConfiguration {
8 | constructor(o) {
9 | super('language', o);
10 | }
11 |
12 | getParameters(req, res) {
13 | // find all the values for all keys with names that end with '_id'
14 | const ids = _.get(res, 'data', []).reduce((acc, doc) => {
15 | Array.prototype.push.apply(acc, _.values(_.pickBy(doc.parent, (v, k) => _.endsWith(k, '_id') ) ) );
16 | return acc;
17 | }, []);
18 | const lang = _.get(req, 'clean.lang.iso6393');
19 | const parameters = {
20 | // arrays will be nested, so flatten first, then uniqify, and finally join elements with comma
21 | ids: _.uniq(_.flattenDeep(ids)).join(',')
22 | };
23 |
24 | if (lang) {
25 | parameters.lang = lang;
26 | }
27 |
28 | return parameters;
29 |
30 | }
31 |
32 | getUrl(req) {
33 | return url.resolve(this.baseUrl, 'parser/findbyid');
34 | }
35 |
36 | }
37 |
38 | module.exports = Language;
39 |
--------------------------------------------------------------------------------
/service/configurations/Libpostal.js:
--------------------------------------------------------------------------------
1 | const url = require('url');
2 |
3 | const ServiceConfiguration = require('pelias-microservice-wrapper').ServiceConfiguration;
4 |
5 | class Libpostal extends ServiceConfiguration {
6 | constructor(o, propertyExtractor) {
7 | super('libpostal', o);
8 |
9 | // save off the propertyExtractor function
10 | // this is used to extract a single property from req. eg:
11 | // * _.property('clean.text')
12 | // * _.property('clean.parsed_text.address')
13 | // will return those properties from req
14 | this.propertyExtractor = propertyExtractor;
15 |
16 | }
17 |
18 | getParameters(req) {
19 | return {
20 | address: this.propertyExtractor(req)
21 | };
22 |
23 | }
24 |
25 | getUrl(req) {
26 | return url.resolve(this.baseUrl, 'parse');
27 | }
28 |
29 | }
30 |
31 | module.exports = Libpostal;
32 |
--------------------------------------------------------------------------------
/service/configurations/PlaceHolder.js:
--------------------------------------------------------------------------------
1 | const url = require('url');
2 |
3 | const _ = require('lodash');
4 |
5 | const ServiceConfiguration = require('pelias-microservice-wrapper').ServiceConfiguration;
6 |
7 | class PlaceHolder extends ServiceConfiguration {
8 | constructor(o) {
9 | super('placeholder', o);
10 | }
11 |
12 | getParameters(req) {
13 | const parameters = {};
14 |
15 | if (_.has(req.clean.parsed_text, 'street')) {
16 | // assemble all these fields into a space-delimited string
17 | parameters.text = _.values(_.pick(req.clean.parsed_text,
18 | ['neighbourhood', 'borough', 'city', 'county', 'state', 'country'])).join(' ');
19 |
20 | } else {
21 | parameters.text = req.clean.text;
22 |
23 | }
24 |
25 | if (_.has(req.clean, 'lang.iso6393')) {
26 | parameters.lang = req.clean.lang.iso6393;
27 | }
28 |
29 | return parameters;
30 | }
31 |
32 | getUrl(req) {
33 | return url.resolve(this.baseUrl, 'parser/search');
34 | }
35 |
36 | }
37 |
38 | module.exports = PlaceHolder;
39 |
--------------------------------------------------------------------------------
/service/configurations/PointInPolygon.js:
--------------------------------------------------------------------------------
1 | const url = require('url');
2 |
3 | const _ = require('lodash');
4 |
5 | const ServiceConfiguration = require('pelias-microservice-wrapper').ServiceConfiguration;
6 |
7 | class PointInPolygon extends ServiceConfiguration {
8 | constructor(o) {
9 | super('pip', o);
10 | }
11 |
12 | getParameters(req) {
13 | if (_.has(req, 'clean.layers')) {
14 | return {
15 | layers: _.join(req.clean.layers, ',')
16 | };
17 | }
18 |
19 | return {};
20 | }
21 |
22 | getUrl(req) {
23 | // use resolve to eliminate possibility of duplicate /'s in URL
24 | return url.resolve(this.baseUrl, `${req.clean['point.lon']}/${req.clean['point.lat']}`);
25 | }
26 |
27 | }
28 |
29 | module.exports = PointInPolygon;
30 |
--------------------------------------------------------------------------------
/service/mget.js:
--------------------------------------------------------------------------------
1 | var logger = require( 'pelias-logger' ).get( 'api' );
2 |
3 | function service( esclient, query, cb ){
4 |
5 | // elasticsearch command
6 | var cmd = {
7 | body: {
8 | docs: query
9 | }
10 | };
11 |
12 | // query elasticsearch
13 | const startTime = new Date();
14 | esclient.mget( cmd, function( err, data ){
15 | if (data) {
16 | data.response_time = new Date() - startTime;
17 | }
18 |
19 | // handle elasticsearch errors
20 | if( err ){
21 | logger.error( `elasticsearch error ${err}`);
22 | return cb( err );
23 | }
24 |
25 | // map returned documents
26 | var docs = [];
27 | if( data && Array.isArray(data.docs) ){
28 |
29 | docs = data.docs.filter( function( doc ){
30 |
31 | // remove docs not actually found
32 | return doc.found;
33 |
34 | }).map( function( doc ){
35 |
36 | // map metadata in to _source so we
37 | // can serve it up to the consumer
38 | doc._source._id = doc._id;
39 |
40 | return doc._source;
41 | });
42 | }
43 |
44 | // fire callback
45 | return cb( null, docs, data );
46 | });
47 |
48 | }
49 |
50 | module.exports = service;
51 |
--------------------------------------------------------------------------------
/test/ciao.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaults": {
3 | "protocol": "http",
4 | "host": "localhost",
5 | "port": 3100
6 | },
7 | "config": {}
8 | }
--------------------------------------------------------------------------------
/test/ciao/404.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> invalid path
3 | path: '/notexist'
4 |
5 | #? not found
6 | response.statusCode.should.be.equal 404
7 |
8 | #? content-type header correctly set
9 | response.should.have.header 'Content-Type','application/json; charset=utf-8'
10 |
11 | #? cache-control header correctly set
12 | response.should.have.header 'Cache-Control','public'
13 |
14 | #? should respond in json with server info
15 | should.exist json
16 | should.exist json.error
17 | json.error.should.be.equal 'not found: invalid path'
--------------------------------------------------------------------------------
/test/ciao/CORS/headers_GET.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> cross-origin resource sharing
3 | path: '/'
4 |
5 | #? access control headers correctly set
6 | response.should.have.header 'Access-Control-Allow-Origin','*'
7 | response.should.have.header 'Access-Control-Allow-Methods','GET, OPTIONS'
8 | response.should.have.header 'Access-Control-Allow-Headers','X-Requested-With,content-type'
9 |
--------------------------------------------------------------------------------
/test/ciao/CORS/headers_OPTIONS.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> cross-origin resource sharing
3 | path: '/'
4 | method: 'OPTIONS'
5 |
6 | #? access control headers correctly set
7 | response.should.have.header 'Access-Control-Allow-Origin','*'
8 | response.should.have.header 'Access-Control-Allow-Methods','GET, OPTIONS'
9 | response.should.have.header 'Access-Control-Allow-Headers','X-Requested-With,content-type'
10 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/boundary_gid_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding gid
3 | path: '/v1/autocomplete?text=a&boundary.gid=abc::'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | json.geocoding.errors.should.eql [
27 | 'abc:: does not follow source:layer:id format'
28 | ]
29 |
30 | #? expected warnings
31 | should.not.exist json.geocoding.warnings
32 |
33 | #? inputs
34 | json.geocoding.query['text'].should.eql 'a'
35 | json.geocoding.query['size'].should.eql 10
36 | should.not.exist json.geocoding.query['boundary.gid']
--------------------------------------------------------------------------------
/test/ciao/autocomplete/boundary_gid_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding gid
3 | path: '/v1/autocomplete?text=a&boundary.gid=whosonfirst:neighbourhood:85869245'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['boundary.gid'].should.eql '85869245'
--------------------------------------------------------------------------------
/test/ciao/autocomplete/boundary_rect_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/autocomplete?text=cairo&boundary.rect.min_lat=30&boundary.rect.max_lat=32&boundary.rect.min_lon=29&boundary.rect.max_lon=31'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'cairo'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['boundary.rect.min_lat'].should.eql 30
35 | json.geocoding.query['boundary.rect.max_lat'].should.eql 32
36 | json.geocoding.query['boundary.rect.min_lon'].should.eql 29
37 | json.geocoding.query['boundary.rect.max_lon'].should.eql 31
38 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/focus_point_invalid_lat.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/autocomplete?text=a&focus.point.lat=foo&focus.point.lon=-73.990342'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'missing param \'focus.point.lat\'' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['focus.point.lat']
36 | should.not.exist json.geocoding.query['focus.point.lon']
37 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/focus_point_invalid_lon.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/autocomplete?text=a&focus.point.lat=40.744243&focus.point.lon='
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'missing param \'focus.point.lon\'' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | json.geocoding.query['focus.point.lat'].should.eql 40.744243
36 | should.not.exist json.geocoding.query['focus.point.lon']
37 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/focus_point_missing_lat.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/autocomplete?text=a&focus.point.lon=-73.990342'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'parameters focus.point.lat and focus.point.lon must both be specified' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['focus.point.lat']
36 | should.not.exist json.geocoding.query['focus.point.lon']
37 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/focus_point_missing_lon.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/autocomplete?text=a&focus.point.lat=40.744243'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'parameters focus.point.lat and focus.point.lon must both be specified' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['focus.point.lat']
36 | should.not.exist json.geocoding.query['focus.point.lon']
37 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/focus_point_null_island.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point null island
3 | path: '/v1/autocomplete?text=a&focus.point.lat=0&focus.point.lon=0'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['focus.point.lat'].should.eql 0
35 | json.geocoding.query['focus.point.lon'].should.eql 0
--------------------------------------------------------------------------------
/test/ciao/autocomplete/focus_point_valid_duo.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/autocomplete?text=a&focus.point.lat=40.744243&focus.point.lon=-73.990342'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['focus.point.lat'].should.eql 40.744243
35 | json.geocoding.query['focus.point.lon'].should.eql -73.990342
--------------------------------------------------------------------------------
/test/ciao/autocomplete/language_default.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/autocomplete?text=example'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | name: 'English',
34 | iso6391: 'en',
35 | iso6393: 'eng',
36 | defaulted: true
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/language_header_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/autocomplete?text=example'
4 | headers: 'Accept-Language': 'example'
5 |
6 | #? 200 ok
7 | response.statusCode.should.be.equal 200
8 | response.should.have.header 'charset', 'utf8'
9 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
10 |
11 | #? valid geocoding block
12 | should.exist json.geocoding
13 | should.exist json.geocoding.version
14 | should.exist json.geocoding.attribution
15 | should.exist json.geocoding.query
16 | should.exist json.geocoding.engine
17 | should.exist json.geocoding.engine.name
18 | should.exist json.geocoding.engine.author
19 | should.exist json.geocoding.engine.version
20 | should.exist json.geocoding.timestamp
21 |
22 | #? valid geojson
23 | json.type.should.be.equal 'FeatureCollection'
24 | json.features.should.be.instanceof Array
25 |
26 | #? expected errors
27 | should.not.exist json.geocoding.errors
28 |
29 | #? expected warnings
30 | json.geocoding.warnings.should.eql [ 'invalid language provided via header' ]
31 |
32 | #? language
33 | json.geocoding.query['lang'].should.eql {
34 | name: 'English',
35 | iso6391: 'en',
36 | iso6393: 'eng',
37 | defaulted: true
38 | }
39 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/language_header_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/autocomplete?text=example'
4 | headers: 'Accept-Language': 'fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5'
5 |
6 | #? 200 ok
7 | response.statusCode.should.be.equal 200
8 | response.should.have.header 'charset', 'utf8'
9 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
10 |
11 | #? valid geocoding block
12 | should.exist json.geocoding
13 | should.exist json.geocoding.version
14 | should.exist json.geocoding.attribution
15 | should.exist json.geocoding.query
16 | should.exist json.geocoding.engine
17 | should.exist json.geocoding.engine.name
18 | should.exist json.geocoding.engine.author
19 | should.exist json.geocoding.engine.version
20 | should.exist json.geocoding.timestamp
21 |
22 | #? valid geojson
23 | json.type.should.be.equal 'FeatureCollection'
24 | json.features.should.be.instanceof Array
25 |
26 | #? expected errors
27 | should.not.exist json.geocoding.errors
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? language
33 | json.geocoding.query['lang'].should.eql {
34 | defaulted: false,
35 | iso6391: 'fr',
36 | iso6393: 'fra',
37 | name: 'French'
38 | }
39 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/language_querystring_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/autocomplete?lang=example&text=example'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | json.geocoding.warnings.should.eql [ 'invalid language provided via querystring' ]
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | name: 'English',
34 | iso6391: 'en',
35 | iso6393: 'eng',
36 | defaulted: true
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/language_querystring_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/autocomplete?lang=fr&text=example'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | defaulted: false,
34 | iso6391: 'fr',
35 | iso6393: 'fra',
36 | name: 'French'
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/layers_alias_address.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/autocomplete?text=a&layers=address'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.layers.should.eql ["address"]
35 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/layers_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/autocomplete?text=a&layers=notlayer'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ '\'notlayer\' is an invalid layers parameter. Valid options: coarse,address,venue,street,country,macroregion,region,county,localadmin,locality,borough,neighbourhood,continent,empire,dependency,macrocounty,macrohood,microhood,disputed,postalcode,ocean,marinearea' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/layers_multiple.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/autocomplete?text=a&layers=country,region'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.layers.should.eql ["country","region"]
35 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/layers_single.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/autocomplete?text=a&layers=country'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.layers.should.eql ["country"]
35 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/no_params.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> no params specified
3 | path: '/v1/autocomplete'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'invalid param \'text\': text length, must be >0' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/non_scalar_parameter_array.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> define two sources
3 | path: '/v1/autocomplete?text=A&sources=A&sources=B'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected warnings
26 | should.not.exist json.geocoding.warnings
27 |
28 | #? expected errors
29 | should.exist json.geocoding.errors
30 | json.geocoding.errors.should.eql [ '\'sources\' parameter can only have one value' ]
31 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/non_scalar_parameter_object.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> define parameter as object
3 | path: '/v1/autocomplete?text=A¶meter[idx]=value'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected warnings
26 | should.not.exist json.geocoding.warnings
27 |
28 | #? expected errors
29 | should.exist json.geocoding.errors
30 | json.geocoding.errors.should.eql [ '\'parameter\' parameter must be a scalar' ]
31 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/size_not_default.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> set size (autocomplete does not allow size to be changed)
3 | path: '/v1/autocomplete?text=a&size=3'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.exist json.geocoding.warnings
30 | json.geocoding.warnings.should.eql [ 'out-of-range integer \'size\', using MIN_SIZE' ]
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10 # should remain the default size
35 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/sources_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources filter
3 | path: '/v1/autocomplete?text=a&sources=openstreetmap,notasource'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ '\'notasource\' is an invalid sources parameter. Valid options: osm,oa,gn,wof,openstreetmap,openaddresses,geonames,whosonfirst' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/sources_layers_valid_combo.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources and layers specified
3 | path: '/v1/autocomplete?text=a&sources=openaddresses&layers=address'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.layers.should.eql ["address"]
35 | json.geocoding.query.sources.should.eql ["openaddresses"]
36 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/sources_multiple.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources filter
3 | path: "/v1/autocomplete?text=a&sources=openstreetmap,geonames"
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header "charset", 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.sources.should.eql ["openstreetmap", "geonames"]
35 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/sources_single.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources filter
3 | path: '/v1/autocomplete?text=a&sources=openstreetmap'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.sources.should.eql ["openstreetmap"]
35 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/text_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> basic autocomplete
3 | path: '/v1/autocomplete?text='
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'invalid param \'text\': text length, must be >0' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | should.not.exist json.geocoding.query['text']
34 | json.geocoding.query['size'].should.eql 10
35 |
--------------------------------------------------------------------------------
/test/ciao/autocomplete/text_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> basic autocomplete
3 | path: '/v1/autocomplete?text=a'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
--------------------------------------------------------------------------------
/test/ciao/index.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> api root
3 | path: '/v1/'
4 |
5 | #? endpoint available
6 | response.statusCode.should.be.equal 200
7 |
8 | #? content-type header correctly set
9 | response.should.have.header 'Content-Type','text/html; charset=utf-8'
10 |
11 | #? charset header correctly set
12 | response.should.have.header 'Charset','utf8'
13 |
14 | #? cache-control header correctly set
15 | response.should.have.header 'Cache-Control','public'
16 |
17 | #? server header correctly set
18 | response.should.have.header 'Server'
19 | response.headers.server.should.match /Pelias\/\d{1,2}\.\d{1,2}\.\d{1,2}/
20 |
21 | #? vanity header correctly set
22 | response.should.have.header 'X-Powered-By','pelias'
23 |
--------------------------------------------------------------------------------
/test/ciao/place/basic_place.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> basic place
3 | path: '/v1/place?ids=geonames:venue:1'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['ids'].should.eql [{ id: '1', layer: 'venue', source: 'geonames' }]
33 | should.not.exist json.geocoding.query['size']
34 |
--------------------------------------------------------------------------------
/test/ciao/place/language_default.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/place?ids=geonames:venue:1'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | name: 'English',
34 | iso6391: 'en',
35 | iso6393: 'eng',
36 | defaulted: true
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/place/language_header_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/place?ids=geonames:venue:1'
4 | headers: 'Accept-Language': 'example'
5 |
6 | #? 200 ok
7 | response.statusCode.should.be.equal 200
8 | response.should.have.header 'charset', 'utf8'
9 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
10 |
11 | #? valid geocoding block
12 | should.exist json.geocoding
13 | should.exist json.geocoding.version
14 | should.exist json.geocoding.attribution
15 | should.exist json.geocoding.query
16 | should.exist json.geocoding.engine
17 | should.exist json.geocoding.engine.name
18 | should.exist json.geocoding.engine.author
19 | should.exist json.geocoding.engine.version
20 | should.exist json.geocoding.timestamp
21 |
22 | #? valid geojson
23 | json.type.should.be.equal 'FeatureCollection'
24 | json.features.should.be.instanceof Array
25 |
26 | #? expected errors
27 | should.not.exist json.geocoding.errors
28 |
29 | #? expected warnings
30 | json.geocoding.warnings.should.eql [ 'invalid language provided via header' ]
31 |
32 | #? language
33 | json.geocoding.query['lang'].should.eql {
34 | name: 'English',
35 | iso6391: 'en',
36 | iso6393: 'eng',
37 | defaulted: true
38 | }
39 |
--------------------------------------------------------------------------------
/test/ciao/place/language_header_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/place?ids=geonames:venue:1'
4 | headers: 'Accept-Language': 'fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5'
5 |
6 | #? 200 ok
7 | response.statusCode.should.be.equal 200
8 | response.should.have.header 'charset', 'utf8'
9 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
10 |
11 | #? valid geocoding block
12 | should.exist json.geocoding
13 | should.exist json.geocoding.version
14 | should.exist json.geocoding.attribution
15 | should.exist json.geocoding.query
16 | should.exist json.geocoding.engine
17 | should.exist json.geocoding.engine.name
18 | should.exist json.geocoding.engine.author
19 | should.exist json.geocoding.engine.version
20 | should.exist json.geocoding.timestamp
21 |
22 | #? valid geojson
23 | json.type.should.be.equal 'FeatureCollection'
24 | json.features.should.be.instanceof Array
25 |
26 | #? expected errors
27 | should.not.exist json.geocoding.errors
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? language
33 | json.geocoding.query['lang'].should.eql {
34 | defaulted: false,
35 | iso6391: 'fr',
36 | iso6393: 'fra',
37 | name: 'French'
38 | }
39 |
--------------------------------------------------------------------------------
/test/ciao/place/language_querystring_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/place?lang=example&ids=geonames:venue:1'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | json.geocoding.warnings.should.eql [ 'invalid language provided via querystring' ]
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | name: 'English',
34 | iso6391: 'en',
35 | iso6393: 'eng',
36 | defaulted: true
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/place/language_querystring_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/place?lang=fr&ids=geonames:venue:1'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | defaulted: false,
34 | iso6391: 'fr',
35 | iso6393: 'fra',
36 | name: 'French'
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/place/missing_id.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> missing id
3 | path: '/v1/place'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'invalid param \'ids\': length must be >0' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | should.not.exist json.geocoding.query['ids']
34 | should.not.exist json.geocoding.query['size']
35 |
--------------------------------------------------------------------------------
/test/ciao/reverse/basic_reverse.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> basic reverse
3 | path: '/v1/reverse?point.lat=1&point.lon=2'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['point.lat'].should.eql 1
33 | json.geocoding.query['point.lon'].should.eql 2
34 | json.geocoding.query['size'].should.eql 10
--------------------------------------------------------------------------------
/test/ciao/reverse/boundary_circle_invalid_radius.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding circle
3 | path: '/v1/reverse?point.lat=40.744243&point.lon=-73.990342&boundary.circle.radius=foo'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'missing param \'boundary.circle.radius\'' ]
28 |
29 | #? inputs
30 | # json.geocoding.query['size'].should.eql 10
31 | json.geocoding.query['point.lat'].should.eql 40.744243
32 | json.geocoding.query['point.lon'].should.eql -73.990342
33 | should.not.exist json.geocoding.query['boundary.circle.radius']
34 | should.not.exist json.geocoding.query['boundary.circle.lat']
35 | should.not.exist json.geocoding.query['boundary.circle.lon']
36 |
--------------------------------------------------------------------------------
/test/ciao/reverse/boundary_circle_valid_radius.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding circle
3 | path: '/v1/reverse?point.lat=40.744243&point.lon=-73.990342&boundary.circle.radius=999.9'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | # expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query['point.lat'].should.eql 40.744243
34 | json.geocoding.query['point.lon'].should.eql -73.990342
35 | json.geocoding.query['boundary.circle.lat'].should.eql 40.744243
36 | json.geocoding.query['boundary.circle.lon'].should.eql -73.990342
37 | json.geocoding.query['boundary.circle.radius'].should.eql 999.9
38 |
--------------------------------------------------------------------------------
/test/ciao/reverse/boundary_country_invalid_alpha2.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding country
3 | path: '/v1/reverse?point.lat=1&point.lon=1&boundary.country=ZZ'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'ZZ is not a valid ISO2/ISO3 country code' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 | should.not.exist json.geocoding.query['boundary.country']
35 |
--------------------------------------------------------------------------------
/test/ciao/reverse/boundary_country_invalid_alpha3.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding country
3 | path: '/v1/reverse?point.lat=1&point.lon=1&boundary.country=ZZZ'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'ZZZ is not a valid ISO2/ISO3 country code' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 | should.not.exist json.geocoding.query['boundary.country']
35 |
--------------------------------------------------------------------------------
/test/ciao/reverse/boundary_country_invalid_iso3166.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding country
3 | path: '/v1/reverse?point.lat=1&point.lon=1&boundary.country=FOOBAR'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'FOOBAR is not a valid ISO2/ISO3 country code' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 | should.not.exist json.geocoding.query['boundary.country']
35 |
--------------------------------------------------------------------------------
/test/ciao/reverse/boundary_country_valid_alpha2.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding country
3 | path: '/v1/reverse?point.lat=1&point.lon=1&boundary.country=US'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query['boundary.country'].should.eql 'USA'
--------------------------------------------------------------------------------
/test/ciao/reverse/boundary_country_valid_alpha3.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding country
3 | path: '/v1/reverse?point.lat=1&point.lon=1&boundary.country=USA'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query['boundary.country'].should.eql 'USA'
--------------------------------------------------------------------------------
/test/ciao/reverse/boundary_gid_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding gid
3 | path: '/v1/reverse?point.lat=1&point.lon=1&boundary.gid=abc::'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | json.geocoding.errors.should.eql [
27 | 'abc:: does not follow source:layer:id format'
28 | ]
29 |
30 | #? expected warnings
31 | should.not.exist json.geocoding.warnings
32 |
33 | #? inputs
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['boundary.gid']
--------------------------------------------------------------------------------
/test/ciao/reverse/boundary_gid_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding gid
3 | path: '/v1/reverse?point.lat=1&point.lon=1&boundary.gid=whosonfirst:neighbourhood:85869245'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query['boundary.gid'].should.eql '85869245'
--------------------------------------------------------------------------------
/test/ciao/reverse/duplicate_parameter_name.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> set size
3 | path: '/v1/reverse?point.lat=1&point.lon=1¶m=value1¶m=value2'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected warnings
26 | should.not.exist json.geocoding.warnings
27 |
28 | #? expected errors
29 | should.exist json.geocoding.errors
30 | json.geocoding.errors.should.eql [ '\'param\' parameter can only have one value' ]
31 |
--------------------------------------------------------------------------------
/test/ciao/reverse/language_default.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/reverse?point.lat=1&point.lon=2'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | name: 'English',
34 | iso6391: 'en',
35 | iso6393: 'eng',
36 | defaulted: true
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/reverse/language_header_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/reverse?point.lat=1&point.lon=2'
4 | headers: 'Accept-Language': 'example'
5 |
6 | #? 200 ok
7 | response.statusCode.should.be.equal 200
8 | response.should.have.header 'charset', 'utf8'
9 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
10 |
11 | #? valid geocoding block
12 | should.exist json.geocoding
13 | should.exist json.geocoding.version
14 | should.exist json.geocoding.attribution
15 | should.exist json.geocoding.query
16 | should.exist json.geocoding.engine
17 | should.exist json.geocoding.engine.name
18 | should.exist json.geocoding.engine.author
19 | should.exist json.geocoding.engine.version
20 | should.exist json.geocoding.timestamp
21 |
22 | #? valid geojson
23 | json.type.should.be.equal 'FeatureCollection'
24 | json.features.should.be.instanceof Array
25 |
26 | #? expected errors
27 | should.not.exist json.geocoding.errors
28 |
29 | #? expected warnings
30 | json.geocoding.warnings.should.eql [ 'invalid language provided via header' ]
31 |
32 | #? language
33 | json.geocoding.query['lang'].should.eql {
34 | name: 'English',
35 | iso6391: 'en',
36 | iso6393: 'eng',
37 | defaulted: true
38 | }
39 |
--------------------------------------------------------------------------------
/test/ciao/reverse/language_header_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/reverse?point.lat=1&point.lon=2'
4 | headers: 'Accept-Language': 'fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5'
5 |
6 | #? 200 ok
7 | response.statusCode.should.be.equal 200
8 | response.should.have.header 'charset', 'utf8'
9 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
10 |
11 | #? valid geocoding block
12 | should.exist json.geocoding
13 | should.exist json.geocoding.version
14 | should.exist json.geocoding.attribution
15 | should.exist json.geocoding.query
16 | should.exist json.geocoding.engine
17 | should.exist json.geocoding.engine.name
18 | should.exist json.geocoding.engine.author
19 | should.exist json.geocoding.engine.version
20 | should.exist json.geocoding.timestamp
21 |
22 | #? valid geojson
23 | json.type.should.be.equal 'FeatureCollection'
24 | json.features.should.be.instanceof Array
25 |
26 | #? expected errors
27 | should.not.exist json.geocoding.errors
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? language
33 | json.geocoding.query['lang'].should.eql {
34 | defaulted: false,
35 | iso6391: 'fr',
36 | iso6393: 'fra',
37 | name: 'French'
38 | }
39 |
--------------------------------------------------------------------------------
/test/ciao/reverse/language_querystring_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/reverse?lang=example&point.lat=1&point.lon=2'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | json.geocoding.warnings.should.eql [ 'invalid language provided via querystring' ]
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | name: 'English',
34 | iso6391: 'en',
35 | iso6393: 'eng',
36 | defaulted: true
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/reverse/language_querystring_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/reverse?lang=fr&point.lat=1&point.lon=2'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | defaulted: false,
34 | iso6391: 'fr',
35 | iso6393: 'fra',
36 | name: 'French'
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/reverse/layers_alias_address.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/reverse?point.lat=1&point.lon=2&layers=address'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query.layers.should.eql ["address"]
34 |
--------------------------------------------------------------------------------
/test/ciao/reverse/layers_alias_coarse.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/reverse?point.lat=1&point.lon=2&layers=coarse'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query.layers.should.eql [ "continent",
34 | "empire",
35 | "country",
36 | "dependency",
37 | "macroregion",
38 | "region",
39 | "locality",
40 | "localadmin",
41 | "macrocounty",
42 | "county",
43 | "macrohood",
44 | "borough",
45 | "neighbourhood",
46 | "microhood",
47 | "disputed",
48 | "postalcode",
49 | "ocean",
50 | "marinearea"
51 | ]
52 |
--------------------------------------------------------------------------------
/test/ciao/reverse/layers_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/reverse?point.lat=1&point.lon=2&layers=notlayer'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ '\'notlayer\' is an invalid layers parameter. Valid options: coarse,address,venue,street,country,macroregion,region,county,localadmin,locality,borough,neighbourhood,continent,empire,dependency,macrocounty,macrohood,microhood,disputed,postalcode,ocean,marinearea' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 | should.not.exist json.geocoding.query['types']
35 | should.not.exist json.geocoding.query['type']
36 |
--------------------------------------------------------------------------------
/test/ciao/reverse/layers_multiple.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/reverse?point.lat=1&point.lon=2&layers=country,region'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query.layers.should.eql ["country","region"]
34 |
--------------------------------------------------------------------------------
/test/ciao/reverse/layers_single.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/reverse?point.lat=1&point.lon=2&layers=country'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query.layers.should.eql ["country"]
34 |
--------------------------------------------------------------------------------
/test/ciao/reverse/non_scalar_parameter_array.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> define two sources
3 | path: '/v1/reverse?point.lat=1&point.lon=1&sources=A&sources=B'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected warnings
26 | should.not.exist json.geocoding.warnings
27 |
28 | #? expected errors
29 | should.exist json.geocoding.errors
30 | json.geocoding.errors.should.eql [ '\'sources\' parameter can only have one value' ]
31 |
--------------------------------------------------------------------------------
/test/ciao/reverse/non_scalar_parameter_object.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> define parameter as object
3 | path: '/v1/reverse?point.lat=1&point.lon=1¶meter[idx]=value'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected warnings
26 | should.not.exist json.geocoding.warnings
27 |
28 | #? expected errors
29 | should.exist json.geocoding.errors
30 | json.geocoding.errors.should.eql [ '\'parameter\' parameter must be a scalar' ]
31 |
--------------------------------------------------------------------------------
/test/ciao/reverse/point_invalid_lat.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> point
3 | path: '/v1/reverse?point.lat=foo&point.lon=-73.990342'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'missing param \'point.lat\'' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 | should.not.exist json.geocoding.query['point.lat']
35 | should.not.exist json.geocoding.query['point.lon']
36 |
--------------------------------------------------------------------------------
/test/ciao/reverse/point_invalid_lon.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> point
3 | path: '/v1/reverse?point.lat=40.744243&point.lon='
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'missing param \'point.lon\'' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['point.lat'].should.eql 40.744243
35 | should.not.exist json.geocoding.query['point.lon']
36 |
--------------------------------------------------------------------------------
/test/ciao/reverse/point_missing_lat.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> point
3 | path: '/v1/reverse?point.lon=-73.990342'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'parameters point.lat and point.lon must both be specified' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 | should.not.exist json.geocoding.query['point.lat']
35 | should.not.exist json.geocoding.query['point.lon']
36 |
--------------------------------------------------------------------------------
/test/ciao/reverse/point_missing_lon.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> point
3 | path: '/v1/reverse?point.lat=40.744243'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'parameters point.lat and point.lon must both be specified' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 | should.not.exist json.geocoding.query['point.lat']
35 | should.not.exist json.geocoding.query['point.lon']
36 |
--------------------------------------------------------------------------------
/test/ciao/reverse/point_null_island.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> point null island
3 | path: '/v1/reverse?point.lat=0&point.lon=0'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query['point.lat'].should.eql 0
34 | json.geocoding.query['point.lon'].should.eql 0
--------------------------------------------------------------------------------
/test/ciao/reverse/point_valid_duo.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> point
3 | path: '/v1/reverse?point.lat=40.744243&point.lon=-73.990342'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query['point.lat'].should.eql 40.744243
34 | json.geocoding.query['point.lon'].should.eql -73.990342
--------------------------------------------------------------------------------
/test/ciao/reverse/privacy_false.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> accept privacy var
3 | path: '/v1/reverse?point.lat=1&point.lon=2&private=false'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query['private'].should.eql false
--------------------------------------------------------------------------------
/test/ciao/reverse/privacy_true.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> accept privacy var
3 | path: '/v1/reverse?point.lat=1&point.lon=2&private=true'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query['private'].should.eql true
--------------------------------------------------------------------------------
/test/ciao/reverse/size_over_max.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> set size
3 | path: '/v1/reverse?point.lat=1&point.lon=1&size=999'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.exist json.geocoding.warnings
30 | json.geocoding.warnings.should.eql [ 'out-of-range integer \'size\', using MAX_SIZE' ]
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 40
--------------------------------------------------------------------------------
/test/ciao/reverse/size_under_min.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> set size
3 | path: '/v1/reverse?point.lat=1&point.lon=1&size=0'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.exist json.geocoding.warnings
30 | json.geocoding.warnings.should.eql [ 'out-of-range integer \'size\', using MIN_SIZE' ]
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 1
--------------------------------------------------------------------------------
/test/ciao/reverse/size_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> set size
3 | path: '/v1/reverse?point.lat=1&point.lon=1&size=3'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 3
--------------------------------------------------------------------------------
/test/ciao/reverse/sources_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources filter
3 | path: '/v1/reverse?point.lat=1&point.lon=2&sources=openstreetmap,notasource'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ '\'notasource\' is an invalid sources parameter. Valid options: osm,oa,gn,wof,openstreetmap,openaddresses,geonames,whosonfirst' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 | should.not.exist json.geocoding.query['types']
35 | should.not.exist json.geocoding.query['type']
36 |
--------------------------------------------------------------------------------
/test/ciao/reverse/sources_layers_invalid_combo.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources and layers specified (invalid combo)
3 | path: '/v1/reverse?point.lat=1&point.lon=2&sources=whosonfirst&layers=address'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'You have specified both the `sources` and `layers` parameters in a combination that will return no results: the whosonfirst source has nothing in the address layer' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.layers.should.eql ["address"]
35 | json.geocoding.query.sources.should.eql ["whosonfirst"]
36 |
--------------------------------------------------------------------------------
/test/ciao/reverse/sources_layers_valid_combo.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources and layers specified
3 | path: '/v1/reverse?point.lat=1&point.lon=2&sources=openaddresses&layers=address'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query.layers.should.eql ["address"]
34 | json.geocoding.query.sources.should.eql ["openaddresses"]
35 |
--------------------------------------------------------------------------------
/test/ciao/reverse/sources_multiple.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources filter
3 | path: '/v1/reverse?point.lat=1&point.lon=2&sources=openstreetmap,openaddresses'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query.sources.should.eql ["openstreetmap", "openaddresses"]
34 |
--------------------------------------------------------------------------------
/test/ciao/reverse/sources_single.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources filter
3 | path: '/v1/reverse?point.lat=1&point.lon=2&sources=openstreetmap'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['size'].should.eql 10
33 | json.geocoding.query.sources.should.eql ["openstreetmap"]
34 |
--------------------------------------------------------------------------------
/test/ciao/search/boundary_circle_invalid_lat_lon_types.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding circle
3 | path: '/v1/search?text=a&boundary.circle.lat=foo&boundary.circle.lon=bar'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'missing param \'boundary.circle.lat\'' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['boundary.circle.lat']
36 | should.not.exist json.geocoding.query['boundary.circle.lon']
37 | should.not.exist json.geocoding.query['boundary.circle.radius']
38 |
--------------------------------------------------------------------------------
/test/ciao/search/boundary_circle_invalid_radius.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding circle
3 | path: '/v1/search?text=a&boundary.circle.lat=40.744243&boundary.circle.lon=-73.990342&boundary.circle.radius=foo'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'missing param \'boundary.circle.radius\'' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['boundary.circle.lat']
36 | should.not.exist json.geocoding.query['boundary.circle.lon']
37 | should.not.exist json.geocoding.query['boundary.circle.radius']
38 |
--------------------------------------------------------------------------------
/test/ciao/search/boundary_circle_valid_duo.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding circle
3 | path: '/v1/search?text=a&boundary.circle.lat=40.744243&boundary.circle.lon=-73.990342'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['boundary.circle.lat'].should.eql 40.744243
35 | json.geocoding.query['boundary.circle.lon'].should.eql -73.990342
36 | should.not.exist json.geocoding.query['boundary.circle.radius']
--------------------------------------------------------------------------------
/test/ciao/search/boundary_circle_valid_trio.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding circle
3 | path: '/v1/search?text=a&boundary.circle.lat=40.744243&boundary.circle.lon=-73.990342&boundary.circle.radius=100'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['boundary.circle.lat'].should.eql 40.744243
35 | json.geocoding.query['boundary.circle.lon'].should.eql -73.990342
36 | json.geocoding.query['boundary.circle.radius'].should.eql 100
--------------------------------------------------------------------------------
/test/ciao/search/boundary_country_invalid_alpha2.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding country
3 | path: '/v1/search?text=a&boundary.country=ZZ'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'ZZ is not a valid ISO2/ISO3 country code' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['boundary.country']
36 |
--------------------------------------------------------------------------------
/test/ciao/search/boundary_country_invalid_alpha3.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding country
3 | path: '/v1/search?text=a&boundary.country=ZZZ'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'ZZZ is not a valid ISO2/ISO3 country code' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['boundary.country']
36 |
--------------------------------------------------------------------------------
/test/ciao/search/boundary_country_invalid_iso3166.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding country
3 | path: '/v1/search?text=a&boundary.country=FOOBAR'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'FOOBAR is not a valid ISO2/ISO3 country code' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['boundary.country']
36 |
--------------------------------------------------------------------------------
/test/ciao/search/boundary_country_valid_alpha2.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding country
3 | path: '/v1/search?text=a&boundary.country=US'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['boundary.country'].should.eql 'USA'
--------------------------------------------------------------------------------
/test/ciao/search/boundary_country_valid_alpha3.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding country
3 | path: '/v1/search?text=a&boundary.country=USA'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['boundary.country'].should.eql 'USA'
--------------------------------------------------------------------------------
/test/ciao/search/boundary_gid_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding gid
3 | path: '/v1/search?text=a&boundary.gid=abc::'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | json.geocoding.errors.should.eql [
27 | 'abc:: does not follow source:layer:id format'
28 | ]
29 |
30 | #? expected warnings
31 | should.not.exist json.geocoding.warnings
32 |
33 | #? inputs
34 | json.geocoding.query['text'].should.eql 'a'
35 | json.geocoding.query['size'].should.eql 10
36 | should.not.exist json.geocoding.query['boundary.gid']
--------------------------------------------------------------------------------
/test/ciao/search/boundary_gid_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> bounding gid
3 | path: '/v1/search?text=a&boundary.gid=whosonfirst:neighbourhood:85869245'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['boundary.gid'].should.eql '85869245'
--------------------------------------------------------------------------------
/test/ciao/search/focus_point_invalid_lat.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/search?text=a&focus.point.lat=foo&focus.point.lon=-73.990342'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'missing param \'focus.point.lat\'' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['focus.point.lat']
36 | should.not.exist json.geocoding.query['focus.point.lon']
37 |
--------------------------------------------------------------------------------
/test/ciao/search/focus_point_invalid_lon.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/search?text=a&focus.point.lat=40.744243&focus.point.lon='
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'missing param \'focus.point.lon\'' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | json.geocoding.query['focus.point.lat'].should.eql 40.744243
36 | should.not.exist json.geocoding.query['focus.point.lon']
37 |
--------------------------------------------------------------------------------
/test/ciao/search/focus_point_missing_lat.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/search?text=a&focus.point.lon=-73.990342'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'parameters focus.point.lat and focus.point.lon must both be specified' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['focus.point.lat']
36 | should.not.exist json.geocoding.query['focus.point.lon']
37 |
--------------------------------------------------------------------------------
/test/ciao/search/focus_point_missing_lon.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/search?text=a&focus.point.lat=40.744243'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'parameters focus.point.lat and focus.point.lon must both be specified' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 | should.not.exist json.geocoding.query['focus.point.lat']
36 | should.not.exist json.geocoding.query['focus.point.lon']
37 |
--------------------------------------------------------------------------------
/test/ciao/search/focus_point_null_island.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point null island
3 | path: '/v1/search?text=a&focus.point.lat=0&focus.point.lon=0'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['focus.point.lat'].should.eql 0
35 | json.geocoding.query['focus.point.lon'].should.eql 0
--------------------------------------------------------------------------------
/test/ciao/search/focus_point_valid_duo.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> focus point
3 | path: '/v1/search?text=a&focus.point.lat=40.744243&focus.point.lon=-73.990342'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['focus.point.lat'].should.eql 40.744243
35 | json.geocoding.query['focus.point.lon'].should.eql -73.990342
--------------------------------------------------------------------------------
/test/ciao/search/language_default.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/search?text=example'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | name: 'English',
34 | iso6391: 'en',
35 | iso6393: 'eng',
36 | defaulted: true
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/search/language_header_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/search?text=example'
4 | headers: 'Accept-Language': 'example'
5 |
6 | #? 200 ok
7 | response.statusCode.should.be.equal 200
8 | response.should.have.header 'charset', 'utf8'
9 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
10 |
11 | #? valid geocoding block
12 | should.exist json.geocoding
13 | should.exist json.geocoding.version
14 | should.exist json.geocoding.attribution
15 | should.exist json.geocoding.query
16 | should.exist json.geocoding.engine
17 | should.exist json.geocoding.engine.name
18 | should.exist json.geocoding.engine.author
19 | should.exist json.geocoding.engine.version
20 | should.exist json.geocoding.timestamp
21 |
22 | #? valid geojson
23 | json.type.should.be.equal 'FeatureCollection'
24 | json.features.should.be.instanceof Array
25 |
26 | #? expected errors
27 | should.not.exist json.geocoding.errors
28 |
29 | #? expected warnings
30 | json.geocoding.warnings.should.eql [ 'invalid language provided via header' ]
31 |
32 | #? language
33 | json.geocoding.query['lang'].should.eql {
34 | name: 'English',
35 | iso6391: 'en',
36 | iso6393: 'eng',
37 | defaulted: true
38 | }
39 |
--------------------------------------------------------------------------------
/test/ciao/search/language_header_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/search?text=example'
4 | headers: 'Accept-Language': 'fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5'
5 |
6 | #? 200 ok
7 | response.statusCode.should.be.equal 200
8 | response.should.have.header 'charset', 'utf8'
9 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
10 |
11 | #? valid geocoding block
12 | should.exist json.geocoding
13 | should.exist json.geocoding.version
14 | should.exist json.geocoding.attribution
15 | should.exist json.geocoding.query
16 | should.exist json.geocoding.engine
17 | should.exist json.geocoding.engine.name
18 | should.exist json.geocoding.engine.author
19 | should.exist json.geocoding.engine.version
20 | should.exist json.geocoding.timestamp
21 |
22 | #? valid geojson
23 | json.type.should.be.equal 'FeatureCollection'
24 | json.features.should.be.instanceof Array
25 |
26 | #? expected errors
27 | should.not.exist json.geocoding.errors
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? language
33 | json.geocoding.query['lang'].should.eql {
34 | defaulted: false,
35 | iso6391: 'fr',
36 | iso6393: 'fra',
37 | name: 'French'
38 | }
39 |
--------------------------------------------------------------------------------
/test/ciao/search/language_querystring_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/search?lang=example&text=example'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | json.geocoding.warnings.should.eql [ 'invalid language provided via querystring' ]
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | name: 'English',
34 | iso6391: 'en',
35 | iso6393: 'eng',
36 | defaulted: true
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/search/language_querystring_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> language
3 | path: '/v1/search?lang=fr&text=example'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? language
32 | json.geocoding.query['lang'].should.eql {
33 | defaulted: false,
34 | iso6391: 'fr',
35 | iso6393: 'fra',
36 | name: 'French'
37 | }
38 |
--------------------------------------------------------------------------------
/test/ciao/search/layers_alias_address.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/search?text=a&layers=address'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.layers.should.eql ["address"]
35 |
--------------------------------------------------------------------------------
/test/ciao/search/layers_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/search?text=a&layers=notlayer'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ '\'notlayer\' is an invalid layers parameter. Valid options: coarse,address,venue,street,country,macroregion,region,county,localadmin,locality,borough,neighbourhood,continent,empire,dependency,macrocounty,macrohood,microhood,disputed,postalcode,ocean,marinearea' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 |
--------------------------------------------------------------------------------
/test/ciao/search/layers_multiple.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/search?text=a&layers=country,region'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.layers.should.eql ["country","region"]
35 |
--------------------------------------------------------------------------------
/test/ciao/search/layers_single.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> layer alias
3 | path: '/v1/search?text=a&layers=country'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.layers.should.eql ["country"]
35 |
--------------------------------------------------------------------------------
/test/ciao/search/no_params.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> no params specified
3 | path: '/v1/search'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'invalid param \'text\': text length, must be >0' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['size'].should.eql 10
34 |
--------------------------------------------------------------------------------
/test/ciao/search/non_scalar_parameter_array.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> define two sources
3 | path: '/v1/search?text=A&sources=A&sources=B'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected warnings
26 | should.not.exist json.geocoding.warnings
27 |
28 | #? expected errors
29 | should.exist json.geocoding.errors
30 | json.geocoding.errors.should.eql [ '\'sources\' parameter can only have one value' ]
31 |
--------------------------------------------------------------------------------
/test/ciao/search/non_scalar_parameter_object.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> define parameter as object
3 | path: '/v1/search?text=A¶meter[idx]=value'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected warnings
26 | should.not.exist json.geocoding.warnings
27 |
28 | #? expected errors
29 | should.exist json.geocoding.errors
30 | json.geocoding.errors.should.eql [ '\'parameter\' parameter must be a scalar' ]
31 |
--------------------------------------------------------------------------------
/test/ciao/search/privacy_false.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> accept privacy var
3 | path: '/v1/search?text=a&private=false'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['private'].should.eql false
--------------------------------------------------------------------------------
/test/ciao/search/privacy_true.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> accept privacy var
3 | path: '/v1/search?text=a&private=true'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query['private'].should.eql true
--------------------------------------------------------------------------------
/test/ciao/search/size_over_max.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> set size
3 | path: '/v1/search?text=a&size=999'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.exist json.geocoding.warnings
30 | json.geocoding.warnings.should.eql [ 'out-of-range integer \'size\', using MAX_SIZE' ]
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 40
--------------------------------------------------------------------------------
/test/ciao/search/size_under_min.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> set size
3 | path: '/v1/search?text=a&size=0'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.exist json.geocoding.warnings
30 | json.geocoding.warnings.should.eql [ 'out-of-range integer \'size\', using MIN_SIZE' ]
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 1
--------------------------------------------------------------------------------
/test/ciao/search/size_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> set size
3 | path: '/v1/search?text=a&size=3'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 3
--------------------------------------------------------------------------------
/test/ciao/search/sources_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources filter
3 | path: '/v1/search?text=a&sources=openstreetmap,notasource'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ '\'notasource\' is an invalid sources parameter. Valid options: osm,oa,gn,wof,openstreetmap,openaddresses,geonames,whosonfirst' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | json.geocoding.query['text'].should.eql 'a'
34 | json.geocoding.query['size'].should.eql 10
35 |
--------------------------------------------------------------------------------
/test/ciao/search/sources_layers_valid_combo.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources and layers specified
3 | path: '/v1/search?text=a&sources=openaddresses&layers=address'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.layers.should.eql ["address"]
35 | json.geocoding.query.sources.should.eql ["openaddresses"]
36 |
--------------------------------------------------------------------------------
/test/ciao/search/sources_multiple.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources filter
3 | path: "/v1/search?text=a&sources=openstreetmap,geonames"
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header "charset", 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.sources.should.eql ["openstreetmap", "geonames"]
35 |
--------------------------------------------------------------------------------
/test/ciao/search/sources_single.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> sources filter
3 | path: '/v1/search?text=a&sources=openstreetmap'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 | json.geocoding.query.sources.should.eql ["openstreetmap"]
35 |
--------------------------------------------------------------------------------
/test/ciao/search/text_invalid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> basic search
3 | path: '/v1/search?text='
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 400
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.exist json.geocoding.errors
27 | json.geocoding.errors.should.eql [ 'invalid param \'text\': text length, must be >0' ]
28 |
29 | #? expected warnings
30 | should.not.exist json.geocoding.warnings
31 |
32 | #? inputs
33 | should.not.exist json.geocoding.query['text']
34 | json.geocoding.query['size'].should.eql 10
35 |
--------------------------------------------------------------------------------
/test/ciao/search/text_valid.coffee:
--------------------------------------------------------------------------------
1 |
2 | #> basic search
3 | path: '/v1/search?text=a'
4 |
5 | #? 200 ok
6 | response.statusCode.should.be.equal 200
7 | response.should.have.header 'charset', 'utf8'
8 | response.should.have.header 'content-type', 'application/json; charset=utf-8'
9 |
10 | #? valid geocoding block
11 | should.exist json.geocoding
12 | should.exist json.geocoding.version
13 | should.exist json.geocoding.attribution
14 | should.exist json.geocoding.query
15 | should.exist json.geocoding.engine
16 | should.exist json.geocoding.engine.name
17 | should.exist json.geocoding.engine.author
18 | should.exist json.geocoding.engine.version
19 | should.exist json.geocoding.timestamp
20 |
21 | #? valid geojson
22 | json.type.should.be.equal 'FeatureCollection'
23 | json.features.should.be.instanceof Array
24 |
25 | #? expected errors
26 | should.not.exist json.geocoding.errors
27 |
28 | #? expected warnings
29 | should.not.exist json.geocoding.warnings
30 |
31 | #? inputs
32 | json.geocoding.query['text'].should.eql 'a'
33 | json.geocoding.query['size'].should.eql 10
34 |
--------------------------------------------------------------------------------
/test/test-pelias-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "api": {
3 | "targets": {
4 | "auto_discover": false
5 | }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/test/unit/app.js:
--------------------------------------------------------------------------------
1 | const proxyquire = require('proxyquire').noCallThru();
2 |
3 | module.exports.tests = {};
4 |
5 | module.exports.tests.invalid_configuration = (test, common) => {
6 | test('configuration validation throwing error should rethrow', (t) => {
7 | t.throws(() => {
8 | proxyquire('../../app', {
9 | './schema': 'this is the schema',
10 | 'pelias-config': {
11 | generate: (schema) => {
12 | // the schema passed to generate should be the require'd schema
13 | t.equals(schema, 'this is the schema');
14 |
15 | throw Error('config is not valid');
16 | }
17 | }
18 | });
19 |
20 | }, /config is not valid/);
21 |
22 | t.end();
23 |
24 | });
25 |
26 | };
27 |
28 | module.exports.all = (tape, common) => {
29 |
30 | function test(name, testFunction) {
31 | return tape('app: ' + name, testFunction);
32 | }
33 |
34 | for( var testCase in module.exports.tests ){
35 | module.exports.tests[testCase](test, common);
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/test/unit/fixture/dedupe_elasticsearch_custom_layer_results.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | '_id': '101914069',
4 | 'layer': 'venue',
5 | 'source': 'openstreetmap',
6 | 'name': {
7 | 'default': 'Nike World Headquarters'
8 | },
9 | 'parent': {
10 | 'country_a': ['USA'],
11 | 'country': ['United States'],
12 | 'region': ['Oregon'],
13 | 'region_id': ['85688513']
14 | },
15 | 'confidence': 0.98
16 | },
17 | {
18 | '_id': '2456::trimet::major_employer',
19 | 'layer': 'major_employer',
20 | 'source': 'transit',
21 | 'name': {
22 | 'default': 'Nike World Headquarters'
23 | },
24 | 'parent': {
25 | 'country_a': ['USA'],
26 | 'country': ['United States'],
27 | 'region': ['Oregon'],
28 | 'region_id': ['85688513']
29 | },
30 | 'confidence': 0.50
31 | }
32 | ];
--------------------------------------------------------------------------------
/test/unit/fixture/dedupe_only_postalcode_differs.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | '_id': '101914069',
4 | 'layer': 'venue',
5 | 'source': 'openstreetmap',
6 | 'name': {
7 | 'default': 'A place'
8 | },
9 | 'parent': {
10 | 'country_a': ['USA']
11 | }
12 | },
13 | {
14 | '_id': '323',
15 | 'layer': 'venue',
16 | 'source': 'openstreetmap',
17 | 'name': {
18 | 'default': 'A place'
19 | },
20 | 'address_parts': {
21 | 'zip': '97005'
22 | },
23 | 'parent': {
24 | 'country_a': ['USA']
25 | }
26 | }
27 | ];
28 |
--------------------------------------------------------------------------------
/test/unit/helper/stackTraceLine.js:
--------------------------------------------------------------------------------
1 | const stackTraceLine = require('../../../helper/stackTraceLine');
2 |
3 | module.exports.tests = {};
4 | module.exports.tests.stackTrace = (test, common) => {
5 | test('No exceptions thrown when function is called', (t) => {
6 | t.doesNotThrow(stackTraceLine, 'No exceptions thrown');
7 | t.end();
8 | });
9 | };
10 |
11 | module.exports.all = function (tape, common) {
12 |
13 | function test(name, testFunction) {
14 | return tape('[helper] stackTraceLine: ' + name, testFunction);
15 | }
16 |
17 | for( var testCase in module.exports.tests ){
18 | module.exports.tests[testCase](test, common);
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/test/unit/middleware/distance.js:
--------------------------------------------------------------------------------
1 | var distance = require('../../../middleware/distance')();
2 |
3 | module.exports.tests = {};
4 |
5 | module.exports.tests.computeDistance = function(test, common) {
6 | test('valid lat/lon and results', function(t) {
7 | var req = {
8 | clean: {
9 | 'point.lat': 45,
10 | 'point.lon': -77
11 | }
12 | };
13 | var res = {
14 | data: [
15 | {
16 | center_point: {
17 | lat: 40,
18 | lon: -71
19 | }
20 | }
21 | ]
22 | };
23 |
24 | var expected = 742.735;
25 | distance(req, res, function () {
26 | t.equal(res.data[0].distance, expected, 'correct distance computed');
27 | t.end();
28 | });
29 | });
30 | };
31 |
32 | module.exports.all = function (tape, common) {
33 |
34 | function test(name, testFunction) {
35 | return tape('[middleware] distance: ' + name, testFunction);
36 | }
37 |
38 | for( var testCase in module.exports.tests ){
39 | module.exports.tests[testCase](test, common);
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/test/unit/query/MockQuery.js:
--------------------------------------------------------------------------------
1 | module.exports = class MockQuery {
2 | constructor() {
3 | this._score_functions = [];
4 | this._sort_functions = [];
5 | this._filter_functions = [];
6 | }
7 |
8 | render(vs) {
9 | return {
10 | vs: vs,
11 | score_functions: this._score_functions,
12 | sort_functions: this._sort_functions,
13 | filter_functions: this._filter_functions
14 | };
15 | }
16 |
17 | score(view) {
18 | this._score_functions.push(view);
19 | return this;
20 | }
21 |
22 | sort(view) {
23 | this._sort_functions.push(view);
24 | return this;
25 | }
26 |
27 | filter(view) {
28 | this._filter_functions.push(view);
29 | return this;
30 | }
31 |
32 | };
33 |
--------------------------------------------------------------------------------
/test/unit/query/autocomplete_defaults.js:
--------------------------------------------------------------------------------
1 | var defaults = require('../../../query/autocomplete_defaults');
2 |
3 | module.exports.tests = {};
4 |
5 | module.exports.tests.interface = function(test, common) {
6 | test('valid interface', function(t) {
7 | t.equal(typeof defaults, 'object', 'defaults defined');
8 | t.end();
9 | });
10 | };
11 |
12 | module.exports.all = function (tape, common) {
13 |
14 | function test(name, testFunction) {
15 | return tape('autocomplete defaults ' + name, testFunction);
16 | }
17 |
18 | for( var testCase in module.exports.tests ){
19 | module.exports.tests[testCase](test, common);
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/test/unit/query/reverse_defaults.js:
--------------------------------------------------------------------------------
1 | var defaults = require('../../../query/reverse_defaults');
2 |
3 | module.exports.tests = {};
4 |
5 | module.exports.tests.interface = function(test, common) {
6 | test('valid interface', function(t) {
7 | t.equal(typeof defaults, 'object', 'defaults defined');
8 | t.end();
9 | });
10 | };
11 |
12 | module.exports.all = function (tape, common) {
13 |
14 | function test(name, testFunction) {
15 | return tape('reverse defaults ' + name, testFunction);
16 | }
17 |
18 | for( var testCase in module.exports.tests ){
19 | module.exports.tests[testCase](test, common);
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/test/unit/query/search_defaults.js:
--------------------------------------------------------------------------------
1 | var defaults = require('../../../query/search_defaults');
2 |
3 | module.exports.tests = {};
4 |
5 | module.exports.tests.interface = function(test, common) {
6 | test('valid interface', function(t) {
7 | t.equal(typeof defaults, 'object', 'defaults defined');
8 | t.end();
9 | });
10 | };
11 |
12 | module.exports.all = function (tape, common) {
13 |
14 | function test(name, testFunction) {
15 | return tape('search defaults ' + name, testFunction);
16 | }
17 |
18 | for( var testCase in module.exports.tests ){
19 | module.exports.tests[testCase](test, common);
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/test/unit/sanitizer/_request_language.js:
--------------------------------------------------------------------------------
1 | const sanitizer = require('../../../sanitizer/_request_language')();
2 |
3 | module.exports.tests = {};
4 |
5 | module.exports.tests.do_nothing = (test, common) => {
6 | test('sanitize should return empty warnings/erros', t => {
7 | const messages = sanitizer.sanitize();
8 |
9 | t.deepEquals(messages.errors, [], 'no errors');
10 | t.deepEquals(messages.warnings, [], 'no warnings');
11 | t.end();
12 |
13 | });
14 |
15 | };
16 |
17 | module.exports.tests.expected = (test, common) => {
18 | test('expected should contain only \'lang\'', t => {
19 | const expected = sanitizer.expected();
20 |
21 | t.deepEquals(expected, [{'name': 'lang'}]);
22 | t.end();
23 |
24 | });
25 | };
26 |
27 | module.exports.all = (tape, common) => {
28 | function test(name, testFunction) {
29 | return tape(`SANITIZE _request_language: ${name}`, testFunction);
30 | }
31 |
32 | for( const testCase in module.exports.tests ){
33 | module.exports.tests[testCase](test, common);
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/test/unit/sanitizer/_truthy.js:
--------------------------------------------------------------------------------
1 | var isTruthy = require('../../../sanitizer/_truthy');
2 |
3 | module.exports.tests = {};
4 |
5 | module.exports.tests.sanitize_truthy = function(test, common) {
6 | var valid_values = ['true', true, 1, '1', 'yes', 'y'];
7 | valid_values.forEach(function(value) {
8 | test('truthy value ' + value, function(t) {
9 | t.equal(isTruthy(value), true, 'returns true');
10 | t.end();
11 | });
12 | });
13 |
14 | var valid_false_values = ['false', false, 0, '0', 'no', 'n', null, -1, 123, NaN, 'abc'];
15 | valid_false_values.forEach(function(value) {
16 | test('falsey value ' + value, function(t) {
17 | t.equal(isTruthy(value), false, 'returns false');
18 | t.end();
19 | });
20 | });
21 | };
22 |
23 | module.exports.all = function (tape, common) {
24 | function test(name, testFunction) {
25 | return tape('SANTIZE _truthy ' + name, testFunction);
26 | }
27 |
28 | for( var testCase in module.exports.tests ){
29 | module.exports.tests[testCase](test, common);
30 | }
31 | };
32 |
--------------------------------------------------------------------------------