diff --git a/.jshintrc b/.jshintrc index f9df9b9..e005239 100644 --- a/.jshintrc +++ b/.jshintrc @@ -2,6 +2,7 @@ "node": true, "curly": true, "eqeqeq": true, + "esversion": 6, "freeze": true, "immed": true, "indent": 2, diff --git a/Document.js b/Document.js index 046654a..17d0bf1 100644 --- a/Document.js +++ b/Document.js @@ -6,6 +6,24 @@ var valid = require('./util/valid'); var transform = require('./util/transform'); var _ = require('lodash'); +const addressFields = ['name', 'number', 'street', 'zip']; + +const parentFields = [ + 'continent', + 'country', + 'dependency', + 'macroregion', + 'region', + 'macrocounty', + 'county', + 'borough', + 'locality', + 'localadmin', + 'macrohood', + 'neighbourhood', + 'postalcode' +]; + function Document( source, layer, source_id ){ this.name = {}; this.phrase = {}; @@ -15,8 +33,10 @@ function Document( source, layer, source_id ){ this.category = []; // initialize 'parent' fields to empty arrays - Document.parentFields.forEach( function(field){ + parentFields.forEach( (field) => { this.parent[field] = []; + this.parent[`${field}_a`] = []; + this.parent[`${field}_id`] = []; }, this); // create a non-enumerable property for metadata @@ -207,7 +227,7 @@ Document.prototype.clearParent = function(field) { // address Document.prototype.setAddress = function ( prop, val ){ return model.setChild( 'address_parts' ) - .validate( valid.property( Document.addressFields ) ) + .validate( valid.property( addressFields ) ) .validate( valid.type('string') ) .validate( valid.truthy() ) .call( this, prop, val ); @@ -298,22 +318,14 @@ Document.prototype.setBoundingBox = model.set( 'bounding_box' ) // marshal the internal bounding_box back into the representation the caller supplied Document.prototype.getBoundingBox = model.get('bounding_box'); -Document.addressFields = ['name', 'number', 'street', 'zip']; - -Document.parentFields = [ - 'continent', 'continent_a', 'continent_id', - 'country', 'country_a', 'country_id', - 'dependency', 'dependency_a', 'dependency_id', - 'macroregion', 'macroregion_a', 'macroregion_id', - 'region', 'region_a', 'region_id', - 'macrocounty', 'macrocounty_a', 'macrocounty_id', - 'county', 'county_a', 'county_id', - 'borough', 'borough_a', 'borough_id', - 'locality', 'locality_a', 'locality_id', - 'localadmin', 'localadmin_a', 'localadmin_id', - 'neighbourhood', 'neighbourhood_a', 'neighbourhood_id', - 'postalcode', 'postalcode_a', 'postalcode_id' -]; +Document.prototype.isSupportedParent = (placetype) => { + return parentFields.indexOf(placetype) !== -1; +}; + +// return a clone so it's immutable +Document.prototype.getParentFields = () => { + return _.cloneDeep(parentFields); +}; // export module.exports = Document; diff --git a/test/Document.js b/test/Document.js index e338f60..9733d50 100644 --- a/test/Document.js +++ b/test/Document.js @@ -1,4 +1,3 @@ - var Document = require('../Document'); module.exports.tests = {}; @@ -38,7 +37,7 @@ module.exports.tests.constructor = function(test) { // initialize 'parent' fields to empty arrays t.equal(typeof doc.parent, 'object', 'initial value'); - Document.parentFields.forEach( function(field){ + doc.getParentFields().forEach( function(field){ t.true(Array.isArray(doc.parent[field]), 'initial value'); }); @@ -74,6 +73,69 @@ module.exports.tests.clearParent = function(test) { }); }; +module.exports.tests.parent_types = (test) => { + test('supported WOF placetypes should return true', (t) => { + const doc = new Document('mysource', 'mylayer', 'myid'); + + t.deepEquals(doc.getParentFields(), [ + 'continent', + 'country', + 'dependency', + 'macroregion', + 'region', + 'macrocounty', + 'county', + 'borough', + 'locality', + 'localadmin', + 'macrohood', + 'neighbourhood', + 'postalcode' + ]); + + t.end(); + + }); + + test('supported WOF placetypes should return true', (t) => { + const doc = new Document('mysource', 'mylayer', 'myid'); + + doc.getParentFields().forEach((type) => { + t.ok(doc.isSupportedParent(type), `${type} should be supported`); + }); + + t.end(); + + }); + + test('abbreviation and id names for WOF placetypes should return false', (t) => { + const doc = new Document('mysource', 'mylayer', 'myid'); + + // this verifies that _a and _id parents aren't supported + doc.getParentFields().forEach((type) => { + t.notOk(doc.isSupportedParent(`${type}_a`), `${type}_a should not be supported`); + t.notOk(doc.isSupportedParent(`${type}_id`), `${type}_id should not be supported`); + }); + + t.end(); + + }); + + test('non-WOF placetype arguments should return false', (t) => { + const doc = new Document('mysource', 'mylayer', 'myid'); + + const placetype = 'unsupported placetype'; + + // push a new placetype to show that it's a clone of the internal list + doc.getParentFields().push(placetype); + + t.notOk(doc.isSupportedParent(placetype), 'should be false'); + t.end(); + + }); + +}; + module.exports.all = function (tape, common) { function test(name, testFunction) { diff --git a/test/serialize/test.js b/test/serialize/test.js index 53eda82..4770bb1 100644 --- a/test/serialize/test.js +++ b/test/serialize/test.js @@ -57,6 +57,9 @@ module.exports.tests.minimal = function(test) { 'macroregion': [], 'macroregion_a': [], 'macroregion_id': [], + 'macrohood': [], + 'macrohood_a': [], + 'macrohood_id': [], 'neighbourhood': [], 'neighbourhood_a': [], 'neighbourhood_id': [], @@ -160,6 +163,9 @@ module.exports.tests.complete = function(test) { 'macroregion': [], 'macroregion_a': [], 'macroregion_id': [], + 'macrohood': [], + 'macrohood_a': [], + 'macrohood_id': [], 'neighbourhood': ['Shoreditch'], 'neighbourhood_a': [null], 'neighbourhood_id': ['2002'],