Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ideditor/location-conflation

Package Overview
Dependencies
Maintainers
2
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ideditor/location-conflation - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

test/validateLocationSet.test.js

20

CHANGELOG.md

@@ -19,2 +19,16 @@ # What's New

# 0.5.0
##### 2020-Aug-25
* :warning: Refactor - API now has:
* `validateLocation` / `validateLocationSet` - fast, return stable ids
* `resolveLocation` / `resolveLocationSet` - slower, resolve GeoJSON features
* All functions now return similar result objects
* :warning: Introduce strict / non-strict modes. Location-conflation defaults to "strict" mode now.
* In strict mode, any invalid location or locationSet throws an error.
* In non strict mode, invalid locations are ignored, and locationSets that include nothing are assumed to include the entire world.
* Can change modes by calling `.strict(val)`, for example:<br/>
`const loco = new LocationConflation(features).strict(false); // not strict`
* Add tests and document everything
# 0.4.0

@@ -31,3 +45,3 @@ ##### 2020-Aug-20

## 0.3.0
# 0.3.0
##### 2020-Feb-13

@@ -46,3 +60,3 @@ * Use uppercase Wikidata identifiers, lowercase geojson filenames

## 0.2.0
# 0.2.0
##### 2020-Jan-15

@@ -52,4 +66,4 @@ * Ensure that feature results always have both `id` and `properties.id`

## 0.1.0
# 0.1.0
##### 2020-Jan-13
* Initial release

2

package.json
{
"name": "@ideditor/location-conflation",
"version": "0.4.0",
"version": "0.5.0",
"license": "ISC",

@@ -5,0 +5,0 @@ "repository": "github:ideditor/location-conflation",

@@ -18,3 +18,3 @@ [![npm version](https://badge.fury.io/js/%40ideditor%2Flocation-conflation.svg)](https://badge.fury.io/js/%40ideditor%2Flocation-conflation)

You can define a *location set* as an Object with `include` and `exclude` properties:
You can define a *locationSet* as an Object with `include` and `exclude` properties:
```js

@@ -57,3 +57,3 @@ let locationSet = {

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/@ideditor/location-conflation@0/index.min.mjs"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@ideditor/location-conflation@0.5/index.min.mjs"></script>
```

@@ -63,3 +63,3 @@

```html
<script src="https://cdn.jsdelivr.net/npm/@ideditor/location-conflation@0/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@ideditor/location-conflation@0.5/dist/index.min.js"></script>
```

@@ -69,3 +69,3 @@

```html
<script src="https://cdn.jsdelivr.net/npm/@ideditor/location-conflation@0/dist/index.es5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@ideditor/location-conflation@0.5/dist/index.es5.min.js"></script>
```

@@ -75,3 +75,3 @@

### Examples
## Examples
```js

@@ -85,3 +85,4 @@ const LocationConflation = require('@ideditor/location-conflation');

```js
let result = loco.resolveLocationSet({ include: ['039'] }); // 039 = Southern Europe
let locationSet = { include: ['039'] }; // 039 = Southern Europe
let result = loco.resolveLocationSet(locationSet);
```

@@ -93,3 +94,4 @@ <img width="800px" alt="Southern Europe" src="https://raw.githubusercontent.com/ideditor/location-conflation/master/docs/images/example1.png"/>

```js
let result = loco.resolveLocationSet({ include: ['039','015'] }); // 015 = Northern Africa
let locationSet = { include: ['039','015'] }; // 015 = Northern Africa
let result = loco.resolveLocationSet(locationSet);
```

@@ -101,3 +103,4 @@ <img width="800px" alt="Southern Europe and Northern Africa" src="https://raw.githubusercontent.com/ideditor/location-conflation/master/docs/images/example2.png"/>

```js
let result = loco.resolveLocationSet({ include: ['039','015'], exclude: ['eg','sd'] });
let locationSet = { include: ['039','015'], exclude: ['eg','sd'] };
let result = loco.resolveLocationSet(locationSet);
```

@@ -114,15 +117,166 @@ <img width="800px" alt="Southern Europe and Northern Africa, excluding Egypt and Sudan" src="https://raw.githubusercontent.com/ideditor/location-conflation/master/docs/images/example3.png"/>

&nbsp;
### Other Fun facts
* This library is a wrapper around
* [country-coder](https://github.com/ideditor/country-coder) for world boundaries, and
* [polygon-clipping](https://github.com/mfogel/polygon-clipping) for union/difference functions
* Results contain an `area` property containing the approximate size of the feature in km²<br/>(This is helpful for sorting features)
* Results contain a stable `id` in the form `+[included]-[excluded]`<br/>(e.g. "+[015,039]-[eg,sd]")
* Results are cached, so if you ask for the same thing multiple times we don't repeat the expensive clipping operations.
## API Reference
* [constructor](#constructor)
* [validateLocation](#validateLocation)
* [validateLocationSet](#validateLocationSet)
* [resolveLocation](#resolveLocation)
* [resolveLocationSet](#resolveLocationSet)
* [strict](#strict)
* [stringify](#stringify)
* [cache](#cache)
&nbsp;
#### Prerequisites
<a name="constructor" href="#constructor">#</a> const <i>loco</i> = new <b>LocationConflation</b>(<i>featureCollection</i>)
Constructs a new LocationConflation instance.
Optionally pass a GeoJSON FeatureCollection of known features which can be used later as locations.
Each feature *must* have a filename-like `id`, for example: `example.geojson`
```js
{
"type": "FeatureCollection"
"features": [
{
"type": "Feature",
"id": "example.geojson",
"properties": { … },
"geometry": { … }
}
]
}
```
&nbsp;
<a name="validateLocation" href="#validateLocation">#</a> <i>loco</i>.<b>validateLocation</b>(<i>location</i>)
Validates a given location. The "locations" can be:
* Points as `[longitude, latitude]` coordinate pairs. _Example: `[8.67039, 49.41882]`_
* Filenames for known `.geojson` features. _Example: `"de-hamburg.geojson"`_
* Strings recognized by the [country-coder library](https://github.com/ideditor/country-coder#readme). _Example: `"de"`_
If the location is valid, returns a result `Object` like:
```js
{
type: 'point', 'geojson', or 'countrycoder'
location: the queried location
id: the stable identifier for the feature
}
```
If the location is invalid,
* _in strict mode_, throws an error
* _in non-strict mode_, returns `null`
&nbsp;
<a name="validateLocationSet" href="#validateLocationSet">#</a> <i>loco</i>.<b>validateLocationSet</b>(<i>locationSet</i>)
Validates a given locationSet. Pass a locationSet `Object` like:
```js
{
include: [ Array of locations ],
exclude: [ Array of locations ]
}
```
If the locationSet is valid, returns a result `Object` like:
```js
{
type: 'locationset'
locationSet: the queried locationSet
id: the stable identifier for the feature
}
```
If the locationSet is invalid or contains any invalid locations,
* _in strict mode_, throws an error
* _in non-strict mode_, invalid locations are quietly ignored. A locationSet with nothing included will be considered valid, and will validate as if it were a locationSet covering the entire world. `{ type: 'locationset', locationSet: ['Q2'], id: +[Q2] }`
&nbsp;
<a name="resolveLocation" href="#resolveLocation">#</a> <i>loco</i>.<b>resolveLocation</b>(<i>location</i>)
Resolves a given location into a GeoJSON feature. This is similar to [validateLocation](#validateLocation), but runs slower and includes the actual GeoJSON in the result. Results are cached, so if you ask for the same thing multiple times we don't repeat the expensive clipping operations.
The returned GeoJSON feature will also have an `area` property containing the approximate size of the feature in km². (This is helpful for sorting features)
If the location is valid, returns a result `Object` like:
```js
{
type: 'point', 'geojson', or 'countrycoder'
location: the queried location
id: the stable identifier for the feature
feature: the resolved GeoJSON feature
}
```
If the location is invalid,
* _in strict mode_, throws an error
* _in non-strict mode_, returns `null`
&nbsp;
<a name="resolveLocationSet" href="#resolveLocationSet">#</a> <i>loco</i>.<b>resolveLocationSet</b>(<i>locationSet</i>)
Resolves a given locationSet into a GeoJSON feature. This is similar to [validateLocationSet](#validateLocationSet), but runs slower and includes the actual GeoJSON in the result. Results are cached, so if you ask for the same thing multiple times we don't repeat the expensive clipping operations.
The returned GeoJSON feature will also have an `area` property containing the approximate size of the feature in km². (This is helpful for sorting features)
If the locationSet is valid, returns a result `Object` like:
```js
{
type: 'locationset'
locationSet: the queried locationSet
id: the stable identifier for the feature
feature: the resolved GeoJSON feature
}
```
If the locationSet is invalid or contains any invalid locations,
* _in strict mode_, throws an error
* _in non-strict mode_, invalid locations are quietly ignored. A locationSet with nothing included will be considered valid, and will validate as if it were a locationSet covering the entire world. `{ type: 'locationset', locationSet: ['Q2'], id: +[Q2] }`
&nbsp;
<a name="strict" href="#strict">#</a> <i>loco</i>.<b>strict</b>(<i>val</i>)
Get/set "strict mode". New instances of LocationConflation start out in strict mode by default.
* In strict mode, any invalid location or locationSet throws an error.
* In non strict mode, invalid locations are ignored, and locationSets that include nothing are assumed to include the entire world.
```js
loco.strict(false); // pass a true/false value to set the strict mode
const isStrict = loco.strict(); // pass no value to return the current value
```
&nbsp;
<a name="stringify" href="#stringify">#</a> <i>loco</i>.<b>stringify</b>(<i>object</i>, <i>options</i>)
Convenience method that wraps [json-stringify-pretty-compact](https://www.npmjs.com/package/@aitodotai/json-stringify-pretty-compact) to stringify the given object. Optional `options` parameter gets passed through to json-stringify-pretty-compact.
```js
loco.stringify(someGeoJson, { maxLength: 100 }); // Make it pretty!
```
<a name="cache" href="#cache">#</a> <i>loco</i>.<b>cache</b>()
Convenience method to access the internal feature `_cache`. You probably shouldn't use it except for debugging.
&nbsp;
## Contributing
### Prerequisites
* [Node.js](https://nodejs.org/) version 10 or newer

@@ -132,3 +286,3 @@ * [`git`](https://www.atlassian.com/git/tutorials/install-git/) for your platform

#### Installing
### Installing

@@ -141,3 +295,3 @@ * Clone this project, for example:

#### Building
### Building

@@ -147,2 +301,9 @@ * `npm run build`

### Thanks!
**location-conflation** is really just a wrapper around these other great projects:
* [country-coder](https://github.com/ideditor/country-coder) for world boundaries, and
* [polygon-clipping](https://github.com/mfogel/polygon-clipping) for union/difference functions
### License

@@ -149,0 +310,0 @@

@@ -6,2 +6,3 @@ const test = require('tap').test;

const loco = new LocationConflation(features);
const locoNS = new LocationConflation(features).strict(false);

@@ -13,17 +14,24 @@

t.test('a valid [lon,lat] coordinate pair returns a feature match', t => {
const result = loco.resolveLocation([0, 0]);
const location = [0, 0];
const result = loco.resolveLocation(location);
t.notEqual(result, null);
t.equal(result.type, 'point');
t.type(result.feature, 'object');
t.type(result.feature.properties, 'object');
t.equal(result.feature.id, '[0,0]'); // has an id
t.equal(result.feature.properties.id, '[0,0]'); // has an id property
t.match(result.feature.properties, { area: /\d+/ }); // has a numeric area property
t.equal(result.location, location);
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, '[0,0]'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, '[0,0]'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.test('an invalid [lon,lat] coordinate pair returns a null match', t => {
const result = loco.resolveLocation([]);
t.equal(result, null);
t.test('(strict mode) an invalid [lon,lat] coordinate pair throws an error', t => {
const location = [];
t.throws(() => loco.resolveLocation(location));
t.end();
});
t.test('(non strict mode) an invalid [lon,lat] coordinate pair returns falsy', t => {
const location = [];
t.notOk(locoNS.resolveLocation(location));
t.end();
});
t.end();

@@ -35,39 +43,50 @@ });

t.test('a known `.geojson` filename with id returns a feature match', t => {
const result = loco.resolveLocation('dc_metro.geojson');
const location = 'dc_metro.geojson';
const result = loco.resolveLocation(location);
t.notEqual(result, null);
t.equal(result.type, 'geojson');
t.type(result.feature, 'object');
t.type(result.feature.properties, 'object');
t.equal(result.feature.id, 'dc_metro.geojson'); // has an id
t.equal(result.feature.properties.id, 'dc_metro.geojson'); // has an id property
t.match(result.feature.properties, { area: /\d+/ }); // has a numeric area property
t.equal(result.location, location);
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, 'dc_metro.geojson'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, 'dc_metro.geojson'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.test('a known `.geojson` filename with id property returns a feature match', t => {
const result = loco.resolveLocation('philly_metro.geojson');
const location = 'philly_metro.geojson';
const result = loco.resolveLocation(location);
t.notEqual(result, null);
t.equal(result.type, 'geojson');
t.type(result.feature, 'object');
t.type(result.feature.properties, 'object');
t.equal(result.feature.id, 'philly_metro.geojson'); // has an id
t.equal(result.feature.properties.id, 'philly_metro.geojson'); // has an id property
t.match(result.feature.properties, { area: /\d+/ }); // has a numeric area property
t.equal(result.location, location);
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, 'philly_metro.geojson'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, 'philly_metro.geojson'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.test('`.geojson` identifiers compare as lowercase', t => {
const result = loco.resolveLocation('PHiLLy_MeTRo.GeoJSoN');
const location = 'PHiLLy_MeTRo.GeoJSoN';
const result = loco.resolveLocation(location);
t.notEqual(result, null);
t.equal(result.type, 'geojson');
t.type(result.feature, 'object');
t.type(result.feature.properties, 'object');
t.equal(result.feature.id, 'philly_metro.geojson'); // has an id
t.equal(result.feature.properties.id, 'philly_metro.geojson'); // has an id property
t.match(result.feature.properties, { area: /\d+/ }); // has a numeric area property
t.equal(result.location, location);
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, 'philly_metro.geojson'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, 'philly_metro.geojson'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.test('an invalid `.geojson` filename returns a null match', t => {
const result = loco.resolveLocation('fake.geojson');
t.equal(result, null);
t.test('(strict mode) an invalid `.geojson` filename throws an error', t => {
const location = 'fake.geojson';
t.throws(() => loco.resolveLocation(location));
t.end();
});
t.test('(non strict mode) an invalid `.geojson` filename returns falsy', t => {
const location = 'fake.geojson';
t.notOk(locoNS.resolveLocation(location));
t.end();
});
t.end();

@@ -79,17 +98,24 @@ });

t.test('a valid country coder feature identifier returns a feature match', t => {
const result = loco.resolveLocation('gb');
const location = 'gb';
const result = loco.resolveLocation(location);
t.notEqual(result, null);
t.equal(result.type, 'countrycoder');
t.type(result.feature, 'object');
t.type(result.feature.properties, 'object');
t.equal(result.feature.id, 'Q145'); // has an id
t.equal(result.feature.properties.id, 'Q145'); // has an id property
t.match(result.feature.properties, { area: /\d+/ }); // has a numeric area property
t.equal(result.location, location);
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, 'Q145'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, 'Q145'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.test('an invalid country coder feature identifier returns a null match', t => {
const result = loco.resolveLocation('fake');
t.equal(result, null);
t.test('(strict mode) an invalid country coder feature identifier throws an error', t => {
const location = 'fake';
t.throws(() => loco.resolveLocation(location));
t.end();
});
t.test('(non strict mode) an invalid country coder feature identifier returns falsy', t => {
const location = 'fake';
t.notOk(locoNS.resolveLocation(location));
t.end();
});
t.end();

@@ -96,0 +122,0 @@ });

@@ -6,92 +6,186 @@ const test = require('tap').test;

const loco = new LocationConflation(features);
const locoNS = new LocationConflation(features).strict(false);
test('resolveLocationSet', t => {
t.test('empty include defaults to world (Q2)', t => {
const locationSet = { };
const result = loco.resolveLocationSet(locationSet);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, 'Q2');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.end();
});
t.test('sorts included countrycoder locations', t => {
const locationSet = { include: ['013', '005'] };
const result = loco.resolveLocationSet(locationSet);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, '+[Q18,Q27611]');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.test('empty locationSet', t => {
t.test('(strict mode) empty locationSet throws an error', t => {
const locationSet = { };
t.throws(() => loco.resolveLocationSet(locationSet));
t.end();
});
t.test('(non strict mode) empty locationSet defaults to world (Q2)', t => {
const locationSet = { };
const result = locoNS.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[Q2]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, 'Q2'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, 'Q2'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.end();
});
t.test('sorts excluded countrycoder locations', t => {
const locationSet = { exclude: ['013', '005'] };
const result = loco.resolveLocationSet(locationSet);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, '+[Q2]-[Q18,Q27611]');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.test('country coder feature identifiers', t => {
t.test('sorts included countrycoder locations', t => {
const locationSet = { include: ['013', '005'] };
const result = loco.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[Q18,Q27611]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, '+[Q18,Q27611]'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, '+[Q18,Q27611]'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.test('sorts excluded countrycoder locations', t => {
const locationSet = { include: ['001'], exclude: ['013', '005'] };
const result = loco.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[Q2]-[Q18,Q27611]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, '+[Q2]-[Q18,Q27611]'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, '+[Q2]-[Q18,Q27611]'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.end();
});
t.test('sorts included .geojson locations', t => {
const locationSet = { include: ['philly_metro.geojson', 'dc_metro.geojson'] };
const result = loco.resolveLocationSet(locationSet);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, '+[dc_metro.geojson,philly_metro.geojson]');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.test('`.geojson` filenames', t => {
t.test('sorts included .geojson locations', t => {
const locationSet = { include: ['philly_metro.geojson', 'dc_metro.geojson'] };
const result = loco.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[dc_metro.geojson,philly_metro.geojson]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, '+[dc_metro.geojson,philly_metro.geojson]'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, '+[dc_metro.geojson,philly_metro.geojson]'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a `numeric` area property
t.end();
});
t.test('sorts excluded .geojson locations', t => {
const locationSet = { include: ['001'], exclude: ['philly_metro.geojson', 'dc_metro.geojson'] };
const result = loco.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[Q2]-[dc_metro.geojson,philly_metro.geojson]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, '+[Q2]-[dc_metro.geojson,philly_metro.geojson]'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, '+[Q2]-[dc_metro.geojson,philly_metro.geojson]'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.end();
});
t.test('sorts excluded .geojson locations', t => {
const locationSet = { exclude: ['philly_metro.geojson', 'dc_metro.geojson'] };
const result = loco.resolveLocationSet(locationSet);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, '+[Q2]-[dc_metro.geojson,philly_metro.geojson]');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.test('points', t => {
t.test('sorts included point locations', t => {
const locationSet = { include: [[1, 0], [0, 1], [1, 1], [0, 0]] };
const result = loco.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[[0,0],[0,1],[1,0],[1,1]]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, '+[[0,0],[0,1],[1,0],[1,1]]'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, '+[[0,0],[0,1],[1,0],[1,1]]'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.test('sorts excluded point locations', t => {
const locationSet = { include: ['001'], exclude: [[1, 0], [0, 1], [1, 1], [0, 0]] };
const result = loco.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[Q2]-[[0,0],[0,1],[1,0],[1,1]]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, '+[Q2]-[[0,0],[0,1],[1,0],[1,1]]'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, '+[Q2]-[[0,0],[0,1],[1,0],[1,1]]'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.end();
});
t.test('sorts included point locations', t => {
const locationSet = { include: [[1, 0], [0, 1], [1, 1], [0, 0]] };
const result = loco.resolveLocationSet(locationSet);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, '+[[0,0],[0,1],[1,0],[1,1]]');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.test('(strict mode) included junk locations throw an error', t => {
const locationSet = { include: ['fake', 'null'] };
t.throws(() => loco.resolveLocationSet(locationSet));
t.end();
});
t.test('sorts excluded point locations', t => {
const locationSet = { exclude: [[1, 0], [0, 1], [1, 1], [0, 0]] };
const result = loco.resolveLocationSet(locationSet);
t.test('(non strict mode) ignores included junk locations', t => {
const locationSet = { include: ['fake', 'null'] };
const result = locoNS.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, '+[Q2]-[[0,0],[0,1],[1,0],[1,1]]');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[Q2]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, 'Q2'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, 'Q2'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.test('ignores included junk locations', t => {
const locationSet = { include: ['fake', 'null'] };
const result = loco.resolveLocationSet(locationSet);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, 'Q2');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.test('(strict mode) excluded junk locations throw an error', t => {
const locationSet = { include: ['001'], exclude: ['fake', 'null'] };
t.throws(() => loco.resolveLocationSet(locationSet));
t.end();
});
t.test('ignores excluded junk locations', t => {
const locationSet = { exclude: ['fake', 'null'] };
const result = loco.resolveLocationSet(locationSet);
t.test('(non strict mode) ignores excluded junk locations', t => {
const locationSet = { include: ['001'], exclude: ['fake', 'null'] };
const result = locoNS.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, 'Q2');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[Q2]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, 'Q2'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, 'Q2'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();

@@ -103,6 +197,12 @@ });

const result = loco.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, '+[Q16,philly_metro.geojson,[0,0]]');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[Q16,philly_metro.geojson,[0,0]]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, '+[Q16,philly_metro.geojson,[0,0]]'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, '+[Q16,philly_metro.geojson,[0,0]]'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();

@@ -112,22 +212,18 @@ });

t.test('sorts excluded countrycoder < geojson < point', t => {
const locationSet = { exclude: ['philly_metro.geojson', [0,0], 'ca'] };
const locationSet = { include: ['001'], exclude: ['philly_metro.geojson', [0,0], 'ca'] };
const result = loco.resolveLocationSet(locationSet);
t.notEqual(result, null);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, '+[Q2]-[Q16,philly_metro.geojson,[0,0]]');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.equal(result.type, 'locationset');
t.equal(result.locationSet, locationSet);
t.equal(result.id, '+[Q2]-[Q16,philly_metro.geojson,[0,0]]');
t.type(result.feature, 'object'); // result includes a `feature`
t.equal(result.feature.id, '+[Q2]-[Q16,philly_metro.geojson,[0,0]]'); // feature has an `id`
t.type(result.feature.properties, 'object'); // feature has `properties`
t.equal(result.feature.properties.id, '+[Q2]-[Q16,philly_metro.geojson,[0,0]]'); // properties has an `id` property
t.match(result.feature.properties, { area: /\d+/ }); // properties has a numeric `area` property
t.end();
});
t.test('force lowercase', t => {
const locationSet = { include: ['US'], exclude: ['PR'] };
const result = loco.resolveLocationSet(locationSet);
t.type(result, 'object');
t.type(result.properties, 'object');
t.equal(result.properties.id, '+[Q30]-[Q1183]');
t.match(result.properties, { area: /\d+/ }); // has a numeric area property
t.end();
});
t.end();
});

@@ -6,2 +6,3 @@ const test = require('tap').test;

const loco = new LocationConflation(features);
const locoNS = new LocationConflation(features).strict(false);

@@ -17,2 +18,3 @@

t.equal(result.type, 'point');
t.equal(result.location, val);
t.equal(result.id, '[' + val.toString() + ']');

@@ -22,13 +24,24 @@ });

});
t.test('an invalid [lon,lat] coordinate pair returns false', t => {
t.notOk(loco.validateLocation([]));
t.notOk(loco.validateLocation(['a']));
t.notOk(loco.validateLocation([0]));
t.notOk(loco.validateLocation([0, 0, 0]));
t.notOk(loco.validateLocation([-181, -90]));
t.notOk(loco.validateLocation([-180, 91]));
t.notOk(loco.validateLocation([181, -90]));
t.notOk(loco.validateLocation([180, 91]));
t.test('(strict mode) an invalid [lon,lat] coordinate pair throws an error', t => {
t.throws(() => loco.validateLocation([]));
t.throws(() => loco.validateLocation(['a']));
t.throws(() => loco.validateLocation([0]));
t.throws(() => loco.validateLocation([0, 0, 0]));
t.throws(() => loco.validateLocation([-181, -90]));
t.throws(() => loco.validateLocation([-180, 91]));
t.throws(() => loco.validateLocation([181, -90]));
t.throws(() => loco.validateLocation([180, 91]));
t.end();
});
t.test('(non strict mode) an invalid [lon,lat] coordinate pair returns falsy', t => {
t.notOk(locoNS.validateLocation([]));
t.notOk(locoNS.validateLocation(['a']));
t.notOk(locoNS.validateLocation([0]));
t.notOk(locoNS.validateLocation([0, 0, 0]));
t.notOk(locoNS.validateLocation([-181, -90]));
t.notOk(locoNS.validateLocation([-180, 91]));
t.notOk(locoNS.validateLocation([181, -90]));
t.notOk(locoNS.validateLocation([180, 91]));
t.end();
});
t.end();

@@ -44,2 +57,3 @@ });

t.equal(result.type, 'geojson');
t.equal(result.location, val);
t.equal(result.id, val);

@@ -49,7 +63,12 @@ });

});
t.test('an invalid `.geojson` identifier returns false', t => {
t.notOk(loco.validateLocation('philly_metro')); // missing .geojson
t.notOk(loco.validateLocation('fake.geojson')); // fake filename
t.test('(strict mode) an invalid `.geojson` identifier throws an error', t => {
t.throws(() => loco.validateLocation('philly_metro')); // missing .geojson
t.throws(() => loco.validateLocation('fake.geojson')); // fake filename
t.end();
});
t.test('(non strict mode) an invalid `.geojson` identifier returns falsy', t => {
t.notOk(locoNS.validateLocation('philly_metro')); // missing .geojson
t.notOk(locoNS.validateLocation('fake.geojson')); // fake filename
t.end();
});
t.test('`.geojson` identifiers compare as lowercase', t => {

@@ -59,2 +78,3 @@ const result = loco.validateLocation('PHiLLy_MeTRo.GeoJSoN');

t.equal(result.type, 'geojson');
t.equal(result.location, 'PHiLLy_MeTRo.GeoJSoN');
t.equal(result.id, 'philly_metro.geojson');

@@ -73,2 +93,3 @@ t.end();

t.equal(result.type, 'countrycoder');
t.equal(result.location, val);
t.equal(result.id, 'Q145');

@@ -78,8 +99,14 @@ });

});
t.test('an invalid country coder identifier returns false', t => {
t.notOk(loco.validateLocation(''));
t.notOk(loco.validateLocation('false'));
t.notOk(loco.validateLocation('null'));
t.test('(strict mode) an invalid country coder identifier throws an error', t => {
t.throws(() => loco.validateLocation(''));
t.throws(() => loco.validateLocation('false'));
t.throws(() => loco.validateLocation('null'));
t.end();
});
t.test('(non strict mode) an invalid country coder identifier returns falsy', t => {
t.notOk(locoNS.validateLocation(''));
t.notOk(locoNS.validateLocation('false'));
t.notOk(locoNS.validateLocation('null'));
t.end();
});
t.end();

@@ -86,0 +113,0 @@ });

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc