mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-14 21:28:11 +02:00
coreLocation tests, documentation
This commit is contained in:
@@ -4,7 +4,7 @@ export { coreDifference } from './difference';
|
||||
export { coreGraph } from './graph';
|
||||
export { coreHistory } from './history';
|
||||
export { coreLocalizer, t, localizer } from './localizer';
|
||||
export { coreLocations } from './locations';
|
||||
export { coreLocations, locationManager } from './locations';
|
||||
export { prefs } from './preferences';
|
||||
export { coreTree } from './tree';
|
||||
export { coreUploader } from './uploader';
|
||||
|
||||
+51
-28
@@ -22,9 +22,9 @@ export { _mainLocations as locationManager };
|
||||
//
|
||||
export function coreLocations() {
|
||||
let _this = {};
|
||||
let _resolvedFeatures = {}; // cache of *resolved* locationSet features
|
||||
let _loco = new LocationConflation(); // instance of a location-conflation resolver
|
||||
let _wp; // instance of a which-polygon index
|
||||
let _resolvedFeatures = {}; // cache of *resolved* locationSet features
|
||||
let _loco = new LocationConflation(); // instance of a location-conflation resolver
|
||||
let _wp; // instance of a which-polygon index
|
||||
|
||||
// pre-resolve the worldwide locationSet
|
||||
const world = { locationSet: { include: ['Q2'] } };
|
||||
@@ -36,6 +36,7 @@ export function coreLocations() {
|
||||
let _inProcess;
|
||||
|
||||
|
||||
// Returns a Promise to process the queue
|
||||
function processQueue() {
|
||||
if (!_queue.length) return Promise.resolve();
|
||||
|
||||
@@ -55,6 +56,8 @@ export function coreLocations() {
|
||||
.then(() => processQueue());
|
||||
}
|
||||
|
||||
// Pass an Object with a `locationSet` property,
|
||||
// Performs the locationSet resolution, caches the result, and sets a `locationSetID` property on the object.
|
||||
function resolveLocationSet(obj) {
|
||||
if (obj.locationSetID) return; // work was done already
|
||||
|
||||
@@ -80,6 +83,7 @@ export function coreLocations() {
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuilds the whichPolygon index with whatever features have been resolved.
|
||||
function rebuildIndex() {
|
||||
_wp = whichPolygon({ features: Object.values(_resolvedFeatures) });
|
||||
}
|
||||
@@ -148,7 +152,7 @@ export function coreLocations() {
|
||||
// ]
|
||||
//
|
||||
// Returns a Promise fullfilled when the resolving/indexing has been completed
|
||||
// This will take some seconds but happen in the background during browser idle time
|
||||
// This will take some seconds but happen in the background during browser idle time.
|
||||
//
|
||||
_this.mergeLocationSets = (objects) => {
|
||||
if (!Array.isArray(objects)) return Promise.reject('nothing to do');
|
||||
@@ -165,12 +169,12 @@ export function coreLocations() {
|
||||
// https://github.com/osmlab/name-suggestion-index/issues/4784#issuecomment-742003434
|
||||
_queue = _queue.concat(utilArrayChunk(objects, 200));
|
||||
|
||||
// Everything after here will be deferred.
|
||||
if (!_inProcess) {
|
||||
_inProcess = processQueue()
|
||||
.then(() => {
|
||||
rebuildIndex();
|
||||
_inProcess = null;
|
||||
return objects;
|
||||
});
|
||||
}
|
||||
return _inProcess;
|
||||
@@ -179,7 +183,13 @@ export function coreLocations() {
|
||||
|
||||
//
|
||||
// `locationSetID`
|
||||
// Return a locationSetID for a given locationSet (fallback to the 'world')
|
||||
// Returns a locationSetID for a given locationSet (fallback to `+[Q2]`, world)
|
||||
// (The locationset doesn't necessarily need to be resolved to compute its `id`)
|
||||
//
|
||||
// Arguments
|
||||
// `locationSet`: A locationSet, e.g. `{ include: ['us'] }`
|
||||
// Returns
|
||||
// The locationSetID, e.g. `+[Q30]`
|
||||
//
|
||||
_this.locationSetID = (locationSet) => {
|
||||
let locationSetID;
|
||||
@@ -194,36 +204,36 @@ export function coreLocations() {
|
||||
|
||||
//
|
||||
// `feature`
|
||||
// Return the GeoJSON feature for a given locationSetID (fallback to 'world')
|
||||
// Returns the resolved GeoJSON feature for a given locationSetID (fallback to 'world')
|
||||
//
|
||||
// Arguments
|
||||
// `locationSetID`: id of the form like `+[Q30]` (United States)
|
||||
// Returns
|
||||
// A GeoJSON feature:
|
||||
// {
|
||||
// type: 'Feature',
|
||||
// id: '+[Q30]',
|
||||
// properties: { id: '+[Q30]', area: 21817019.17, … },
|
||||
// geometry: { … }
|
||||
// }
|
||||
_this.feature = (locationSetID) => _resolvedFeatures[locationSetID] || _resolvedFeatures['+[Q2]'];
|
||||
|
||||
|
||||
//
|
||||
// `query`
|
||||
// Execute a query directly against which-polygon
|
||||
// https://github.com/mapbox/which-polygon
|
||||
// Arguments
|
||||
// `loc`: the [lon,lat] location to query,
|
||||
// `multi`= true to return all results, `false` to return first result
|
||||
// Returns
|
||||
// Array of GeoJSON *properties* for the locationSet features that exist at `loc`
|
||||
//
|
||||
_this.query = (loc, multi) => _wp(loc, multi);
|
||||
|
||||
//
|
||||
// `locationsAt`
|
||||
// Convenience method to find all the locationSets valid at the given location.
|
||||
// Find all the resolved locationSets valid at the given location.
|
||||
// Results include the area (in km²) to facilitate sorting.
|
||||
//
|
||||
// Arguments
|
||||
// `loc`: the [lon,lat] location to query
|
||||
// `loc`: the [lon,lat] location to query, e.g. `[-74.4813, 40.7967]`
|
||||
// Returns
|
||||
// A result Object of ids to areas
|
||||
// {
|
||||
// "+[Q2]": 511207893.3958111,
|
||||
// "+[Q30]": 21817019.17,
|
||||
// "+[new_jersey.geojson]": 22390.77,
|
||||
// …
|
||||
// }
|
||||
// Object of locationSetIDs to areas (in km²)
|
||||
// {
|
||||
// "+[Q2]": 511207893.3958111,
|
||||
// "+[Q30]": 21817019.17,
|
||||
// "+[new_jersey.geojson]": 22390.77,
|
||||
// …
|
||||
// }
|
||||
//
|
||||
_this.locationsAt = (loc) => {
|
||||
let result = {};
|
||||
@@ -231,6 +241,19 @@ export function coreLocations() {
|
||||
return result;
|
||||
};
|
||||
|
||||
//
|
||||
// `query`
|
||||
// Execute a query directly against which-polygon
|
||||
// https://github.com/mapbox/which-polygon
|
||||
//
|
||||
// Arguments
|
||||
// `loc`: the [lon,lat] location to query,
|
||||
// `multi`: `true` to return all results, `false` to return first result
|
||||
// Returns
|
||||
// Array of GeoJSON *properties* for the locationSet features that exist at `loc`
|
||||
//
|
||||
_this.query = (loc, multi) => _wp(loc, multi);
|
||||
|
||||
// Direct access to the location-conflation resolver
|
||||
_this.loco = () => _loco;
|
||||
|
||||
|
||||
+2
-1
@@ -81,6 +81,7 @@
|
||||
'spec/core/file_fetcher.js',
|
||||
'spec/core/graph.js',
|
||||
'spec/core/history.js',
|
||||
'spec/core/locations.js',
|
||||
'spec/core/tree.js',
|
||||
'spec/core/validator.js',
|
||||
|
||||
@@ -203,4 +204,4 @@
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -0,0 +1,150 @@
|
||||
describe('iD.coreLocations', function() {
|
||||
var locationManager, loco, wp;
|
||||
|
||||
var colorado = {
|
||||
type: 'Feature',
|
||||
id: 'colorado.geojson',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'Polygon',
|
||||
coordinates: [
|
||||
[
|
||||
[-107.9197, 41.0039],
|
||||
[-102.0539, 41.0039],
|
||||
[-102.043, 36.9948],
|
||||
[-109.0425, 37.0003],
|
||||
[-109.048, 40.9984],
|
||||
[-107.9197, 41.0039]
|
||||
]
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
var fc = { type: 'FeatureCollection', features: [colorado] };
|
||||
|
||||
|
||||
beforeEach(function() {
|
||||
// make a new one each time, so we aren't accidently testing the "global" locationManager
|
||||
locationManager = iD.coreLocations();
|
||||
loco = locationManager.loco();
|
||||
wp = locationManager.wp();
|
||||
});
|
||||
|
||||
|
||||
describe('#mergeCustomGeoJSON', function() {
|
||||
it('merges geojson into lococation-conflation cache', function() {
|
||||
locationManager.mergeCustomGeoJSON(fc);
|
||||
expect(loco._cache['colorado.geojson']).to.be.eql(colorado);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#mergeLocationSets', function() {
|
||||
it('returns a promise rejected if not passed an array', function(done) {
|
||||
var prom = locationManager.mergeLocationSets({});
|
||||
prom
|
||||
.then(function() {
|
||||
throw new Error('This was supposed to fail, but somehow succeeded.');
|
||||
})
|
||||
.catch(function(err) {
|
||||
expect(/^nothing to do/.test(err)).to.be.true;
|
||||
})
|
||||
.finally(done);
|
||||
|
||||
window.setTimeout(function() {}, 20); // async - to let the promise settle in phantomjs
|
||||
});
|
||||
|
||||
it('resolves locationSets, assigning locationSetID', function(done) {
|
||||
var data = [
|
||||
{ id: 'world', locationSet: { include: ['001'] } },
|
||||
{ id: 'usa', locationSet: { include: ['usa'] } }
|
||||
];
|
||||
var prom = locationManager.mergeLocationSets(data);
|
||||
prom
|
||||
.then(function(data) {
|
||||
expect(data).to.be.a('array');
|
||||
expect(data[0]).locationSetID.to.eql('+[Q2]');
|
||||
expect(data[1]).locationSetID.to.eql('+[Q30]');
|
||||
})
|
||||
.finally(done);
|
||||
|
||||
window.setTimeout(function() {}, 20); // async - to let the promise settle in phantomjs
|
||||
});
|
||||
|
||||
it('resolves locationSets, falls back to world locationSetID on errror', function(done) {
|
||||
var data = [
|
||||
{ id: 'bogus1', locationSet: { foo: 'bar' } },
|
||||
{ id: 'bogus2', locationSet: { include: ['fake.geojson'] } }
|
||||
];
|
||||
var prom = locationManager.mergeLocationSets(data);
|
||||
prom
|
||||
.then(function(data) {
|
||||
expect(data).to.be.a('array');
|
||||
expect(data[0]).locationSetID.to.eql('+[Q2]');
|
||||
expect(data[1]).locationSetID.to.eql('+[Q2]');
|
||||
})
|
||||
.finally(done);
|
||||
|
||||
window.setTimeout(function() {}, 20); // async - to let the promise settle in phantomjs
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#locationSetID', function() {
|
||||
it('calculates a locationSetID for a locationSet', function() {
|
||||
expect(locationManager.locationSetID({ include: ['usa'] })).to.be.eql('+[Q30]');
|
||||
});
|
||||
|
||||
it('falls back to the world locationSetID in case of errors', function() {
|
||||
expect(locationManager.locationSetID({ foo: 'bar' })).to.be.eql('+[Q2]');
|
||||
expect(locationManager.locationSetID({ include: ['fake.geojson'] })).to.be.eql('+[Q2]');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#feature', function() {
|
||||
it('has the world locationSet pre-resolved', function() {
|
||||
var result = locationManager.feature('+[Q2]');
|
||||
expect(result).to.include({ type: 'Feature', id: '+[Q2]' });
|
||||
});
|
||||
|
||||
it('falls back to the world locationSetID in case of errors', function() {
|
||||
var result = locationManager.feature('fake');
|
||||
expect(result).to.include({ type: 'Feature', id: '+[Q2]' });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#locationsAt', function() {
|
||||
it('has the world locationSet pre-resolved', function() {
|
||||
var result1 = locationManager.locationsAt([-108.557, 39.065]); // Grand Junction
|
||||
expect(result1).to.be.an('object').that.has.all.keys('+[Q2]');
|
||||
var result2 = locationManager.locationsAt([-74.481, 40.797]); // Morristown
|
||||
expect(result2).to.be.an('object').that.has.all.keys('+[Q2]');
|
||||
var result3 = locationManager.locationsAt([13.575, 41.207,]); // Gaeta
|
||||
expect(result3).to.be.an('object').that.has.all.keys('+[Q2]');
|
||||
});
|
||||
|
||||
it('returns valid locations at a given lon,lat', function(done) {
|
||||
// setup, load colorado.geojson and resolve some locationSets
|
||||
locationManager.mergeCustomGeoJSON(fc);
|
||||
locationManager.mergeLocationSets([
|
||||
{ id: 'OSM-World', locationSet: { include: ['001'] } },
|
||||
{ id: 'OSM-USA', locationSet: { include: ['us'] } },
|
||||
{ id: 'OSM-Colorado', locationSet: { include: ['colorado.geojson'] } }
|
||||
])
|
||||
.then(function() {
|
||||
var result1 = locationManager.locationsAt([-108.557, 39.065]); // Grand Junction
|
||||
expect(result1).to.be.an('object').that.has.all.keys('+[Q2]', '+[Q30]', '+[colorado.geojson]');
|
||||
var result2 = locationManager.locationsAt([-74.481, 40.797]); // Morristown
|
||||
expect(result2).to.be.an('object').that.has.all.keys('+[Q2]', '+[Q30]');
|
||||
var result3 = locationManager.locationsAt([13.575, 41.207,]); // Gaeta
|
||||
expect(result3).to.be.an('object').that.has.all.keys('+[Q2]');
|
||||
})
|
||||
.finally(done);
|
||||
|
||||
window.setTimeout(function() {}, 20); // async - to let the promise settle in phantomjs
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user