mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 01:02:58 +00:00
Properly export areaKeys, fix preset and maprules tests
This commit is contained in:
@@ -484,7 +484,7 @@ export function coreContext() {
|
||||
var maprules = utilStringQs(window.location.hash).maprules;
|
||||
d3_json(maprules, function (err, mapcss) {
|
||||
if (err) return;
|
||||
services.maprules.init(context.presets().areaKeys());
|
||||
services.maprules.init();
|
||||
_each(mapcss, function(mapcssSelector) {
|
||||
return services.maprules.addRule(mapcssSelector);
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ export * from './validations/index';
|
||||
import { services } from './services/index';
|
||||
var Connection = services.osm;
|
||||
export { Connection };
|
||||
export { coreContext as Context, setAreaKeys } from './core/context';
|
||||
export { coreContext as Context, setAreaKeys, areaKeys } from './core/context';
|
||||
export { coreDifference as Difference } from './core/difference';
|
||||
export { coreGraph as Graph } from './core/graph';
|
||||
export { coreHistory as History } from './core/history';
|
||||
|
||||
@@ -4,7 +4,6 @@ export function osmIsInterestingTag(key) {
|
||||
key !== 'source' &&
|
||||
key !== 'odbl' &&
|
||||
key.indexOf('tiger:') !== 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ import _isMatch from 'lodash-es/isMatch';
|
||||
import _intersection from 'lodash-es/intersection';
|
||||
import _reduce from 'lodash-es/reduce';
|
||||
import _every from 'lodash-es/every';
|
||||
import { areaKeys } from '../core/context';
|
||||
|
||||
|
||||
var buildRuleChecks = function() {
|
||||
return {
|
||||
@@ -95,12 +97,13 @@ var buildLineKeys = function() {
|
||||
};
|
||||
|
||||
export default {
|
||||
init: function(areaKeys) {
|
||||
init: function() {
|
||||
this._ruleChecks = buildRuleChecks();
|
||||
this._validationRules = [];
|
||||
this._areaKeys = areaKeys;
|
||||
this._lineKeys = buildLineKeys();
|
||||
},
|
||||
|
||||
// list of rules only relevant to tag checks...
|
||||
filterRuleChecks: function(selector) {
|
||||
var _ruleChecks = this._ruleChecks;
|
||||
@@ -111,6 +114,7 @@ export default {
|
||||
return rules;
|
||||
}, []);
|
||||
},
|
||||
|
||||
// builds tagMap from mapcss-parse selector object...
|
||||
buildTagMap: function(selector) {
|
||||
var getRegexValues = function(regexes) {
|
||||
@@ -153,6 +157,7 @@ export default {
|
||||
|
||||
return tagMap;
|
||||
},
|
||||
|
||||
// inspired by osmWay#isArea()
|
||||
inferGeometry: function(tagMap) {
|
||||
var _lineKeys = this._lineKeys;
|
||||
@@ -185,6 +190,7 @@ export default {
|
||||
|
||||
return 'line';
|
||||
},
|
||||
|
||||
// adds from mapcss-parse selector check...
|
||||
addRule: function(selector) {
|
||||
var rule = {
|
||||
@@ -219,9 +225,12 @@ export default {
|
||||
};
|
||||
this._validationRules.push(rule);
|
||||
},
|
||||
|
||||
clearRules: function() { this._validationRules = []; },
|
||||
|
||||
// returns validationRules...
|
||||
validationRules: function() { return this._validationRules; },
|
||||
|
||||
// returns ruleChecks
|
||||
ruleChecks: function() { return this._ruleChecks; }
|
||||
};
|
||||
|
||||
@@ -149,12 +149,12 @@ describe('iD.presetCollection', function() {
|
||||
|
||||
it('excludes presets with searchable: false', function() {
|
||||
var excluded = iD.presetPreset('__test/excluded', {
|
||||
name: 'excluded',
|
||||
tags: { amenity: 'excluded' },
|
||||
geometry: ['point'],
|
||||
searchable: false
|
||||
}),
|
||||
collection = iD.presetCollection([excluded, p.point]);
|
||||
name: 'excluded',
|
||||
tags: { amenity: 'excluded' },
|
||||
geometry: ['point'],
|
||||
searchable: false
|
||||
});
|
||||
var collection = iD.presetCollection([excluded, p.point]);
|
||||
expect(collection.search('excluded', 'point').collection).not.to.include(excluded);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,55 +1,42 @@
|
||||
describe('iD.presetIndex', function () {
|
||||
var savedPresets, server;
|
||||
var savedPresets, savedAreaKeys, server;
|
||||
|
||||
before(function () {
|
||||
savedPresets = iD.data.presets;
|
||||
savedAreaKeys = iD.areaKeys;
|
||||
});
|
||||
|
||||
after(function () {
|
||||
iD.data.presets = savedPresets;
|
||||
iD.setAreaKeys(savedAreaKeys);
|
||||
});
|
||||
|
||||
describe('#match', function () {
|
||||
var testPresets = {
|
||||
presets: {
|
||||
point: {
|
||||
tags: {},
|
||||
geometry: ['point']
|
||||
},
|
||||
line: {
|
||||
tags: {},
|
||||
geometry: ['line']
|
||||
},
|
||||
vertex: {
|
||||
tags: {},
|
||||
geometry: ['vertex']
|
||||
},
|
||||
residential: {
|
||||
tags: { highway: 'residential' },
|
||||
geometry: ['line']
|
||||
},
|
||||
park: {
|
||||
tags: { leisure: 'park' },
|
||||
geometry: ['point', 'area']
|
||||
}
|
||||
point: { tags: {}, geometry: ['point'] },
|
||||
line: { tags: {}, geometry: ['line'] },
|
||||
vertex: { tags: {}, geometry: ['vertex'] },
|
||||
residential: { tags: { highway: 'residential' }, geometry: ['line'] },
|
||||
park: { tags: { leisure: 'park' }, geometry: ['point', 'area'] }
|
||||
}
|
||||
};
|
||||
|
||||
it('returns a collection containing presets matching a geometry and tags', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
way = iD.Way({ tags: { highway: 'residential' } }),
|
||||
graph = iD.Graph([way]);
|
||||
var presets = iD.coreContext().presets();
|
||||
var way = iD.osmWay({ tags: { highway: 'residential' } });
|
||||
var graph = iD.coreGraph([way]);
|
||||
|
||||
expect(presets.match(way, graph).id).to.eql('residential');
|
||||
});
|
||||
|
||||
it('returns the appropriate fallback preset when no tags match', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
point = iD.Node(),
|
||||
line = iD.Way({ tags: { foo: 'bar' } }),
|
||||
graph = iD.Graph([point, line]);
|
||||
var presets = iD.coreContext().presets();
|
||||
var point = iD.osmNode();
|
||||
var line = iD.osmWay({ tags: { foo: 'bar' } });
|
||||
var graph = iD.coreGraph([point, line]);
|
||||
|
||||
expect(presets.match(point, graph).id).to.eql('point');
|
||||
expect(presets.match(line, graph).id).to.eql('line');
|
||||
@@ -57,20 +44,20 @@ describe('iD.presetIndex', function () {
|
||||
|
||||
it('matches vertices on a line as vertices', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
point = iD.Node({ tags: { leisure: 'park' } }),
|
||||
line = iD.Way({ nodes: [point.id], tags: { 'highway': 'residential' } }),
|
||||
graph = iD.Graph([point, line]);
|
||||
var presets = iD.coreContext().presets();
|
||||
var point = iD.osmNode({ tags: { leisure: 'park' } });
|
||||
var line = iD.osmWay({ nodes: [point.id], tags: { 'highway': 'residential' } });
|
||||
var graph = iD.coreGraph([point, line]);
|
||||
|
||||
expect(presets.match(point, graph).id).to.eql('vertex');
|
||||
});
|
||||
|
||||
it('matches vertices on an addr:interpolation line as points', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
point = iD.Node({ tags: { leisure: 'park' } }),
|
||||
line = iD.Way({ nodes: [point.id], tags: { 'addr:interpolation': 'even' } }),
|
||||
graph = iD.Graph([point, line]);
|
||||
var presets = iD.coreContext().presets();
|
||||
var point = iD.osmNode({ tags: { leisure: 'park' } });
|
||||
var line = iD.osmWay({ nodes: [point.id], tags: { 'addr:interpolation': 'even' } });
|
||||
var graph = iD.coreGraph([point, line]);
|
||||
|
||||
expect(presets.match(point, graph).id).to.eql('park');
|
||||
});
|
||||
@@ -80,119 +67,97 @@ describe('iD.presetIndex', function () {
|
||||
describe('#areaKeys', function () {
|
||||
var testPresets = {
|
||||
presets: {
|
||||
'amenity/fuel/shell': {
|
||||
tags: { 'amenity': 'fuel' },
|
||||
geometry: ['point', 'area'],
|
||||
suggestion: true
|
||||
},
|
||||
'highway/foo': {
|
||||
tags: { 'highway': 'foo' },
|
||||
geometry: ['area']
|
||||
},
|
||||
'leisure/track': {
|
||||
tags: { 'leisure': 'track' },
|
||||
geometry: ['line', 'area']
|
||||
},
|
||||
'natural': {
|
||||
tags: { 'natural': '*' },
|
||||
geometry: ['point', 'vertex', 'area']
|
||||
},
|
||||
'natural/peak': {
|
||||
tags: { 'natural': 'peak' },
|
||||
geometry: ['point', 'vertex']
|
||||
},
|
||||
'natural/tree_row': {
|
||||
tags: { 'natural': 'tree_row' },
|
||||
geometry: ['line']
|
||||
},
|
||||
'natural/wood': {
|
||||
tags: { 'natural': 'wood' },
|
||||
geometry: ['point', 'area']
|
||||
}
|
||||
'amenity/fuel/shell': { tags: { 'amenity': 'fuel' }, geometry: ['point', 'area'], suggestion: true },
|
||||
'highway/foo': { tags: { 'highway': 'foo' }, geometry: ['area'] },
|
||||
'leisure/track': { tags: { 'leisure': 'track' }, geometry: ['line', 'area'] },
|
||||
'natural': { tags: { 'natural': '*' }, geometry: ['point', 'vertex', 'area'] },
|
||||
'natural/peak': { tags: { 'natural': 'peak' }, geometry: ['point', 'vertex'] },
|
||||
'natural/tree_row': { tags: { 'natural': 'tree_row' }, geometry: ['line'] },
|
||||
'natural/wood': { tags: { 'natural': 'wood' }, geometry: ['point', 'area'] }
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
it('whitelists keys for presets with area geometry', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
var presets = iD.coreContext().presets();
|
||||
expect(presets.areaKeys()).to.include.keys('natural');
|
||||
});
|
||||
|
||||
it('blacklists key-values for presets with a line geometry', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
var presets = iD.coreContext().presets();
|
||||
expect(presets.areaKeys().natural).to.include.keys('tree_row');
|
||||
expect(presets.areaKeys().natural.tree_row).to.be.true;
|
||||
});
|
||||
|
||||
it('blacklists key-values for presets with both area and line geometry', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
var presets = iD.coreContext().presets();
|
||||
expect(presets.areaKeys().leisure).to.include.keys('track');
|
||||
});
|
||||
|
||||
it('does not blacklist key-values for presets with neither area nor line geometry', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
var presets = iD.coreContext().presets();
|
||||
expect(presets.areaKeys().natural).not.to.include.keys('peak');
|
||||
});
|
||||
|
||||
it('does not blacklist generic \'*\' key-values', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
var presets = iD.coreContext().presets();
|
||||
expect(presets.areaKeys().natural).not.to.include.keys('natural');
|
||||
});
|
||||
|
||||
it('ignores keys like \'highway\' that are assumed to be lines', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
var presets = iD.coreContext().presets();
|
||||
expect(presets.areaKeys()).not.to.include.keys('highway');
|
||||
});
|
||||
|
||||
it('ignores suggestion presets', function () {
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.Context().presets();
|
||||
var presets = iD.coreContext().presets();
|
||||
expect(presets.areaKeys()).not.to.include.keys('amenity');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#build', function () {
|
||||
it('builds presets from provided', function () {
|
||||
var surfShop = iD.Node({ tags: { amenity: 'shop', 'shop:type': 'surf' } }),
|
||||
graph = iD.Graph([surfShop]),
|
||||
presets = iD.Context().presets(),
|
||||
morePresets = {
|
||||
presets: {
|
||||
'amenity/shop/surf': {
|
||||
tags: { amenity: 'shop', 'shop:type': 'surf' },
|
||||
geometry: ['point', 'area']
|
||||
}
|
||||
var surfShop = iD.osmNode({ tags: { amenity: 'shop', 'shop:type': 'surf' } });
|
||||
var graph = iD.coreGraph([surfShop]);
|
||||
var presets = iD.coreContext().presets();
|
||||
var morePresets = {
|
||||
presets: {
|
||||
'amenity/shop/surf': {
|
||||
tags: { amenity: 'shop', 'shop:type': 'surf' },
|
||||
geometry: ['point', 'area']
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
expect(presets.match(surfShop, graph)).to.eql(undefined); // no surfshop preset yet...
|
||||
presets.build(morePresets, true);
|
||||
expect(presets.match(surfShop, graph).addTags).to.eql({ amenity: 'shop', 'shop:type': 'surf' });
|
||||
});
|
||||
|
||||
it('configures presets\' initial visibility', function () {
|
||||
var surfShop = iD.Node({ tags: { amenity: 'shop', 'shop:type': 'surf' } }),
|
||||
firstStreetJetty = iD.Node({ tags: { man_made: 'jetty' } }),
|
||||
entities = [surfShop, firstStreetJetty],
|
||||
graph = iD.Graph(entities),
|
||||
presets = iD.Context().presets(),
|
||||
morePresets = {
|
||||
presets: {
|
||||
'amenity/shop/surf': {
|
||||
tags: { amenity: 'shop', 'shop:type': 'surf' },
|
||||
geometry: ['point', 'area']
|
||||
},
|
||||
'man_made/jetty': {
|
||||
tags: { man_made: 'jetty' },
|
||||
geometry: ['point']
|
||||
}
|
||||
var surfShop = iD.osmNode({ tags: { amenity: 'shop', 'shop:type': 'surf' } });
|
||||
var firstStreetJetty = iD.osmNode({ tags: { man_made: 'jetty' } });
|
||||
var entities = [surfShop, firstStreetJetty];
|
||||
var graph = iD.coreGraph(entities);
|
||||
var presets = iD.coreContext().presets();
|
||||
var morePresets = {
|
||||
presets: {
|
||||
'amenity/shop/surf': {
|
||||
tags: { amenity: 'shop', 'shop:type': 'surf' },
|
||||
geometry: ['point', 'area']
|
||||
},
|
||||
'man_made/jetty': {
|
||||
tags: { man_made: 'jetty' },
|
||||
geometry: ['point']
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
presets.build(morePresets, false);
|
||||
entities.forEach(function (entity) {
|
||||
@@ -203,241 +168,143 @@ describe('iD.presetIndex', function () {
|
||||
});
|
||||
|
||||
describe('expected matches', function () {
|
||||
var testPresets = {
|
||||
presets: {
|
||||
area: { name: 'Area', tags: {}, geometry: ['area'] },
|
||||
line: { name: 'Line', tags: {}, geometry: ['line'] },
|
||||
point: { name: 'Point', tags: {}, geometry: ['point'] },
|
||||
vertex: { name: 'Vertex', tags: {}, geometry: ['vertex'] },
|
||||
relation: { name: 'Relation', tags: {}, geometry: ['relation'] },
|
||||
building: { name: 'Building', tags: { building: 'yes' }, geometry: ['area'] },
|
||||
'type/multipolygon': {
|
||||
name: 'Multipolygon',
|
||||
geometry: ['area', 'relation'],
|
||||
tags: { 'type': 'multipolygon' },
|
||||
searchable: false,
|
||||
matchScore: 0.1
|
||||
},
|
||||
address: {
|
||||
name: 'Address',
|
||||
geometry: ['point', 'vertex', 'area'],
|
||||
tags: { 'addr:*': '*' },
|
||||
matchScore: 0.15
|
||||
},
|
||||
'highway/pedestrian_area': {
|
||||
name: 'Pedestrian Area',
|
||||
geometry: ['area'],
|
||||
tags: { highway: 'pedestrian', area: 'yes' }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
it('prefers building to multipolygon', function () {
|
||||
iD.data.presets = savedPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
relation = iD.Relation({ tags: { type: 'multipolygon', building: 'yes' } }),
|
||||
graph = iD.Graph([relation]);
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.coreContext().presets();
|
||||
var relation = iD.osmRelation({ tags: { type: 'multipolygon', building: 'yes' } });
|
||||
var graph = iD.coreGraph([relation]);
|
||||
expect(presets.match(relation, graph).id).to.eql('building');
|
||||
});
|
||||
|
||||
it('prefers building to address', function () {
|
||||
iD.data.presets = savedPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
way = iD.Way({ tags: { area: 'yes', building: 'yes', 'addr:housenumber': '1234' } }),
|
||||
graph = iD.Graph([way]);
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.coreContext().presets();
|
||||
var way = iD.osmWay({ tags: { area: 'yes', building: 'yes', 'addr:housenumber': '1234' } });
|
||||
var graph = iD.coreGraph([way]);
|
||||
expect(presets.match(way, graph).id).to.eql('building');
|
||||
});
|
||||
|
||||
it('prefers pedestrian to area', function () {
|
||||
iD.data.presets = savedPresets;
|
||||
var presets = iD.Context().presets(),
|
||||
way = iD.Way({ tags: { area: 'yes', highway: 'pedestrian' } }),
|
||||
graph = iD.Graph([way]);
|
||||
iD.data.presets = testPresets;
|
||||
var presets = iD.coreContext().presets();
|
||||
var way = iD.osmWay({ tags: { area: 'yes', highway: 'pedestrian' } });
|
||||
var graph = iD.coreGraph([way]);
|
||||
expect(presets.match(way, graph).id).to.eql('highway/pedestrian_area');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#fromExternal', function () {
|
||||
var morePresets;
|
||||
before(function () {
|
||||
morePresets = {
|
||||
'categories': {
|
||||
'category-area': {
|
||||
'icon': 'maki-natural',
|
||||
'geometry': 'area',
|
||||
'name': 'MapRules area Features',
|
||||
'members': [
|
||||
'8bc64d6d-1dbb-44a8-a2f9-80d41d067d78',
|
||||
'a9b78746-ca8a-4380-b340-157414f1464d'
|
||||
]
|
||||
},
|
||||
'category-point': {
|
||||
'icon': 'maki-natural',
|
||||
'geometry': 'point',
|
||||
'name': 'MapRules point Features',
|
||||
'members': [
|
||||
'8bc64d6d-1dbb-44a8-a2f9-80d41d067d78',
|
||||
'8f83ed0b-6514-4772-a644-f04aad9d2308'
|
||||
]
|
||||
}
|
||||
},
|
||||
'presets': {
|
||||
'8bc64d6d-1dbb-44a8-a2f9-80d41d067d78': {
|
||||
'geometry': ['area', 'point'],
|
||||
'tags': { 'amenity': 'shop', 'shop:type': 'surf' },
|
||||
'icon': 'maki-natural',
|
||||
'name': 'Surf Shop',
|
||||
'fields': ['358f404a-c7d5-4267-94ed-41f789b16228'],
|
||||
'matchScore': 0.99
|
||||
},
|
||||
'a9b78746-ca8a-4380-b340-157414f1464d': {
|
||||
'geometry': ['area'],
|
||||
'tags': { 'amenity': 'marketplace' },
|
||||
'icon': 'maki-natural',
|
||||
'name': 'Market',
|
||||
'fields': [
|
||||
'name',
|
||||
'source',
|
||||
'2161a712-f67f-4759-92fa-f5d9488ba969',
|
||||
'368ecbdf-bc02-4de2-a82e-d51c250602da',
|
||||
'1887834c-0cdd-4d40-852b-d29b8df94567'
|
||||
],
|
||||
'matchScore': 0.99
|
||||
},
|
||||
'8f83ed0b-6514-4772-a644-f04aad9d2308': {
|
||||
'geometry': ['point'],
|
||||
'tags': {
|
||||
'amenity': 'drinking_water',
|
||||
'man_made': 'water_tap'
|
||||
},
|
||||
'icon': 'maki-natural',
|
||||
'name': 'Water Tap',
|
||||
'fields': ['name'],
|
||||
'matchScore': 0.99
|
||||
}
|
||||
},
|
||||
'fields': {
|
||||
'358f404a-c7d5-4267-94ed-41f789b16228': {
|
||||
'key': 'healthcare',
|
||||
'label': 'Healthcare',
|
||||
'overrideLabel': 'Healthcare',
|
||||
'placeholder': '...',
|
||||
'type': 'text'
|
||||
},
|
||||
'name': {
|
||||
'key': 'name',
|
||||
'type': 'localized',
|
||||
'label': 'Name',
|
||||
'universal': true,
|
||||
'placeholder': 'Common name (if any)'
|
||||
},
|
||||
'source': {
|
||||
'key': 'source',
|
||||
'type': 'semiCombo',
|
||||
'icon': 'source',
|
||||
'universal': true,
|
||||
'label': 'Sources',
|
||||
'snake_case': false,
|
||||
'caseSensitive': true,
|
||||
'options': [
|
||||
'survey',
|
||||
'local knowledge',
|
||||
'gps',
|
||||
'aerial imagery',
|
||||
'streetlevel imagery'
|
||||
]
|
||||
},
|
||||
'2161a712-f67f-4759-92fa-f5d9488ba969': {
|
||||
'key': 'building',
|
||||
'label': 'Building',
|
||||
'overrideLabel': 'Building',
|
||||
'placeholder': '...',
|
||||
'type': 'text'
|
||||
},
|
||||
'368ecbdf-bc02-4de2-a82e-d51c250602da': {
|
||||
'key': 'opening_hours',
|
||||
'label': 'Opening Hours',
|
||||
'overrideLabel': 'Opening Hours',
|
||||
'placeholder': '24/7, sunrise to sunset...',
|
||||
'strings': {
|
||||
'options': {
|
||||
'24/7': '24/7',
|
||||
'sunrise to sunset': 'sunrise to sunset'
|
||||
}
|
||||
},
|
||||
'type': 'combo'
|
||||
},
|
||||
'1887834c-0cdd-4d40-852b-d29b8df94567': {
|
||||
'key': 'height',
|
||||
'label': 'Height',
|
||||
'overrideLabel': 'Height',
|
||||
'placeholder': '...',
|
||||
'minValue': 1, 'type': 'number'
|
||||
},
|
||||
'relation': {
|
||||
'key': 'type',
|
||||
'type': 'combo',
|
||||
'label': 'Type'
|
||||
},
|
||||
'comment': {
|
||||
'key': 'comment',
|
||||
'type': 'textarea',
|
||||
'label': 'Changeset Comment',
|
||||
'placeholder': 'Brief description of your contributions (required)'
|
||||
},
|
||||
'hashtags': {
|
||||
'key': 'hashtags',
|
||||
'type': 'semiCombo',
|
||||
'label': 'Suggested Hashtags',
|
||||
'placeholder': '#example'
|
||||
}
|
||||
},
|
||||
'defaults': {
|
||||
'point': [
|
||||
'point',
|
||||
'8bc64d6d-1dbb-44a8-a2f9-80d41d067d78',
|
||||
'8f83ed0b-6514-4772-a644-f04aad9d2308'
|
||||
],
|
||||
'line': ['line'],
|
||||
'area': [
|
||||
'area',
|
||||
'8bc64d6d-1dbb-44a8-a2f9-80d41d067d78',
|
||||
'a9b78746-ca8a-4380-b340-157414f1464d'
|
||||
],
|
||||
'vertex': ['vertex'],
|
||||
'relation': ['relation']
|
||||
var origPresets = {
|
||||
presets: {
|
||||
area: { name: 'Area', tags: {}, geometry: ['area'] },
|
||||
line: { name: 'Line', tags: {}, geometry: ['line'] },
|
||||
point: { name: 'Point', tags: {}, geometry: ['point'] },
|
||||
vertex: { name: 'Vertex', tags: {}, geometry: ['vertex'] },
|
||||
relation: { name: 'Relation', tags: {}, geometry: ['relation'] },
|
||||
building: { name: 'Building', tags: { building: 'yes' }, geometry: ['area'] }
|
||||
}
|
||||
};
|
||||
|
||||
var morePresets = {
|
||||
presets: {
|
||||
'8bc64d6d': {
|
||||
'name': 'Surf Shop',
|
||||
'geometry': ['area', 'point'],
|
||||
'fields': ['2161a712'],
|
||||
'tags': { 'amenity': 'shop', 'shop:type': 'surf' },
|
||||
'matchScore': 0.99
|
||||
}
|
||||
};
|
||||
},
|
||||
'fields': {
|
||||
'2161a712': {
|
||||
'key': 'building',
|
||||
'label': 'Building',
|
||||
'overrideLabel': 'Building',
|
||||
'type': 'text'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
beforeEach(function () {
|
||||
server = sinon.fakeServer.create();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
server.restore();
|
||||
});
|
||||
|
||||
it('builds presets w/external sources set to visible', function () {
|
||||
var surfShop = iD.Node({ tags: { amenity: 'shop', 'shop:type': 'surf' } }),
|
||||
graph = iD.Graph([surfShop]),
|
||||
maprules = 'https://fakemaprules.io',
|
||||
presetLocation = '/config/dfcfac13-ba7c-4223-8880-c856180e5c5b/presets/iD/',
|
||||
match = new RegExp(presetLocation),
|
||||
external = maprules + presetLocation;
|
||||
|
||||
// no exernal presets yet
|
||||
expect(iD.Context().presets().match(surfShop, graph).id).to.eql('amenity');
|
||||
var surfShop = iD.osmNode({ tags: { amenity: 'shop', 'shop:type': 'surf' } });
|
||||
var graph = iD.coreGraph([surfShop]);
|
||||
var url = 'https://fakemaprules.io/fake.json';
|
||||
|
||||
// no exernal presets yet
|
||||
expect(iD.coreContext().presets().match(surfShop, graph).id).to.eql('point');
|
||||
|
||||
// reset graph...
|
||||
graph = iD.Graph([surfShop]);
|
||||
graph = iD.coreGraph([surfShop]);
|
||||
|
||||
// add the validations query param...
|
||||
iD.Context().presets().fromExternal(external, function (externalPresets) {
|
||||
// includes newer presets...
|
||||
expect(externalPresets.match(surfShop, graph).id).to.eql('8bc64d6d-1dbb-44a8-a2f9-80d41d067d78');
|
||||
iD.coreContext().presets().fromExternal(url, function (externalPresets) {
|
||||
expect(externalPresets.match(surfShop, graph).id).to.eql('8bc64d6d');
|
||||
});
|
||||
|
||||
server.respondWith('GET', match,
|
||||
server.respondWith('GET', /fake\.json/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(morePresets)]
|
||||
);
|
||||
server.respond();
|
||||
});
|
||||
it('makes only the external presets initially visible', function () {
|
||||
var maprules = 'https://fakemaprules.io',
|
||||
presetLocation = '/config/dfcfac13-ba7c-4223-8880-c856180e5c5b/presets/iD/',
|
||||
match = new RegExp(presetLocation),
|
||||
external = maprules + presetLocation;
|
||||
|
||||
iD.Context().presets().fromExternal(external, function(externalPresets) {
|
||||
var external = externalPresets.collection.reduce(function(presets, preset) {
|
||||
it('makes only the external presets initially visible', function () {
|
||||
var url = 'https://fakemaprules.io/fake.json';
|
||||
|
||||
iD.coreContext().presets().fromExternal(url, function(externalPresets) {
|
||||
var external = externalPresets.collection.reduce(function(presets, preset) {
|
||||
if (!preset.hasOwnProperty('members') && preset.visible()) {
|
||||
presets.push(preset.id);
|
||||
}
|
||||
return presets;
|
||||
}, []);
|
||||
|
||||
var morePresetKeys = Object.keys(morePresets.presets);
|
||||
|
||||
var morePresetKeys = Object.keys(morePresets.presets);
|
||||
expect(morePresetKeys.length).to.eql(external.length);
|
||||
|
||||
morePresetKeys.forEach(function(presetId) {
|
||||
expect(external.indexOf(presetId)).to.be.at.least(0);
|
||||
morePresetKeys.forEach(function(presetID) {
|
||||
expect(external.indexOf(presetID)).to.be.at.least(0);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
server.respondWith('GET', match,
|
||||
server.respondWith('GET', /fake\.json/,
|
||||
[200, { 'Content-Type': 'application/json' }, JSON.stringify(morePresets)]
|
||||
);
|
||||
server.respond();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* globals context: true */
|
||||
describe('iD.presetPreset', function() {
|
||||
it('has optional fields', function() {
|
||||
var preset = iD.presetPreset('test', {});
|
||||
@@ -19,30 +18,30 @@ describe('iD.presetPreset', function() {
|
||||
|
||||
describe('#matchScore', function() {
|
||||
it('returns -1 if preset does not match tags', function() {
|
||||
var preset = iD.presetPreset('test', {tags: {foo: 'bar'}}),
|
||||
entity = iD.Way({tags: {highway: 'motorway'}});
|
||||
var preset = iD.presetPreset('test', {tags: {foo: 'bar'}});
|
||||
var entity = iD.osmWay({tags: {highway: 'motorway'}});
|
||||
expect(preset.matchScore(entity)).to.equal(-1);
|
||||
});
|
||||
|
||||
it('returns the value of the matchScore property when matched', function() {
|
||||
var preset = iD.presetPreset('test', {tags: {highway: 'motorway'}, matchScore: 0.2}),
|
||||
entity = iD.Way({tags: {highway: 'motorway'}});
|
||||
var preset = iD.presetPreset('test', {tags: {highway: 'motorway'}, matchScore: 0.2});
|
||||
var entity = iD.osmWay({tags: {highway: 'motorway'}});
|
||||
expect(preset.matchScore(entity)).to.equal(0.2);
|
||||
});
|
||||
|
||||
it('defaults to the number of matched tags', function() {
|
||||
var preset = iD.presetPreset('test', {tags: {highway: 'residential'}}),
|
||||
entity = iD.Way({tags: {highway: 'residential'}});
|
||||
var preset = iD.presetPreset('test', {tags: {highway: 'residential'}});
|
||||
var entity = iD.osmWay({tags: {highway: 'residential'}});
|
||||
expect(preset.matchScore(entity)).to.equal(1);
|
||||
|
||||
preset = iD.presetPreset('test', {tags: {highway: 'service', service: 'alley'}});
|
||||
entity = iD.Way({tags: {highway: 'service', service: 'alley'}});
|
||||
entity = iD.osmWay({tags: {highway: 'service', service: 'alley'}});
|
||||
expect(preset.matchScore(entity)).to.equal(2);
|
||||
});
|
||||
|
||||
it('counts * as a match for any value with score 0.5', function() {
|
||||
var preset = iD.presetPreset('test', {tags: {building: '*'}}),
|
||||
entity = iD.Way({tags: {building: 'yep'}});
|
||||
var preset = iD.presetPreset('test', {tags: {building: '*'}});
|
||||
var entity = iD.osmWay({tags: {building: 'yep'}});
|
||||
expect(preset.matchScore(entity)).to.equal(0.5);
|
||||
});
|
||||
});
|
||||
@@ -70,14 +69,25 @@ describe('iD.presetPreset', function() {
|
||||
});
|
||||
|
||||
describe('#setTags', function() {
|
||||
var savedAreaKeys;
|
||||
|
||||
before(function () {
|
||||
savedAreaKeys = iD.areaKeys;
|
||||
iD.setAreaKeys({ building: {}, natural: {} });
|
||||
});
|
||||
|
||||
after(function () {
|
||||
iD.setAreaKeys(savedAreaKeys);
|
||||
});
|
||||
|
||||
it('adds match tags', function() {
|
||||
var preset = iD.presetPreset('test', {tags: {highway: 'residential'}});
|
||||
expect(preset.setTags({}, 'line')).to.eql({highway: 'residential'});
|
||||
});
|
||||
|
||||
it('adds wildcard tags with value \'yes\'', function() {
|
||||
var preset = iD.presetPreset('test', {tags: {building: '*'}});
|
||||
expect(preset.setTags({}, 'area')).to.eql({building: 'yes'});
|
||||
var preset = iD.presetPreset('test', {tags: {natural: '*'}});
|
||||
expect(preset.setTags({}, 'area')).to.eql({natural: 'yes'});
|
||||
});
|
||||
|
||||
it('prefers to add tags of addTags property', function() {
|
||||
@@ -86,14 +96,14 @@ describe('iD.presetPreset', function() {
|
||||
});
|
||||
|
||||
it('adds default tags of fields with matching geometry', function() {
|
||||
var field = iD.presetField('field', {key: 'building', geometry: 'area', default: 'yes'}),
|
||||
preset = iD.presetPreset('test', {fields: ['field']}, {field: field});
|
||||
var field = iD.presetField('field', {key: 'building', geometry: 'area', default: 'yes'});
|
||||
var preset = iD.presetPreset('test', {fields: ['field']}, {field: field});
|
||||
expect(preset.setTags({}, 'area')).to.eql({area: 'yes', building: 'yes'});
|
||||
});
|
||||
|
||||
it('adds no default tags of fields with non-matching geometry', function() {
|
||||
var field = iD.presetField('field', {key: 'building', geometry: 'area', default: 'yes'}),
|
||||
preset = iD.presetPreset('test', {fields: ['field']}, {field: field});
|
||||
var field = iD.presetField('field', {key: 'building', geometry: 'area', default: 'yes'});
|
||||
var preset = iD.presetPreset('test', {fields: ['field']}, {field: field});
|
||||
expect(preset.setTags({}, 'point')).to.eql({});
|
||||
});
|
||||
|
||||
@@ -111,9 +121,10 @@ describe('iD.presetPreset', function() {
|
||||
|
||||
describe('for a preset with a tag in areaKeys', function() {
|
||||
it('doesn\'t add area=yes automatically', function() {
|
||||
var preset = iD.presetPreset('test', {geometry: ['area'], tags: {name: 'testname', natural: 'water'}});
|
||||
expect(preset.setTags({}, 'area')).to.eql({name: 'testname', natural: 'water'});
|
||||
var preset = iD.presetPreset('test', {geometry: ['area'], tags: {name: 'testname', building: 'yes'}});
|
||||
expect(preset.setTags({}, 'area')).to.eql({name: 'testname', building: 'yes'});
|
||||
});
|
||||
|
||||
it('does add area=yes if asked to', function() {
|
||||
var preset = iD.presetPreset('test', {geometry: ['area'], tags: {name: 'testname', area: 'yes'}});
|
||||
expect(preset.setTags({}, 'area')).to.eql({name: 'testname', area: 'yes'});
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
describe('maprules', function() {
|
||||
var _ruleChecks, validationRules;
|
||||
var _ruleChecks, savedAreaKeys, validationRules;
|
||||
|
||||
before(function() {
|
||||
savedAreaKeys = iD.areaKeys;
|
||||
iD.setAreaKeys({ building: {}, amenity: {} });
|
||||
|
||||
iD.services.maprules = iD.serviceMapRules;
|
||||
var areaKeys = iD.Context().presets().areaKeys();
|
||||
iD.serviceMapRules.init(areaKeys);
|
||||
iD.serviceMapRules.init();
|
||||
_ruleChecks = iD.serviceMapRules.ruleChecks();
|
||||
});
|
||||
|
||||
after(function() {
|
||||
iD.setAreaKeys(savedAreaKeys);
|
||||
delete iD.services.maprules;
|
||||
});
|
||||
|
||||
@@ -23,7 +26,7 @@ describe('maprules', function() {
|
||||
var filteredChecks = iD.serviceMapRules.filterRuleChecks(selector);
|
||||
var equalsCheck = filteredChecks[0];
|
||||
var absenceCheck = filteredChecks[1];
|
||||
var entityTags = {amenity: 'marketplace'};
|
||||
var entityTags = { amenity: 'marketplace' };
|
||||
|
||||
expect(filteredChecks.length).eql(2);
|
||||
expect(equalsCheck(entityTags)).to.be.true;
|
||||
@@ -146,7 +149,7 @@ describe('maprules', function() {
|
||||
});
|
||||
|
||||
describe('#addRule', function() {
|
||||
it ('builds a rule from provided selector and adds it to _validationRules', function () {
|
||||
it('builds a rule from provided selector and adds it to _validationRules', function () {
|
||||
var selector = {
|
||||
geometry:'node',
|
||||
equals: {amenity:'marketplace'},
|
||||
@@ -159,7 +162,7 @@ describe('maprules', function() {
|
||||
});
|
||||
});
|
||||
describe('#clearRules', function() {
|
||||
it ('clears _validationRules array', function() {
|
||||
it('clears _validationRules array', function() {
|
||||
expect(iD.serviceMapRules.validationRules().length).to.eql(1);
|
||||
iD.serviceMapRules.clearRules();
|
||||
expect(iD.serviceMapRules.validationRules()).to.be.empty;
|
||||
@@ -184,19 +187,19 @@ describe('maprules', function() {
|
||||
describe('_ruleChecks', function () {
|
||||
describe('#equals', function() {
|
||||
it('is true when two tag maps intersect', function() {
|
||||
var a = { amenity: 'school'};
|
||||
var a = { amenity: 'school' };
|
||||
var b = { amenity: 'school' };
|
||||
expect(_ruleChecks.equals(a)(b)).to.be.true;
|
||||
});
|
||||
it('is false when two tag maps intersect', function() {
|
||||
var a = { man_made: 'water_tap'};
|
||||
var b = { amenity: 'school'};
|
||||
var a = { man_made: 'water_tap' };
|
||||
var b = { amenity: 'school' };
|
||||
expect(_ruleChecks.equals(a)(b)).to.be.false;
|
||||
});
|
||||
});
|
||||
describe('#notEquals', function() {
|
||||
it('is true when two tag maps do not intersect', function() {
|
||||
var a = { man_made: 'water_tap'};
|
||||
var a = { man_made: 'water_tap' };
|
||||
var b = { amenity: 'school' };
|
||||
expect(_ruleChecks.notEquals(a)(b)).to.be.true;
|
||||
});
|
||||
@@ -427,15 +430,15 @@ describe('maprules', function() {
|
||||
}
|
||||
];
|
||||
entities = [
|
||||
iD.Entity({ type: 'node', tags: { amenity: 'marketplace' }}),
|
||||
iD.Way({ tags: { building: 'house', amenity: 'clinic' }, nodes: [ 'a', 'b', 'c', 'a' ]}),
|
||||
iD.Entity({ type: 'node', tags: { man_made: 'tower', 'tower:type': 'communication', height: 5 }}),
|
||||
iD.Entity({ type: 'node', tags: { man_made: 'tower', height: 6 }}),
|
||||
iD.Entity({ type: 'node', tags: { man_made: 'tower', height: 9 }}),
|
||||
iD.Entity({ type: 'node', tags: { man_made: 'tower', height: 5 }}),
|
||||
iD.Entity({ type: 'node', tags: { man_made: 'tower', height: 10 }}),
|
||||
iD.Way({ tags: { amenity: 'clinic', emergency: 'definitely' }, nodes: [ 'd', 'e', 'f', 'd' ]}),
|
||||
iD.Way({ tags: { highway: 'residential', structure: 'bridge' }}),
|
||||
iD.osmEntity({ type: 'node', tags: { amenity: 'marketplace' }}),
|
||||
iD.osmWay({ tags: { building: 'house', amenity: 'clinic' }, nodes: [ 'a', 'b', 'c', 'a' ]}),
|
||||
iD.osmEntity({ type: 'node', tags: { man_made: 'tower', 'tower:type': 'communication', height: 5 }}),
|
||||
iD.osmEntity({ type: 'node', tags: { man_made: 'tower', height: 6 }}),
|
||||
iD.osmEntity({ type: 'node', tags: { man_made: 'tower', height: 9 }}),
|
||||
iD.osmEntity({ type: 'node', tags: { man_made: 'tower', height: 5 }}),
|
||||
iD.osmEntity({ type: 'node', tags: { man_made: 'tower', height: 10 }}),
|
||||
iD.osmWay({ tags: { amenity: 'clinic', emergency: 'definitely' }, nodes: [ 'd', 'e', 'f', 'd' ]}),
|
||||
iD.osmWay({ tags: { highway: 'residential', structure: 'bridge' }}),
|
||||
];
|
||||
|
||||
iD.serviceMapRules.clearRules();
|
||||
@@ -454,7 +457,7 @@ describe('maprules', function() {
|
||||
positiveRegex: { structure: ['embarkment', 'bridge'] },
|
||||
error: '\'suburban road\' structure tag cannot be \'bridge\' or \'tunnel\''
|
||||
};
|
||||
var entity = iD.Way({ tags: { highway: 'residential', structure: 'tunnel' }});
|
||||
var entity = iD.osmWay({ tags: { highway: 'residential', structure: 'tunnel' }});
|
||||
iD.serviceMapRules.clearRules();
|
||||
iD.serviceMapRules.addRule(selector);
|
||||
var rule = iD.serviceMapRules.validationRules()[0];
|
||||
@@ -522,15 +525,15 @@ describe('maprules', function() {
|
||||
}
|
||||
];
|
||||
entities = [
|
||||
iD.Entity({ type: 'node', tags: { amenity: 'marketplace' }}),
|
||||
iD.Way({ tags: { building: 'house', amenity: 'clinic' }, nodes: [ 'a', 'b', 'c', 'a' ]}),
|
||||
iD.Entity({ type: 'node', tags: { man_made: 'tower', 'tower:type': 'communication', height: 5 }}),
|
||||
iD.Entity({ type: 'node', tags: { man_made: 'tower', height: 6 }}),
|
||||
iD.Entity({ type: 'node', tags: { man_made: 'tower', height: 9 }}),
|
||||
iD.Entity({ type: 'node', tags: { man_made: 'tower', height: 5 }}),
|
||||
iD.Entity({ type: 'node', tags: { man_made: 'tower', height: 10 }}),
|
||||
iD.Way({ tags: { amenity: 'clinic', emergency: 'definitely' }, nodes: [ 'd', 'e', 'f', 'd' ]}),
|
||||
iD.Way({ tags: { highway: 'residential', structure: 'bridge' }}),
|
||||
iD.osmEntity({ type: 'node', tags: { amenity: 'marketplace' }}),
|
||||
iD.osmWay({ tags: { building: 'house', amenity: 'clinic' }, nodes: [ 'a', 'b', 'c', 'a' ]}),
|
||||
iD.osmEntity({ type: 'node', tags: { man_made: 'tower', 'tower:type': 'communication', height: 5 }}),
|
||||
iD.osmEntity({ type: 'node', tags: { man_made: 'tower', height: 6 }}),
|
||||
iD.osmEntity({ type: 'node', tags: { man_made: 'tower', height: 9 }}),
|
||||
iD.osmEntity({ type: 'node', tags: { man_made: 'tower', height: 5 }}),
|
||||
iD.osmEntity({ type: 'node', tags: { man_made: 'tower', height: 10 }}),
|
||||
iD.osmWay({ tags: { amenity: 'clinic', emergency: 'definitely' }, nodes: [ 'd', 'e', 'f', 'd' ]}),
|
||||
iD.osmWay({ tags: { highway: 'residential', structure: 'bridge' }}),
|
||||
];
|
||||
|
||||
var wayNodes = [
|
||||
@@ -541,7 +544,7 @@ describe('maprules', function() {
|
||||
iD.osmNode({ id: 'e' }),
|
||||
iD.osmNode({ id: 'f' }),
|
||||
];
|
||||
_graph = iD.Graph(entities.concat(wayNodes));
|
||||
_graph = iD.coreGraph(entities.concat(wayNodes));
|
||||
iD.serviceMapRules.clearRules();
|
||||
selectors.forEach(function(selector) { iD.serviceMapRules.addRule(selector); });
|
||||
validationRules = iD.serviceMapRules.validationRules();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
describe('iD.svgAreas', function () {
|
||||
var context, surface;
|
||||
var context, surface, savedAreaKeys;
|
||||
var all = function() { return true; };
|
||||
var none = function() { return false; };
|
||||
var projection = d3.geoProjection(function(x, y) { return [x, -y]; })
|
||||
@@ -15,13 +15,15 @@ describe('iD.svgAreas', function () {
|
||||
.call(context.map().centerZoom([0, 0], 17));
|
||||
surface = context.surface();
|
||||
|
||||
iD.setAreaKeys({
|
||||
building: {},
|
||||
landuse: {},
|
||||
natural: {}
|
||||
});
|
||||
savedAreaKeys = iD.areaKeys;
|
||||
iD.setAreaKeys({ building: {}, landuse: {}, natural: {} });
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
iD.setAreaKeys(savedAreaKeys);
|
||||
});
|
||||
|
||||
|
||||
it('adds way and area classes', function () {
|
||||
var graph = iD.coreGraph([
|
||||
iD.osmNode({id: 'a', loc: [0, 0]}),
|
||||
|
||||
Reference in New Issue
Block a user