mirror of https://github.com/pelias/api.git
Harish Krishna
10 years ago
31 changed files with 834 additions and 163 deletions
@ -1,5 +1,4 @@ |
|||||||
language: node_js |
language: node_js |
||||||
script: "npm run unit" |
script: "npm run unit" |
||||||
node_js: |
node_js: |
||||||
- "0.11" |
|
||||||
- "0.10" |
- "0.10" |
@ -0,0 +1,46 @@ |
|||||||
|
|
||||||
|
var app = require('express')(); |
||||||
|
|
||||||
|
/** ----------------------- middleware ----------------------- **/ |
||||||
|
|
||||||
|
app.use( require('./middleware/toobusy') ); // should be first
|
||||||
|
app.use( require('./middleware/headers') ); |
||||||
|
app.use( require('./middleware/cors') ); |
||||||
|
app.use( require('./middleware/jsonp') ); |
||||||
|
|
||||||
|
var middlewares = {}; |
||||||
|
middlewares.search = require('./middleware/search'); |
||||||
|
|
||||||
|
/** ----------------------- sanitisers ----------------------- **/ |
||||||
|
|
||||||
|
var sanitisers = {}; |
||||||
|
sanitisers.sanitiser= require('./sanitiser/sanitise'); |
||||||
|
|
||||||
|
/** ----------------------- controllers ----------------------- **/ |
||||||
|
|
||||||
|
var controllers = {}; |
||||||
|
controllers.index = require('./controller/index'); |
||||||
|
controllers.suggest = require('./controller/suggest'); |
||||||
|
controllers.search = require('./controller/search'); |
||||||
|
|
||||||
|
/** ----------------------- routes ----------------------- **/ |
||||||
|
|
||||||
|
// api root
|
||||||
|
app.get( '/', controllers.index() ); |
||||||
|
|
||||||
|
// suggest API
|
||||||
|
app.get( '/suggest', sanitisers.sanitiser.middleware, controllers.suggest() ); |
||||||
|
|
||||||
|
// search API
|
||||||
|
app.get( '/search', sanitisers.sanitiser.middleware, middlewares.search.middleware, controllers.search() ); |
||||||
|
|
||||||
|
// reverse API
|
||||||
|
app.get( '/reverse', sanitisers.sanitiser.middleware, controllers.search(undefined, require('../query/reverse')) ); |
||||||
|
|
||||||
|
|
||||||
|
/** ----------------------- error middleware ----------------------- **/ |
||||||
|
|
||||||
|
app.use( require('./middleware/404') ); |
||||||
|
app.use( require('./middleware/500') ); |
||||||
|
|
||||||
|
module.exports = app; |
@ -1,16 +1,22 @@ |
|||||||
|
|
||||||
var pkg = require('../package'); |
var pkg = require('../package'); |
||||||
|
|
||||||
function controller( req, res, next ){ |
function setup(){ |
||||||
|
|
||||||
// stats
|
function controller( req, res, next ){ |
||||||
res.json({ |
|
||||||
name: pkg.name, |
// stats
|
||||||
version: { |
res.json({ |
||||||
number: pkg.version |
name: pkg.name, |
||||||
} |
version: { |
||||||
}); |
number: pkg.version |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return controller; |
||||||
|
|
||||||
} |
} |
||||||
|
|
||||||
module.exports = controller; |
module.exports = setup; |
@ -1,37 +1,42 @@ |
|||||||
|
|
||||||
var backend = require('../src/backend'); |
function setup( backend, query ){ |
||||||
|
|
||||||
function controller( req, res, next ){ |
// allow overriding of dependencies
|
||||||
var required_query = req.required_query ? req.required_query : 'search'; |
backend = backend || require('../src/backend'); |
||||||
var query = require('../query/' + required_query); |
query = query || require('../query/search'); |
||||||
|
|
||||||
// backend command
|
|
||||||
var cmd = { |
|
||||||
index: 'pelias', |
|
||||||
body: query( req.clean ) |
|
||||||
}; |
|
||||||
|
|
||||||
// query backend
|
function controller( req, res, next ){ |
||||||
backend().client.search( cmd, function( err, data ){ |
|
||||||
|
|
||||||
var docs = []; |
// backend command
|
||||||
|
var cmd = { |
||||||
|
index: 'pelias', |
||||||
|
body: query( req.clean ) |
||||||
|
}; |
||||||
|
|
||||||
// handle backend errors
|
// query backend
|
||||||
if( err ){ return next( err ); } |
backend().client.search( cmd, function( err, data ){ |
||||||
|
|
||||||
if( data && data.hits && data.hits.total){ |
var docs = []; |
||||||
docs = data.hits.hits.map( function( hit ){ |
|
||||||
return hit._source; |
// handle backend errors
|
||||||
}); |
if( err ){ return next( err ); } |
||||||
} |
|
||||||
|
if( data && data.hits && data.hits.total){ |
||||||
|
docs = data.hits.hits.map( function( hit ){ |
||||||
|
return hit._source; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
// respond
|
// respond
|
||||||
return res.status(200).json({ |
return res.status(200).json({ |
||||||
date: new Date().getTime(), |
date: new Date().getTime(), |
||||||
body: docs |
body: docs |
||||||
|
}); |
||||||
}); |
}); |
||||||
}); |
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return controller; |
||||||
} |
} |
||||||
|
|
||||||
module.exports = controller; |
module.exports = setup; |
||||||
|
@ -1,35 +1,41 @@ |
|||||||
|
|
||||||
var query = require('../query/suggest'), |
function setup( backend, query ){ |
||||||
backend = require('../src/backend'); |
|
||||||
|
|
||||||
function controller( req, res, next ){ |
// allow overriding of dependencies
|
||||||
|
backend = backend || require('../src/backend'); |
||||||
|
query = query || require('../query/suggest'); |
||||||
|
|
||||||
// backend command
|
function controller( req, res, next ){ |
||||||
var cmd = { |
|
||||||
index: 'pelias', |
|
||||||
body: query( req.clean ) |
|
||||||
}; |
|
||||||
|
|
||||||
// query backend
|
// backend command
|
||||||
backend().client.suggest( cmd, function( err, data ){ |
var cmd = { |
||||||
|
index: 'pelias', |
||||||
|
body: query( req.clean ) |
||||||
|
}; |
||||||
|
|
||||||
var docs = []; |
// query backend
|
||||||
|
backend().client.suggest( cmd, function( err, data ){ |
||||||
|
|
||||||
// handle backend errors
|
var docs = []; |
||||||
if( err ){ return next( err ); } |
|
||||||
|
|
||||||
// map response to a valid FeatureCollection
|
// handle backend errors
|
||||||
if( data && Array.isArray( data.pelias ) && data.pelias.length ){ |
if( err ){ return next( err ); } |
||||||
docs = data['pelias'][0].options || []; |
|
||||||
} |
|
||||||
|
|
||||||
// respond
|
// map response to a valid FeatureCollection
|
||||||
return res.status(200).json({ |
if( data && Array.isArray( data.pelias ) && data.pelias.length ){ |
||||||
date: new Date().getTime(), |
docs = data['pelias'][0].options || []; |
||||||
body: docs |
} |
||||||
|
|
||||||
|
// respond
|
||||||
|
return res.status(200).json({ |
||||||
|
date: new Date().getTime(), |
||||||
|
body: docs |
||||||
|
}); |
||||||
}); |
}); |
||||||
}); |
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
return controller; |
||||||
} |
} |
||||||
|
|
||||||
module.exports = controller; |
module.exports = setup; |
@ -1,29 +1,17 @@ |
|||||||
|
|
||||||
var app = require('express')(); |
var cluster = require('cluster'), |
||||||
|
app = require('./app'), |
||||||
/** ----------------------- middleware ----------------------- **/ |
multicore = false, |
||||||
|
port = ( process.env.PORT || 3100 ); |
||||||
app.use( require('./middleware/headers') ); |
|
||||||
app.use( require('./middleware/cors') ); |
/** cluster webserver across all cores **/ |
||||||
app.use( require('./middleware/jsonp') ); |
if( multicore ){ |
||||||
|
// @todo: not finished yet
|
||||||
/** ----------------------- routes ----------------------- **/ |
// cluster(app)
|
||||||
|
// .use(cluster.stats())
|
||||||
// api root
|
// .listen( process.env.PORT || 3100 );
|
||||||
app.get( '/', require('./controller/index') ); |
} |
||||||
|
else { |
||||||
// suggest API
|
console.log( 'listening on ' + port ); |
||||||
app.get( '/suggest', require('./sanitiser/sanitise'), require('./controller/suggest') ); |
app.listen( process.env.PORT || 3100 ); |
||||||
|
} |
||||||
// search API
|
|
||||||
app.get( '/search', require('./sanitiser/sanitise'), require('./middleware/search'), require('./controller/search') ); |
|
||||||
|
|
||||||
// reverse API
|
|
||||||
app.get( '/reverse', require('./sanitiser/sanitise'), require('./middleware/reverse'), require('./controller/search') ); |
|
||||||
|
|
||||||
/** ----------------------- error middleware ----------------------- **/ |
|
||||||
|
|
||||||
app.use( require('./middleware/404') ); |
|
||||||
app.use( require('./middleware/500') ); |
|
||||||
|
|
||||||
app.listen( process.env.PORT || 3100 ); |
|
||||||
|
@ -1,7 +0,0 @@ |
|||||||
// middleware
|
|
||||||
function middleware(req, res, next){ |
|
||||||
req.required_query = "reverse"; |
|
||||||
next(); |
|
||||||
} |
|
||||||
|
|
||||||
module.exports = middleware; |
|
@ -0,0 +1,19 @@ |
|||||||
|
|
||||||
|
// middleware which blocks requests when the eventloop is too busy
|
||||||
|
var toobusy = require('toobusy'); |
||||||
|
|
||||||
|
function middleware(req, res, next){ |
||||||
|
if( toobusy() ){ |
||||||
|
res.status(503); // Service Unavailable
|
||||||
|
return next('Server Overwhelmed'); |
||||||
|
} |
||||||
|
return next(); |
||||||
|
} |
||||||
|
|
||||||
|
// calling .shutdown allows your process to exit normally
|
||||||
|
process.on('SIGINT', function() { |
||||||
|
toobusy.shutdown(); |
||||||
|
process.exit(); |
||||||
|
}); |
||||||
|
|
||||||
|
module.exports = middleware; |
@ -0,0 +1,14 @@ |
|||||||
|
#> valid reverse query |
||||||
|
path: '/reverse?lat=29.49136&lon=-82.50622' |
||||||
|
|
||||||
|
#? 200 ok |
||||||
|
response.statusCode.should.equal 200 |
||||||
|
|
||||||
|
#? valid response |
||||||
|
now = new Date().getTime() |
||||||
|
should.exist json |
||||||
|
should.not.exist json.error |
||||||
|
should.exist json.date |
||||||
|
json.date.should.be.within now-2000, now+2000 |
||||||
|
should.exist json.body |
||||||
|
json.body.should.be.instanceof Array |
@ -0,0 +1,64 @@ |
|||||||
|
|
||||||
|
var setup = require('../../../controller/search'), |
||||||
|
mockBackend = require('../mock/backend'), |
||||||
|
mockQuery = require('../mock/query'); |
||||||
|
|
||||||
|
module.exports.tests = {}; |
||||||
|
|
||||||
|
module.exports.tests.interface = function(test, common) { |
||||||
|
test('valid interface', function(t) { |
||||||
|
t.equal(typeof setup, 'function', 'setup is a function'); |
||||||
|
t.equal(typeof setup(), 'function', 'setup returns a controller'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
// functionally test controller (backend success)
|
||||||
|
module.exports.tests.functional_success = function(test, common) { |
||||||
|
test('functional test', function(t) { |
||||||
|
var backend = mockBackend( 'client/search/ok/1', function( cmd ){ |
||||||
|
t.deepEqual(cmd, { body: { a: 'b' }, index: 'pelias' }, 'correct backend command'); |
||||||
|
}); |
||||||
|
var controller = setup( backend, mockQuery() ); |
||||||
|
var res = { |
||||||
|
status: function( code ){ |
||||||
|
t.equal(code, 200, 'status set'); |
||||||
|
return res; |
||||||
|
}, |
||||||
|
json: function( json ){ |
||||||
|
t.equal(typeof json, 'object', 'returns json'); |
||||||
|
t.equal(typeof json.date, 'number', 'date set'); |
||||||
|
t.true(Array.isArray(json.body), 'body is array'); |
||||||
|
// t.deepEqual(json.body, [ { value: 1 }, { value: 2 } ], 'values correctly mapped');
|
||||||
|
t.end(); |
||||||
|
} |
||||||
|
}; |
||||||
|
controller( { clean: { a: 'b' } }, res ); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
// functionally test controller (backend failure)
|
||||||
|
module.exports.tests.functional_failure = function(test, common) { |
||||||
|
test('functional test', function(t) { |
||||||
|
var backend = mockBackend( 'client/search/fail/1', function( cmd ){ |
||||||
|
t.deepEqual(cmd, { body: { a: 'b' }, index: 'pelias' }, 'correct backend command'); |
||||||
|
}); |
||||||
|
var controller = setup( backend, mockQuery() ); |
||||||
|
var next = function( message ){ |
||||||
|
t.equal(message,'a backend error occurred','error passed to errorHandler'); |
||||||
|
t.end(); |
||||||
|
}; |
||||||
|
controller( { clean: { a: 'b' } }, undefined, next ); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.all = function (tape, common) { |
||||||
|
|
||||||
|
function test(name, testFunction) { |
||||||
|
return tape('GET /search ' + name, testFunction); |
||||||
|
} |
||||||
|
|
||||||
|
for( var testCase in module.exports.tests ){ |
||||||
|
module.exports.tests[testCase](test, common); |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,64 @@ |
|||||||
|
|
||||||
|
var setup = require('../../../controller/suggest'), |
||||||
|
mockBackend = require('../mock/backend'), |
||||||
|
mockQuery = require('../mock/query'); |
||||||
|
|
||||||
|
module.exports.tests = {}; |
||||||
|
|
||||||
|
module.exports.tests.interface = function(test, common) { |
||||||
|
test('valid interface', function(t) { |
||||||
|
t.equal(typeof setup, 'function', 'setup is a function'); |
||||||
|
t.equal(typeof setup(), 'function', 'setup returns a controller'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
// functionally test controller (backend success)
|
||||||
|
module.exports.tests.functional_success = function(test, common) { |
||||||
|
test('functional test', function(t) { |
||||||
|
var backend = mockBackend( 'client/suggest/ok/1', function( cmd ){ |
||||||
|
t.deepEqual(cmd, { body: { a: 'b' }, index: 'pelias' }, 'correct backend command'); |
||||||
|
}); |
||||||
|
var controller = setup( backend, mockQuery() ); |
||||||
|
var res = { |
||||||
|
status: function( code ){ |
||||||
|
t.equal(code, 200, 'status set'); |
||||||
|
return res; |
||||||
|
}, |
||||||
|
json: function( json ){ |
||||||
|
t.equal(typeof json, 'object', 'returns json'); |
||||||
|
t.equal(typeof json.date, 'number', 'date set'); |
||||||
|
t.true(Array.isArray(json.body), 'body is array'); |
||||||
|
t.deepEqual(json.body, [ { value: 1 }, { value: 2 } ], 'values correctly mapped'); |
||||||
|
t.end(); |
||||||
|
} |
||||||
|
}; |
||||||
|
controller( { clean: { a: 'b' } }, res ); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
// functionally test controller (backend failure)
|
||||||
|
module.exports.tests.functional_failure = function(test, common) { |
||||||
|
test('functional test', function(t) { |
||||||
|
var backend = mockBackend( 'client/suggest/fail/1', function( cmd ){ |
||||||
|
t.deepEqual(cmd, { body: { a: 'b' }, index: 'pelias' }, 'correct backend command'); |
||||||
|
}); |
||||||
|
var controller = setup( backend, mockQuery() ); |
||||||
|
var next = function( message ){ |
||||||
|
t.equal(message,'a backend error occurred','error passed to errorHandler'); |
||||||
|
t.end(); |
||||||
|
}; |
||||||
|
controller( { clean: { a: 'b' } }, undefined, next ); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.all = function (tape, common) { |
||||||
|
|
||||||
|
function test(name, testFunction) { |
||||||
|
return tape('GET /suggest ' + name, testFunction); |
||||||
|
} |
||||||
|
|
||||||
|
for( var testCase in module.exports.tests ){ |
||||||
|
module.exports.tests[testCase](test, common); |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,42 @@ |
|||||||
|
|
||||||
|
var responses = {}; |
||||||
|
responses['client/suggest/ok/1'] = function( cmd, cb ){ |
||||||
|
return cb( undefined, suggestEnvelope([ { value: 1 }, { value: 2 } ]) ); |
||||||
|
}; |
||||||
|
responses['client/suggest/fail/1'] = function( cmd, cb ){ |
||||||
|
return cb( 'a backend error occurred' ); |
||||||
|
}; |
||||||
|
responses['client/search/ok/1'] = function( cmd, cb ){ |
||||||
|
return cb( undefined, searchEnvelope([ { value: 1 }, { value: 2 } ]) ); |
||||||
|
}; |
||||||
|
responses['client/search/fail/1'] = function( cmd, cb ){ |
||||||
|
return cb( 'a backend error occurred' ); |
||||||
|
}; |
||||||
|
|
||||||
|
function setup( key, cmdCb ){ |
||||||
|
function backend( a, b ){ |
||||||
|
return { |
||||||
|
client: { |
||||||
|
suggest: function( cmd, cb ){ |
||||||
|
if( 'function' === typeof cmdCb ){ cmdCb( cmd ); } |
||||||
|
return responses[key].apply( this, arguments ); |
||||||
|
}, |
||||||
|
search: function( cmd, cb ){ |
||||||
|
if( 'function' === typeof cmdCb ){ cmdCb( cmd ); } |
||||||
|
return responses[key].apply( this, arguments ); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
return backend; |
||||||
|
} |
||||||
|
|
||||||
|
function suggestEnvelope( options ){ |
||||||
|
return { pelias: [{ options: options }]}; |
||||||
|
} |
||||||
|
|
||||||
|
function searchEnvelope( options ){ |
||||||
|
return { pelias: [{ options: options }]}; |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = setup; |
@ -0,0 +1,10 @@ |
|||||||
|
|
||||||
|
function setup(){ |
||||||
|
return query; |
||||||
|
} |
||||||
|
|
||||||
|
function query( clean ){ |
||||||
|
return clean; |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = setup; |
@ -0,0 +1,23 @@ |
|||||||
|
|
||||||
|
var indeces = require('../../../query/indeces'); |
||||||
|
|
||||||
|
module.exports.tests = {}; |
||||||
|
|
||||||
|
module.exports.tests.interface = function(test, common) { |
||||||
|
test('valid interface', function(t) { |
||||||
|
t.true(Array.isArray(indeces), 'valid array'); |
||||||
|
t.equal(indeces.length, 7, 'valid array'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.all = function (tape, common) { |
||||||
|
|
||||||
|
function test(name, testFunction) { |
||||||
|
return tape('indeces ' + name, testFunction); |
||||||
|
} |
||||||
|
|
||||||
|
for( var testCase in module.exports.tests ){ |
||||||
|
module.exports.tests[testCase](test, common); |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,52 @@ |
|||||||
|
|
||||||
|
var generate = require('../../../query/reverse'); |
||||||
|
|
||||||
|
module.exports.tests = {}; |
||||||
|
|
||||||
|
module.exports.tests.interface = function(test, common) { |
||||||
|
test('valid interface', function(t) { |
||||||
|
t.equal(typeof generate, 'function', 'valid function'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.query = function(test, common) { |
||||||
|
test('valid query', function(t) { |
||||||
|
var query = generate({ |
||||||
|
lat: 29.49136, lon: -82.50622 |
||||||
|
}); |
||||||
|
var expected = { |
||||||
|
query:{ |
||||||
|
filtered : { |
||||||
|
query : { |
||||||
|
match_all : {} |
||||||
|
}, |
||||||
|
filter : { |
||||||
|
geo_distance : { |
||||||
|
distance : '1km', |
||||||
|
center_point : { |
||||||
|
lat: 29.49136,
|
||||||
|
lon: -82.50622 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
size: 1 |
||||||
|
}; |
||||||
|
|
||||||
|
t.deepEqual(query, expected, 'valid reverse query'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.all = function (tape, common) { |
||||||
|
|
||||||
|
function test(name, testFunction) { |
||||||
|
return tape('reverse query ' + name, testFunction); |
||||||
|
} |
||||||
|
|
||||||
|
for( var testCase in module.exports.tests ){ |
||||||
|
module.exports.tests[testCase](test, common); |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,79 @@ |
|||||||
|
|
||||||
|
var generate = require('../../../query/search'); |
||||||
|
|
||||||
|
module.exports.tests = {}; |
||||||
|
|
||||||
|
module.exports.tests.interface = function(test, common) { |
||||||
|
test('valid interface', function(t) { |
||||||
|
t.equal(typeof generate, 'function', 'valid function'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.query = function(test, common) { |
||||||
|
test('valid query', function(t) { |
||||||
|
var query = generate({ |
||||||
|
input: 'test', size: 10, |
||||||
|
lat: 29.49136, lon: -82.50622, |
||||||
|
bbox: { |
||||||
|
top_left: { |
||||||
|
lat: 11.51053655297385, |
||||||
|
lon: -103.16362455862279 |
||||||
|
}, |
||||||
|
bottom_right: { |
||||||
|
lat: 47.472183447026154, |
||||||
|
lon: -61.84881544137721 |
||||||
|
} |
||||||
|
}, |
||||||
|
layers: ['test'] |
||||||
|
}); |
||||||
|
var expected = { |
||||||
|
query:{ |
||||||
|
query_string : { |
||||||
|
query: 'test', |
||||||
|
fields: ['name.default'], |
||||||
|
default_operator: 'OR' |
||||||
|
} |
||||||
|
}, |
||||||
|
filter: { |
||||||
|
geo_bounding_box: { |
||||||
|
center_point: { |
||||||
|
top_left: { |
||||||
|
lat: 11.51053655297385, |
||||||
|
lon: -103.16362455862279 |
||||||
|
}, |
||||||
|
bottom_right: { |
||||||
|
lat: 47.472183447026154, |
||||||
|
lon: -61.84881544137721 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
sort : [{ |
||||||
|
_geo_distance : { |
||||||
|
center_point : { |
||||||
|
lat: 29.49136,
|
||||||
|
lon: -82.50622
|
||||||
|
}, |
||||||
|
order: 'asc', |
||||||
|
unit: 'km' |
||||||
|
} |
||||||
|
}], |
||||||
|
size: 10 |
||||||
|
}; |
||||||
|
|
||||||
|
t.deepEqual(query, expected, 'valid search query'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.all = function (tape, common) { |
||||||
|
|
||||||
|
function test(name, testFunction) { |
||||||
|
return tape('search query ' + name, testFunction); |
||||||
|
} |
||||||
|
|
||||||
|
for( var testCase in module.exports.tests ){ |
||||||
|
module.exports.tests[testCase](test, common); |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,50 @@ |
|||||||
|
|
||||||
|
var generate = require('../../../query/suggest'); |
||||||
|
|
||||||
|
module.exports.tests = {}; |
||||||
|
|
||||||
|
module.exports.tests.interface = function(test, common) { |
||||||
|
test('valid interface', function(t) { |
||||||
|
t.equal(typeof generate, 'function', 'valid function'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.query = function(test, common) { |
||||||
|
test('valid query', function(t) { |
||||||
|
var query = generate({ |
||||||
|
input: 'test', size: 10, |
||||||
|
lat: 0, lon: 0, |
||||||
|
layers: ['test'] |
||||||
|
}); |
||||||
|
var expected = { |
||||||
|
pelias: { |
||||||
|
text: 'test', |
||||||
|
completion: { |
||||||
|
field: 'suggest', |
||||||
|
size: 10, |
||||||
|
context: { |
||||||
|
dataset: [ 'test' ], |
||||||
|
location: { |
||||||
|
precision: 2, |
||||||
|
value: [ 0, 0 ] |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
t.deepEqual(query, expected, 'valid suggest query'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.all = function (tape, common) { |
||||||
|
|
||||||
|
function test(name, testFunction) { |
||||||
|
return tape('suggest query ' + name, testFunction); |
||||||
|
} |
||||||
|
|
||||||
|
for( var testCase in module.exports.tests ){ |
||||||
|
module.exports.tests[testCase](test, common); |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,203 @@ |
|||||||
|
|
||||||
|
var sanitize = require('../../../sanitiser/sanitise'), |
||||||
|
defaultError = 'invalid param \'input\': text length, must be >0', |
||||||
|
defaultClean = { input: 'test', lat: 0, layers: [ 'geoname', 'osmnode', 'osmway', 'admin0', 'admin1', 'admin2', 'neighborhood' ], lon: 0, size: 10, zoom: 10 }; |
||||||
|
|
||||||
|
module.exports.tests = {}; |
||||||
|
|
||||||
|
module.exports.tests.interface = function(test, common) { |
||||||
|
test('sanitize interface', function(t) { |
||||||
|
t.equal(typeof sanitize, 'function', 'sanitize is a function'); |
||||||
|
t.equal(sanitize.length, 2, 'sanitize interface'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
test('middleware interface', function(t) { |
||||||
|
t.equal(typeof sanitize.middleware, 'function', 'middleware is a function'); |
||||||
|
t.equal(sanitize.middleware.length, 3, 'sanitize is valid middleware'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.sanitize_input = function(test, common) { |
||||||
|
var inputs = { |
||||||
|
invalid: [ '', 100, null, undefined, new Date() ], |
||||||
|
valid: [ 'a', 'aa', 'aaaaaaaa' ] |
||||||
|
}; |
||||||
|
inputs.invalid.forEach( function( input ){ |
||||||
|
test('invalid input', function(t) { |
||||||
|
sanitize({ input: input, lat: 0, lon: 0 }, function( err, clean ){ |
||||||
|
t.equal(err, 'invalid param \'input\': text length, must be >0', 'invalid input'); |
||||||
|
t.equal(clean, undefined, 'clean not set'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
inputs.valid.forEach( function( input ){ |
||||||
|
test('valid input', function(t) { |
||||||
|
sanitize({ input: input, lat: 0, lon: 0 }, function( err, clean ){ |
||||||
|
var expected = JSON.parse(JSON.stringify( defaultClean )); |
||||||
|
expected.input = input; |
||||||
|
t.equal(err, undefined, 'no error'); |
||||||
|
t.deepEqual(clean, expected, 'clean set correctly'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.sanitize_lat = function(test, common) { |
||||||
|
var lats = { |
||||||
|
invalid: [ -1, -45, -90, 91, 120, 181 ], |
||||||
|
valid: [ 0, 45, 90, -0, '0', '45', '90' ] |
||||||
|
}; |
||||||
|
lats.invalid.forEach( function( lat ){ |
||||||
|
test('invalid lat', function(t) { |
||||||
|
sanitize({ input: 'test', lat: lat, lon: 0 }, function( err, clean ){ |
||||||
|
t.equal(err, 'invalid param \'lat\': must be >0 and <90', 'invalid latitude'); |
||||||
|
t.equal(clean, undefined, 'clean not set'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
lats.valid.forEach( function( lat ){ |
||||||
|
test('valid lat', function(t) { |
||||||
|
sanitize({ input: 'test', lat: lat, lon: 0 }, function( err, clean ){ |
||||||
|
var expected = JSON.parse(JSON.stringify( defaultClean )); |
||||||
|
expected.lat = parseFloat( lat ); |
||||||
|
t.equal(err, undefined, 'no error'); |
||||||
|
t.deepEqual(clean, expected, 'clean set correctly'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.sanitize_lon = function(test, common) { |
||||||
|
var lons = { |
||||||
|
invalid: [ -360, -181, 181, 360 ], |
||||||
|
valid: [ -180, -1, -0, 0, 45, 90, '-180', '0', '180' ] |
||||||
|
}; |
||||||
|
lons.invalid.forEach( function( lon ){ |
||||||
|
test('invalid lon', function(t) { |
||||||
|
sanitize({ input: 'test', lat: 0, lon: lon }, function( err, clean ){ |
||||||
|
t.equal(err, 'invalid param \'lon\': must be >-180 and <180', 'invalid longitude'); |
||||||
|
t.equal(clean, undefined, 'clean not set'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
lons.valid.forEach( function( lon ){ |
||||||
|
test('valid lon', function(t) { |
||||||
|
sanitize({ input: 'test', lat: 0, lon: lon }, function( err, clean ){ |
||||||
|
var expected = JSON.parse(JSON.stringify( defaultClean )); |
||||||
|
expected.lon = parseFloat( lon ); |
||||||
|
t.equal(err, undefined, 'no error'); |
||||||
|
t.deepEqual(clean, expected, 'clean set correctly'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.sanitize_zoom = function(test, common) { |
||||||
|
test('invalid zoom value', function(t) { |
||||||
|
sanitize({ zoom: 'a', input: 'test', lat: 0, lon: 0 }, function( err, clean ){ |
||||||
|
t.equal(clean.zoom, 10, 'default zoom set'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
test('below min zoom value', function(t) { |
||||||
|
sanitize({ zoom: -100, input: 'test', lat: 0, lon: 0 }, function( err, clean ){ |
||||||
|
t.equal(clean.zoom, 1, 'min zoom set'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
test('above max zoom value', function(t) { |
||||||
|
sanitize({ zoom: 9999, input: 'test', lat: 0, lon: 0 }, function( err, clean ){ |
||||||
|
t.equal(clean.zoom, 18, 'max zoom set'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.sanitize_size = function(test, common) { |
||||||
|
test('invalid size value', function(t) { |
||||||
|
sanitize({ size: 'a', input: 'test', lat: 0, lon: 0 }, function( err, clean ){ |
||||||
|
t.equal(clean.size, 10, 'default size set'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
test('below min size value', function(t) { |
||||||
|
sanitize({ size: -100, input: 'test', lat: 0, lon: 0 }, function( err, clean ){ |
||||||
|
t.equal(clean.size, 1, 'min size set'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
test('above max size value', function(t) { |
||||||
|
sanitize({ size: 9999, input: 'test', lat: 0, lon: 0 }, function( err, clean ){ |
||||||
|
t.equal(clean.size, 40, 'max size set'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.sanitize_layers = function(test, common) { |
||||||
|
test('unspecified', function(t) { |
||||||
|
sanitize({ layers: undefined, input: 'test', lat: 0, lon: 0 }, function( err, clean ){ |
||||||
|
t.deepEqual(clean.layers, defaultClean.layers, 'default layers set'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
test('invalid layer', function(t) { |
||||||
|
sanitize({ layers: 'test_layer', input: 'test', lat: 0, lon: 0 }, function( err, clean ){ |
||||||
|
var msg = 'invalid param \'layer\': must be one or more of geoname,osmnode,osmway,admin0,admin1,admin2,neighborhood'; |
||||||
|
t.equal(err, msg, 'invalid layer requested'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.invalid_params = function(test, common) { |
||||||
|
test('invalid input params', function(t) { |
||||||
|
sanitize( undefined, function( err, clean ){ |
||||||
|
t.equal(err, defaultError, 'handle invalid params gracefully'); |
||||||
|
t.end(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.middleware_failure = function(test, common) { |
||||||
|
test('middleware failure', function(t) { |
||||||
|
var res = { status: function( code ){ |
||||||
|
t.equal(code, 400, 'status set'); |
||||||
|
}}; |
||||||
|
var next = function( message ){ |
||||||
|
t.equal(message, defaultError); |
||||||
|
t.end(); |
||||||
|
}; |
||||||
|
sanitize.middleware( {}, res, next ); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.tests.middleware_success = function(test, common) { |
||||||
|
test('middleware success', function(t) { |
||||||
|
var req = { query: { input: 'test', lat: 0, lon: 0 }}; |
||||||
|
var next = function( message ){ |
||||||
|
t.equal(message, undefined, 'no error message set'); |
||||||
|
t.deepEqual(req.clean, defaultClean); |
||||||
|
t.end(); |
||||||
|
}; |
||||||
|
sanitize.middleware( req, undefined, next ); |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
module.exports.all = function (tape, common) { |
||||||
|
|
||||||
|
function test(name, testFunction) { |
||||||
|
return tape('SANTIZE /sanitise ' + name, testFunction); |
||||||
|
} |
||||||
|
|
||||||
|
for( var testCase in module.exports.tests ){ |
||||||
|
module.exports.tests[testCase](test, common); |
||||||
|
} |
||||||
|
}; |
Loading…
Reference in new issue