Browse Source

refactored geojsonify, improved test coverage

pull/1002/head
Stephen Hess 7 years ago
parent
commit
5e1360f022
  1. 61
      helper/geojsonify.js
  2. 875
      test/unit/helper/geojsonify.js

61
helper/geojsonify.js

@ -1,26 +1,32 @@
var GeoJSON = require('geojson'); const GeoJSON = require('geojson');
var extent = require('@mapbox/geojson-extent'); const extent = require('@mapbox/geojson-extent');
var logger = require('pelias-logger').get('api'); const logger = require('pelias-logger').get('geojsonify');
var addDetails = require('./geojsonify_place_details'); const addDetails = require('./geojsonify_place_details');
var addMetaData = require('./geojsonify_meta_data'); const addMetaData = require('./geojsonify_meta_data');
const _ = require('lodash');
function geojsonifyPlaces( params, docs ){ function geojsonifyPlaces( params, docs ){
// flatten & expand data for geojson conversion // flatten & expand data for geojson conversion
var geodata = docs const geodata = docs
.map(geojsonifyPlace.bind(null, params)) .filter(doc => {
.filter( function( doc ){ if (!_.has(doc, 'center_point')) {
return !!doc; logger.warn('No doc or center_point property');
}); return false;
} else {
return true;
}
})
.map(geojsonifyPlace.bind(null, params));
// get all the bounding_box corners as well as single points // get all the bounding_box corners as well as single points
// to be used for computing the overall bounding_box for the FeatureCollection // to be used for computing the overall bounding_box for the FeatureCollection
var extentPoints = extractExtentPoints(geodata); const extentPoints = extractExtentPoints(geodata);
// convert to geojson // convert to geojson
var geojson = GeoJSON.parse( geodata, { Point: ['lat', 'lng'] }); const geojson = GeoJSON.parse( geodata, { Point: ['lat', 'lng'] });
var geojsonExtentPoints = GeoJSON.parse( extentPoints, { Point: ['lat', 'lng'] }); const geojsonExtentPoints = GeoJSON.parse( extentPoints, { Point: ['lat', 'lng'] });
// to insert the bbox property at the top level of each feature, it must be done separately after // to insert the bbox property at the top level of each feature, it must be done separately after
// initial geojson construction is finished // initial geojson construction is finished
@ -33,13 +39,7 @@ function geojsonifyPlaces( params, docs ){
} }
function geojsonifyPlace(params, place) { function geojsonifyPlace(params, place) {
const output = {};
// something went very wrong
if( !place || !place.hasOwnProperty( 'center_point' ) ) {
return warning('No doc or center_point property');
}
var output = {};
addMetaData(place, output); addMetaData(place, output);
addName(place, output); addName(place, output);
@ -60,9 +60,11 @@ function geojsonifyPlace(params, place) {
* @param {object} dst * @param {object} dst
*/ */
function addName(src, dst) { function addName(src, dst) {
// map name if (_.has(src, 'name.default')) {
if( !src.name || !src.name.default ) { return warning(src); }
dst.name = src.name.default; dst.name = src.name.default;
} else {
logger.warn(`doc ${dst.gid} does not contain name.default`);
}
} }
/** /**
@ -71,7 +73,7 @@ function addName(src, dst) {
* @param {object} geojson * @param {object} geojson
*/ */
function addBBoxPerFeature(geojson) { function addBBoxPerFeature(geojson) {
geojson.features.forEach(function (feature) { geojson.features.forEach(feature => {
if (!feature.properties.hasOwnProperty('bounding_box')) { if (!feature.properties.hasOwnProperty('bounding_box')) {
return; return;
@ -99,7 +101,7 @@ function addBBoxPerFeature(geojson) {
* @returns {Array} * @returns {Array}
*/ */
function extractExtentPoints(geodata) { function extractExtentPoints(geodata) {
var extentPoints = []; const extentPoints = [];
geodata.forEach(function (place) { geodata.forEach(function (place) {
if (place.bounding_box) { if (place.bounding_box) {
extentPoints.push({ extentPoints.push({
@ -142,15 +144,4 @@ function computeBBox(geojson, geojsonExtentPoints) {
} }
} }
/**
* emit a warning if the doc format is invalid
*
* @note: if you see this error, fix it ASAP!
*/
function warning( doc ) {
console.error( 'error: invalid doc', __filename, doc);
return false; // remove offending doc from results
}
module.exports = geojsonifyPlaces; module.exports = geojsonifyPlaces;

875
test/unit/helper/geojsonify.js

@ -1,5 +1,6 @@
const geojsonify = require('../../../helper/geojsonify');
var geojsonify = require('../../../helper/geojsonify'); const proxyquire = require('proxyquire').noCallThru();
module.exports.tests = {}; module.exports.tests = {};
@ -36,433 +37,565 @@ module.exports.tests.earth = function(test, common) {
}; };
module.exports.tests.geojsonify = function(test, common) { module.exports.tests.all = (test, common) => {
test('bounding_box should be calculated using points when avaiable', t => {
test('geojsonify(doc)', function(t) { const input = [
var input = [
{ {
'_id': 'id1', _id: 'id 1',
'_type': 'layer1', source: 'source 1',
'source': 'source1', source_id: 'source_id 1',
'source_id': 'source_id_1', layer: 'layer 1',
'layer': 'layer1', name: {
'center_point': { default: 'name 1',
'lat': 51.5337144,
'lon': -0.1069716
}, },
'name': { center_point: {
'default': '\'Round Midnight Jazz and Blues Bar' lat: 12.121212,
}, lon: 21.212121
'housenumber': '13', }
'street': 'Liverpool Road',
'postalcode': 'N1 0RW',
'country_a': 'GBR',
'country': 'United Kingdom',
'dependency': 'dependency name',
'region': 'Islington',
'region_a': 'ISL',
'macroregion': 'England',
'county': 'Angel',
'localadmin': 'test1',
'locality': 'test2',
'neighbourhood': 'test3',
'category': [
'food',
'nightlife'
],
'label': 'label for id id1'
}, },
{ {
'_id': 'id2', _id: 'id 2',
'_type': 'layer2', source: 'source 2',
'source': 'source2', source_id: 'source_id 2',
'source_id': 'source_id_2', layer: 'layer 2',
'layer': 'layer2', name: {
'name': { default: 'name 2',
'default': 'Blues Cafe'
}, },
'center_point': { center_point: {
'lat': '51.517806', lat: 13.131313,
'lon': '-0.101795' lon: 31.313131
}, }
'country_a': 'GBR', }
'country': 'United Kingdom', ];
'dependency': 'dependency name',
'region': 'City And County Of The City Of London', const geojsonify = proxyquire('../../../helper/geojsonify', {
'region_a': 'COL', './geojsonify_place_details': (params, source, dst) => {
'macroregion': 'England', if (source._id === 'id 1') {
'county': 'Smithfield', dst.property1 = 'property 1';
'localadmin': 'test1', dst.property2 = 'property 2';
'locality': 'test2', } else if (source._id === 'id 2') {
'neighbourhood': 'test3', dst.property3 = 'property 3';
'label': 'label for id id2' dst.property4 = 'property 4';
}
}
});
const actual = geojsonify({}, input);
const expected = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ 21.212121, 12.121212 ]
},
properties: {
id: 'id 1',
gid: 'source 1:layer 1:id 1',
layer: 'layer 1',
source: 'source 1',
source_id: 'source_id 1',
name: 'name 1',
property1: 'property 1',
property2: 'property 2'
}
}, },
{ {
'_id': 'node:34633854', type: 'Feature',
'_type': 'venue', geometry: {
'source': 'openstreetmap', type: 'Point',
'source_id': 'source_id_3', coordinates: [ 31.313131, 13.131313 ]
'layer': 'venue',
'name': {
'default': 'Empire State Building'
}, },
'center_point': { properties: {
'lat': '40.748432', id: 'id 2',
'lon': '-73.985656' gid: 'source 2:layer 2:id 2',
}, layer: 'layer 2',
'country_a': 'USA', source: 'source 2',
'country': 'United States', source_id: 'source_id 2',
'dependency': 'dependency name', name: 'name 2',
'region': 'New York', property3: 'property 3',
'region_a': 'NY', property4: 'property 4'
'county': 'New York', }
'borough': 'Manhattan', }
'locality': 'New York',
'neighbourhood': 'Koreatown',
'category': [
'tourism',
'transport'
], ],
'label': 'label for id node:34633854' bbox: [21.212121, 12.121212, 31.313131, 13.131313]
};
t.deepEquals(actual, expected);
t.end();
});
test('bounding_box should be calculated using polygons when avaiable', t => {
const input = [
{
_id: 'id 1',
source: 'source 1',
source_id: 'source_id 1',
layer: 'layer 1',
name: {
default: 'name 1',
},
bounding_box: {
min_lon: 1,
min_lat: 1,
max_lon: 2,
max_lat: 2
},
center_point: {
lat: 12.121212,
lon: 21.212121
}
},
{
_id: 'id 2',
source: 'source 2',
source_id: 'source_id 2',
layer: 'layer 2',
name: {
default: 'name 2',
},
bounding_box: {
min_lon: -3,
min_lat: -3,
max_lon: -1,
max_lat: -1
},
center_point: {
lat: 13.131313,
lon: 31.313131
}
} }
]; ];
var expected = { const geojsonify = proxyquire('../../../helper/geojsonify', {
'type': 'FeatureCollection', './geojsonify_place_details': (params, source, dst) => {
'bbox': [ -73.985656, 40.748432, -0.101795, 51.5337144 ], if (source._id === 'id 1') {
'features': [ dst.property1 = 'property 1';
dst.property2 = 'property 2';
} else if (source._id === 'id 2') {
dst.property3 = 'property 3';
dst.property4 = 'property 4';
}
}
});
const actual = geojsonify({}, input);
const expected = {
type: 'FeatureCollection',
features: [
{ {
'type': 'Feature', type: 'Feature',
'geometry': { geometry: {
'type': 'Point', type: 'Point',
'coordinates': [ coordinates: [ 21.212121, 12.121212 ]
-0.1069716, },
51.5337144 properties: {
] id: 'id 1',
}, gid: 'source 1:layer 1:id 1',
'properties': { layer: 'layer 1',
'id': 'id1', source: 'source 1',
'gid': 'source1:layer1:id1', source_id: 'source_id 1',
'layer': 'layer1', name: 'name 1',
'source': 'source1', property1: 'property 1',
'source_id': 'source_id_1', property2: 'property 2'
'name': '\'Round Midnight Jazz and Blues Bar', },
'country_a': 'GBR', bbox: [ 1, 1, 2, 2 ]
'country': 'United Kingdom', },
'dependency': 'dependency name', {
'macroregion': 'England', type: 'Feature',
'region': 'Islington', geometry: {
'region_a': 'ISL', type: 'Point',
'county': 'Angel', coordinates: [ 31.313131, 13.131313 ]
'localadmin': 'test1', },
'locality': 'test2', properties: {
'neighbourhood': 'test3', id: 'id 2',
'housenumber': '13', gid: 'source 2:layer 2:id 2',
'street': 'Liverpool Road', layer: 'layer 2',
'postalcode': 'N1 0RW', source: 'source 2',
'category': [ source_id: 'source_id 2',
'food', name: 'name 2',
'nightlife' property3: 'property 3',
property4: 'property 4'
},
bbox: [ -3, -3, -1, -1 ]
}
], ],
'label': 'label for id id1' bbox: [ -3, -3, 2, 2 ]
};
t.deepEquals(actual, expected);
t.end();
});
test('bounding_box should be calculated using polygons AND points when avaiable', t => {
const input = [
{
_id: 'id 1',
source: 'source 1',
source_id: 'source_id 1',
layer: 'layer 1',
name: {
default: 'name 1',
},
center_point: {
lat: 12.121212,
lon: 21.212121
} }
}, },
{ {
'type': 'Feature', _id: 'id 2',
'geometry': { source: 'source 2',
'type': 'Point', source_id: 'source_id 2',
'coordinates': [ layer: 'layer 2',
-0.101795, name: {
51.517806 default: 'name 2',
] },
}, bounding_box: {
'properties': { min_lon: -3,
'id': 'id2', min_lat: -3,
'gid': 'source2:layer2:id2', max_lon: -1,
'layer': 'layer2', max_lat: -1
'source': 'source2', },
'source_id': 'source_id_2', center_point: {
'name': 'Blues Cafe', lat: 13.131313,
'country_a': 'GBR', lon: 31.313131
'country': 'United Kingdom', }
'dependency': 'dependency name', }
'macroregion': 'England', ];
'region': 'City And County Of The City Of London',
'region_a': 'COL', const geojsonify = proxyquire('../../../helper/geojsonify', {
'county': 'Smithfield', './geojsonify_place_details': (params, source, dst) => {
'localadmin': 'test1', if (source._id === 'id 1') {
'locality': 'test2', dst.property1 = 'property 1';
'neighbourhood': 'test3', dst.property2 = 'property 2';
'label': 'label for id id2' } else if (source._id === 'id 2') {
dst.property3 = 'property 3';
dst.property4 = 'property 4';
}
}
});
const actual = geojsonify({}, input);
const expected = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ 21.212121, 12.121212 ]
},
properties: {
id: 'id 1',
gid: 'source 1:layer 1:id 1',
layer: 'layer 1',
source: 'source 1',
source_id: 'source_id 1',
name: 'name 1',
property1: 'property 1',
property2: 'property 2'
} }
}, },
{ {
'type': 'Feature', type: 'Feature',
'geometry': { geometry: {
'type': 'Point', type: 'Point',
'coordinates': [ coordinates: [ 31.313131, 13.131313 ]
-73.985656, },
40.748432 properties: {
] id: 'id 2',
}, gid: 'source 2:layer 2:id 2',
'properties': { layer: 'layer 2',
'id': 'node:34633854', source: 'source 2',
'gid': 'openstreetmap:venue:node:34633854', source_id: 'source_id 2',
'layer': 'venue', name: 'name 2',
'source': 'openstreetmap', property3: 'property 3',
'source_id': 'source_id_3', property4: 'property 4'
'name': 'Empire State Building', },
'country_a': 'USA', bbox: [ -3, -3, -1, -1 ]
'country': 'United States', }
'dependency': 'dependency name',
'region': 'New York',
'region_a': 'NY',
'county': 'New York',
'borough': 'Manhattan',
'locality': 'New York',
'neighbourhood': 'Koreatown',
'category': [
'tourism',
'transport'
], ],
'label': 'label for id node:34633854' bbox: [ -3, -3, 21.212121, 12.121212 ]
};
t.deepEquals(actual, expected);
t.end();
});
};
module.exports.tests.non_optimal_conditions = (test, common) => {
test('null/undefined places should log warnings and be ignored', t => {
const logger = require('pelias-mock-logger')();
const input = [
null,
undefined,
{
_id: 'id 1',
source: 'source 1',
source_id: 'source_id 1',
layer: 'layer 1',
name: {
default: 'name 1',
},
center_point: {
lat: 12.121212,
lon: 21.212121
} }
} }
] ];
};
const geojsonify = proxyquire('../../../helper/geojsonify', {
'./geojsonify_place_details': (params, source, dst) => {
if (source._id === 'id 1') {
dst.property1 = 'property 1';
dst.property2 = 'property 2';
}
},
'pelias-logger': logger
});
const actual = geojsonify({}, input);
var json = geojsonify( {categories: 'foo'}, input ); const expected = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ 21.212121, 12.121212 ]
},
properties: {
id: 'id 1',
gid: 'source 1:layer 1:id 1',
layer: 'layer 1',
source: 'source 1',
source_id: 'source_id 1',
name: 'name 1',
property1: 'property 1',
property2: 'property 2'
}
}
],
bbox: [21.212121, 12.121212, 21.212121, 12.121212]
};
t.deepEqual(json, expected, 'all docs mapped'); t.deepEquals(actual, expected);
t.ok(logger.isWarnMessage('No doc or center_point property'));
t.end(); t.end();
}); });
test('filtering out empty items', function (t) { test('places w/o center_point should log warnings and be ignored', t => {
var input = [ const logger = require('pelias-mock-logger')();
const input = [
{ {
'bounding_box': { _id: 'id 1',
'min_lat': 40.6514712164, source: 'source 1',
'max_lat': 40.6737320588, source_id: 'source_id 1',
'min_lon': -73.8967895508, layer: 'layer 1',
'max_lon': -73.8665771484 name: {
}, default: 'name 1',
'locality': [ }
'New York'
],
'source': 'whosonfirst',
'layer': 'neighbourhood',
'population': 173198,
'popularity': 495,
'center_point': {
'lon': -73.881319,
'lat': 40.663303
}, },
'name': { {
'default': 'East New York' _id: 'id 2',
}, source: 'source 2',
'source_id': '85816607', source_id: 'source_id 2',
'category': ['government'], layer: 'layer 2',
'_id': '85816607', name: {
'_type': 'neighbourhood', default: 'name 2',
'_score': 21.434, },
'confidence': 0.888, center_point: {
'country': [ lat: 13.131313,
'United States' lon: 31.313131
], }
'country_gid': [
'85633793'
],
'country_a': [
'USA'
],
'dependency': [
'dependency name'
],
'dependency_gid': [
'dependency id'
],
'dependency_a': [
'dependency abbrevation'
],
'macroregion': [
'MacroRegion Name'
],
'macroregion_gid': [
'MacroRegion Id'
],
'macroregion_a': [
'MacroRegion Abbreviation'
],
'region': [
'New York'
],
'region_gid': [
'85688543'
],
'region_a': [
'NY'
],
'macrocounty': [
'MacroCounty Name'
],
'macrocounty_gid': [
'MacroCounty Id'
],
'macrocounty_a': [
'MacroCounty Abbreviation'
],
'county': [
'Kings County'
],
'county_gid': [
'102082361'
],
'county_a': [
null
],
'borough': [
'Brooklyn'
],
'localadmin_gid': [
'404521211'
],
'borough_a': [
null
],
'locality_gid': [
'85977539'
],
'locality_a': [
null
],
'neighbourhood': [],
'neighbourhood_gid': [],
'label': 'label for id 85816607'
} }
]; ];
var expected = { const geojsonify = proxyquire('../../../helper/geojsonify', {
'type': 'FeatureCollection', './geojsonify_place_details': (params, source, dst) => {
'bbox': [-73.8967895508, 40.6514712164, -73.8665771484, 40.6737320588], if (source._id === 'id 2') {
'features': [ dst.property3 = 'property 3';
dst.property4 = 'property 4';
}
},
'pelias-logger': logger
});
const actual = geojsonify({}, input);
const expected = {
type: 'FeatureCollection',
features: [
{ {
'type': 'Feature', type: 'Feature',
'properties': { geometry: {
'id': '85816607', type: 'Point',
'gid': 'whosonfirst:neighbourhood:85816607', coordinates: [ 31.313131, 13.131313 ]
'layer': 'neighbourhood', },
'source': 'whosonfirst', properties: {
'source_id': '85816607', id: 'id 2',
'name': 'East New York', gid: 'source 2:layer 2:id 2',
'category': ['government'], layer: 'layer 2',
'confidence': 0.888, source: 'source 2',
'country': 'United States', source_id: 'source_id 2',
'country_gid': '85633793', name: 'name 2',
'country_a': 'USA', property3: 'property 3',
'dependency': 'dependency name', property4: 'property 4'
'dependency_gid': 'dependency id', }
'dependency_a': 'dependency abbrevation', }
'macroregion': 'MacroRegion Name', ],
'macroregion_gid': 'MacroRegion Id', bbox: [31.313131, 13.131313, 31.313131, 13.131313]
'macroregion_a': 'MacroRegion Abbreviation',
'region': 'New York',
'region_gid': '85688543',
'region_a': 'NY',
'macrocounty': 'MacroCounty Name',
'macrocounty_gid': 'MacroCounty Id',
'macrocounty_a': 'MacroCounty Abbreviation',
'county': 'Kings County',
'borough': 'Brooklyn',
'county_gid': '102082361',
'localadmin_gid': '404521211',
'locality': 'New York',
'locality_gid': '85977539',
'label': 'label for id 85816607'
},
'bbox': [-73.8967895508,40.6514712164,-73.8665771484,40.6737320588],
'geometry': {
'type': 'Point',
'coordinates': [
-73.881319,
40.663303
]
}
}
]
}; };
var json = geojsonify( {categories: 'foo'}, input ); t.deepEquals(actual, expected);
t.ok(logger.isWarnMessage('No doc or center_point property'));
t.deepEqual(json, expected, 'all wanted properties exposed');
t.end(); t.end();
}); });
};
module.exports.tests.categories = function (test, common) { test('places w/o names should log warnings and be ignored', t => {
test('only set category if categories filter was used', function (t) { const logger = require('pelias-mock-logger')();
var input = [
const input = [
{ {
'_id': '85816607', _id: 'id 1',
'bounding_box': { source: 'source 1',
'min_lat': 40.6514712164, source_id: 'source_id 1',
'max_lat': 40.6737320588, layer: 'layer 1',
'min_lon': -73.8967895508, center_point: {
'max_lon': -73.8665771484 lat: 12.121212,
lon: 21.212121
}
}, },
'source': 'whosonfirst', {
'layer': 'neighbourhood', _id: 'id 2',
'center_point': { source: 'source 2',
'lon': -73.881319, source_id: 'source_id 2',
'lat': 40.663303 layer: 'layer 2',
name: {},
center_point: {
lat: 13.131313,
lon: 31.313131
}
}, },
'name': { {
'default': 'East New York' _id: 'id 3',
source: 'source 3',
source_id: 'source_id 3',
layer: 'layer 3',
name: {
default: 'name 3',
}, },
'source_id': '85816607', center_point: {
'category': ['government'], lat: 14.141414,
'label': 'label for id 85816607' lon: 41.414141
}
} }
]; ];
var expected = { const geojsonify = proxyquire('../../../helper/geojsonify', {
'type': 'FeatureCollection', './geojsonify_place_details': (params, source, dst) => {
'bbox': [-73.8967895508, 40.6514712164, -73.8665771484, 40.6737320588], if (source._id === 'id 1') {
'features': [ dst.property1 = 'property 1';
dst.property2 = 'property 2';
}
else if (source._id === 'id 2') {
dst.property3 = 'property 3';
dst.property4 = 'property 4';
}
else if (source._id === 'id 3') {
dst.property5 = 'property 5';
dst.property6 = 'property 6';
}
},
'pelias-logger': logger
});
const actual = geojsonify({}, input);
const expected = {
type: 'FeatureCollection',
features: [
{ {
'type': 'Feature', type: 'Feature',
'properties': { geometry: {
'id': '85816607', type: 'Point',
'gid': 'whosonfirst:neighbourhood:85816607', coordinates: [ 21.212121, 12.121212 ]
'layer': 'neighbourhood', },
'source': 'whosonfirst', properties: {
'source_id': '85816607', id: 'id 1',
'name': 'East New York', gid: 'source 1:layer 1:id 1',
'category': ['government'], layer: 'layer 1',
'label': 'label for id 85816607' source: 'source 1',
source_id: 'source_id 1',
property1: 'property 1',
property2: 'property 2'
}
}, },
'bbox': [-73.8967895508,40.6514712164,-73.8665771484,40.6737320588], {
'geometry': { type: 'Feature',
'type': 'Point', geometry: {
'coordinates': [ type: 'Point',
-73.881319, coordinates: [ 31.313131, 13.131313 ]
40.663303 },
] properties: {
id: 'id 2',
gid: 'source 2:layer 2:id 2',
layer: 'layer 2',
source: 'source 2',
source_id: 'source_id 2',
property3: 'property 3',
property4: 'property 4'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [ 41.414141, 14.141414 ]
},
properties: {
id: 'id 3',
gid: 'source 3:layer 3:id 3',
layer: 'layer 3',
source: 'source 3',
source_id: 'source_id 3',
name: 'name 3',
property5: 'property 5',
property6: 'property 6'
} }
} }
] ],
bbox: [21.212121, 12.121212, 41.414141, 14.141414]
}; };
var json = geojsonify( {categories: 'foo'}, input ); t.deepEquals(actual, expected);
t.ok(logger.isWarnMessage('doc source 1:layer 1:id 1 does not contain name.default'));
t.deepEqual(json, expected, 'all wanted properties exposed'); t.ok(logger.isWarnMessage('doc source 2:layer 2:id 2 does not contain name.default'));
t.end(); t.end();
}); });
};
module.exports.all = function (tape, common) { };
module.exports.all = (tape, common) => {
function test(name, testFunction) { function test(name, testFunction) {
return tape('geojsonify: ' + name, testFunction); return tape(`geojsonify: ${name}`, testFunction);
} }
for( var testCase in module.exports.tests ){ for( var testCase in module.exports.tests ){

Loading…
Cancel
Save