Browse Source

Remove proxyquire from adminField test

Add comments and refactor a bit more for clarity in query/search.js
pull/192/head
Diana Shkolnikov 10 years ago
parent
commit
743d8efa54
  1. 24
      helper/adminFields.js
  2. 76
      query/search.js
  3. 72
      test/unit/helper/adminFields.js

24
helper/adminFields.js

@ -1,5 +1,5 @@
var schema = require('pelias-schema'); var peliasSchema = require('pelias-schema');
var logger = require( 'pelias-logger' ).get( 'api' ); var peliasLogger = require( 'pelias-logger' ).get( 'api' );
var ADMIN_FIELDS = [ var ADMIN_FIELDS = [
'admin0', 'admin0',
@ -11,11 +11,24 @@ var ADMIN_FIELDS = [
'neighborhood' 'neighborhood'
]; ];
function getAvailableAdminFields() { /**
* Get all admin fields that were expected and also found in schema
*
* @param {Object} [schema] optional: for testing only
* @param {Array} [expectedFields] optional: for testing only
* @param {Object} [logger] optional: for testing only
* @returns {Array.<string>}
*/
function getAvailableAdminFields(schema, expectedFields, logger) {
schema = schema || peliasSchema;
expectedFields = expectedFields || ADMIN_FIELDS;
logger = logger || peliasLogger;
var actualFields = Object.keys(schema.mappings._default_.properties); var actualFields = Object.keys(schema.mappings._default_.properties);
// check if expected fields are actually in current schema // check if expected fields are actually in current schema
var available = ADMIN_FIELDS.filter(function (field) { var available = expectedFields.filter(function (field) {
return (actualFields.indexOf(field) !== -1); return (actualFields.indexOf(field) !== -1);
}); });
@ -26,5 +39,4 @@ function getAvailableAdminFields() {
return available; return available;
} }
module.exports.availableFields = getAvailableAdminFields(); module.exports = getAvailableAdminFields;
module.exports.expectedFields = ADMIN_FIELDS;

76
query/search.js

@ -1,7 +1,7 @@
var queries = require('geopipes-elasticsearch-backend').queries, var queries = require('geopipes-elasticsearch-backend').queries,
sort = require('../query/sort'), sort = require('../query/sort'),
adminFields = require('../helper/adminFields').availableFields, adminFields = require('../helper/adminFields')(),
addressWeights = require('../helper/address_weights'); addressWeights = require('../helper/address_weights');
@ -60,8 +60,16 @@ function generate( params ){
return query; return query;
} }
/**
* Traverse the parsed input object, containing all the address parts detected in query string.
* Add matches to query for each identifiable component.
*
* @param {Object} query
* @param {string} defaultInput
* @param {Object} parsedInput
*/
function addParsedMatch(query, defaultInput, parsedInput) { function addParsedMatch(query, defaultInput, parsedInput) {
query.query.filtered.query.bool.should = []; query.query.filtered.query.bool.should = query.query.filtered.query.bool.should || [];
// copy expected admin fields so we can remove them as we parse the address // copy expected admin fields so we can remove them as we parse the address
var unmatchedAdminFields = adminFields.slice(); var unmatchedAdminFields = adminFields.slice();
@ -74,7 +82,7 @@ function addParsedMatch(query, defaultInput, parsedInput) {
// city // city
// admin2, locality, local_admin, neighborhood // admin2, locality, local_admin, neighborhood
addMatch(query, unmatchedAdminFields, 'admin2', parsedInput.admin2, addressWeights.admin2); addMatch(query, unmatchedAdminFields, 'admin2', parsedInput.city, addressWeights.admin2);
// state // state
// admin1, admin1_abbr // admin1, admin1_abbr
@ -84,20 +92,54 @@ function addParsedMatch(query, defaultInput, parsedInput) {
// admin0, alpha3 // admin0, alpha3
addMatch(query, unmatchedAdminFields, 'alpha3', parsedInput.country, addressWeights.alpha3); addMatch(query, unmatchedAdminFields, 'alpha3', parsedInput.country, addressWeights.alpha3);
var inputRegions = parsedInput.regions ? parsedInput.regions.join(' ') : undefined; addUnmatchedAdminFieldsToQuery(query, unmatchedAdminFields, parsedInput, defaultInput);
// if no address was identified and input suggests some admin info in it }
if (unmatchedAdminFields.length > 0 && inputRegions !== defaultInput) {
/**
* Check for additional admin fields in the parsed input, and if any was found
* combine into single string and match against all unmatched admin fields.
*
* @param {Object} query
* @param {Array} unmatchedAdminFields
* @param {Object} parsedInput
* @param {string} defaultInput
*/
function addUnmatchedAdminFieldsToQuery(query, unmatchedAdminFields, parsedInput, defaultInput) {
if (unmatchedAdminFields.length === 0 ) {
return;
}
var leftovers = [];
if (parsedInput.admin_parts) {
leftovers.push(parsedInput.admin_parts);
}
else if (parsedInput.regions) {
leftovers.push(parsedInput.regions);
}
if (leftovers.length === 0) {
return;
}
// if there are additional regions/admin_parts found
if (leftovers !== defaultInput) {
unmatchedAdminFields.forEach(function (key) { unmatchedAdminFields.forEach(function (key) {
if (parsedInput.admin_parts) { // combine all the leftover parts into one string
addMatch(query, [], key, parsedInput.admin_parts); addMatch(query, [], key, leftovers.join(' '));
}
else {
addMatch(query, [], key, inputRegions);
}
}); });
} }
} }
/**
* Add key:value match to query. Apply boost if specified.
*
* @param {Object} query
* @param {Array} unmatched
* @param {string} key
* @param {string|number|undefined} value
* @param {number|undefined} [boost] optional
*/
function addMatch(query, unmatched, key, value, boost) { // jshint ignore:line function addMatch(query, unmatched, key, value, boost) { // jshint ignore:line
if (typeof value === 'undefined') { if (typeof value === 'undefined') {
return; return;
@ -117,6 +159,16 @@ function addMatch(query, unmatched, key, value, boost) { // jshint ignore:line
query.query.filtered.query.bool.should.push({ 'match': match }); query.query.filtered.query.bool.should.push({ 'match': match });
removeFromUnmatched(unmatched, key);
}
/**
* If key is found in unmatched list, remove it from the array
*
* @param {Array} unmatched
* @param {string} key
*/
function removeFromUnmatched(unmatched, key) {
var index = unmatched.indexOf(key); var index = unmatched.indexOf(key);
if (index !== -1) { if (index !== -1) {
unmatched.splice(index, 1); unmatched.splice(index, 1);

72
test/unit/helper/adminFields.js

@ -1,18 +1,12 @@
var proxyquire = require('proxyquire'); var adminFields = require('../../../helper/adminFields');
module.exports.tests = {}; module.exports.tests = {};
module.exports.tests.interface = function(test, common) { module.exports.tests.interface = function(test, common) {
test('validate fields', function(t) { test('validate fields', function(t) {
var adminFields = require('../../../helper/adminFields').availableFields; t.assert(adminFields instanceof Function, 'adminFields is a function');
t.assert(adminFields instanceof Array, 'adminFields is an array'); t.assert(adminFields() instanceof Array, 'adminFields() returns an array');
t.assert(adminFields.length > 0, 'adminFields array is not empty'); t.assert(adminFields().length > 0, 'adminFields array is not empty');
t.end();
});
test('validate fields', function(t) {
var adminFields = require('../../../helper/adminFields').expectedFields;
t.assert(adminFields instanceof Array, 'adminFields is an array');
t.assert(adminFields.length > 0, 'adminFields array is not empty');
t.end(); t.end();
}); });
}; };
@ -20,54 +14,60 @@ module.exports.tests.interface = function(test, common) {
module.exports.tests.lookupExistance = function(test, common) { module.exports.tests.lookupExistance = function(test, common) {
test('all expected fields in schema', function(t) { test('all expected fields in schema', function(t) {
var expectedFields = require('../../../helper/adminFields').expectedFields; var expectedFields = [
var schemaMock = { mappings: { _default_: { properties: {} } } }; 'one',
'two',
'three',
'four'
];
var schema = { mappings: { _default_: { properties: {} } } };
// inject all expected fields into schema mock // inject all expected fields into schema mock
expectedFields.forEach(function (field) { expectedFields.forEach(function (field) {
schemaMock.mappings._default_.properties[field] = {}; schema.mappings._default_.properties[field] = {};
}); });
var adminFields = proxyquire('../../../helper/adminFields', {'pelias-schema': schemaMock}); var res = adminFields(schema, expectedFields);
t.deepEquals(adminFields.availableFields, adminFields.expectedFields, 'all expected fields are returned'); t.deepEquals(res, expectedFields, 'all expected fields are returned');
t.end(); t.end();
}); });
test('some expected fields in schema', function(t) { test('some expected fields in schema', function(t) {
var expectedFields = require('../../../helper/adminFields').expectedFields.slice(0, 3); var expectedFields = [
var schemaMock = { mappings: { _default_: { properties: {} } } }; 'one',
'two',
// inject all expected fields into schema mock 'three',
expectedFields.forEach(function (field) { 'four'
schemaMock.mappings._default_.properties[field] = {}; ];
var schema = { mappings: { _default_: { properties: {} } } };
// inject only some of the expected fields into schema mock
expectedFields.slice(0, 3).forEach(function (field) {
schema.mappings._default_.properties[field] = {};
}); });
var adminFields = proxyquire('../../../helper/adminFields', {'pelias-schema': schemaMock}); var res = adminFields(schema, expectedFields);
t.deepEquals(adminFields.availableFields, expectedFields, 'only matching expected fields are returned'); t.deepEquals(res, expectedFields.slice(0, 3), 'only matching expected fields are returned');
t.end(); t.end();
}); });
test('no expected fields in schema', function(t) { test('no expected fields in schema', function(t) {
var schemaMock = { mappings: { _default_: { properties: { foo: {} } } } }; var schema = { mappings: { _default_: { properties: { foo: {} } } } };
var loggerMock = { get: function (name) { var logErrorCalled = false;
t.equal(name, 'api'); var logger = {
return { error: function () {
error: function () {} logErrorCalled = true;
}; }};
}};
var adminFields = proxyquire('../../../helper/adminFields', var res = adminFields(schema, undefined, logger);
{
'pelias-schema': schemaMock,
'pelias-logger': loggerMock
});
t.deepEquals([], adminFields.availableFields, 'no admin fields found'); t.deepEquals(res, [], 'no admin fields found');
t.assert(logErrorCalled, 'log error called');
t.end(); t.end();
}); });
}; };

Loading…
Cancel
Save