mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-14 21:28:11 +02:00
Merge branch 'master' of github.com:systemed/iD
This commit is contained in:
+1
-1
@@ -124,7 +124,7 @@ iD.Connection = function() {
|
||||
}
|
||||
}
|
||||
|
||||
return iD.Graph(entities);
|
||||
return entities;
|
||||
}
|
||||
|
||||
function authenticated() {
|
||||
|
||||
+156
-69
@@ -1,19 +1,30 @@
|
||||
iD.Graph = function(entities, mutable) {
|
||||
if (!(this instanceof iD.Graph)) return new iD.Graph(entities, mutable);
|
||||
iD.Graph = function(other, mutable) {
|
||||
if (!(this instanceof iD.Graph)) return new iD.Graph(other, mutable);
|
||||
|
||||
if (other instanceof iD.Graph) {
|
||||
var base = other.base();
|
||||
this.entities = _.assign(Object.create(base.entities), other.entities);
|
||||
this._parentWays = _.assign(Object.create(base.parentWays), other._parentWays);
|
||||
this._parentRels = _.assign(Object.create(base.parentRels), other._parentRels);
|
||||
this.inherited = true;
|
||||
|
||||
if (_.isArray(entities)) {
|
||||
this.entities = {};
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
this.entities[entities[i].id] = entities[i];
|
||||
}
|
||||
} else {
|
||||
this.entities = entities || {};
|
||||
if (_.isArray(other)) {
|
||||
var entities = {};
|
||||
for (var i = 0; i < other.length; i++) {
|
||||
entities[other[i].id] = other[i];
|
||||
}
|
||||
other = entities;
|
||||
}
|
||||
this.entities = Object.create({});
|
||||
this._parentWays = Object.create({});
|
||||
this._parentRels = Object.create({});
|
||||
this.rebase(other || {});
|
||||
}
|
||||
|
||||
this.transients = {};
|
||||
this._parentWays = {};
|
||||
this._parentRels = {};
|
||||
this._childNodes = {};
|
||||
this.getEntity = _.bind(this.entity, this);
|
||||
|
||||
if (!mutable) {
|
||||
this.freeze();
|
||||
@@ -38,51 +49,21 @@ iD.Graph.prototype = {
|
||||
},
|
||||
|
||||
parentWays: function(entity) {
|
||||
var ent, id, parents;
|
||||
|
||||
if (!this._parentWays.calculated) {
|
||||
for (var i in this.entities) {
|
||||
ent = this.entities[i];
|
||||
if (ent && ent.type === 'way') {
|
||||
for (var j = 0; j < ent.nodes.length; j++) {
|
||||
id = ent.nodes[j];
|
||||
parents = this._parentWays[id] = this._parentWays[id] || [];
|
||||
if (parents.indexOf(ent) < 0) {
|
||||
parents.push(ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this._parentWays.calculated = true;
|
||||
}
|
||||
|
||||
return this._parentWays[entity.id] || [];
|
||||
return _.map(this._parentWays[entity.id], this.getEntity);
|
||||
},
|
||||
|
||||
isPoi: function(entity) {
|
||||
return this.parentWays(entity).length === 0;
|
||||
var parentWays = this._parentWays[entity.id];
|
||||
return !parentWays || parentWays.length === 0;
|
||||
},
|
||||
|
||||
isShared: function(entity) {
|
||||
var parentWays = this._parentWays[entity.id];
|
||||
return parentWays && parentWays.length > 1;
|
||||
},
|
||||
|
||||
parentRelations: function(entity) {
|
||||
var ent, id, parents;
|
||||
|
||||
if (!this._parentRels.calculated) {
|
||||
for (var i in this.entities) {
|
||||
ent = this.entities[i];
|
||||
if (ent && ent.type === 'relation') {
|
||||
for (var j = 0; j < ent.members.length; j++) {
|
||||
id = ent.members[j].id;
|
||||
parents = this._parentRels[id] = this._parentRels[id] || [];
|
||||
if (parents.indexOf(ent) < 0) {
|
||||
parents.push(ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this._parentRels.calculated = true;
|
||||
}
|
||||
|
||||
return this._parentRels[entity.id] || [];
|
||||
return _.map(this._parentRels[entity.id], this.getEntity);
|
||||
},
|
||||
|
||||
childNodes: function(entity) {
|
||||
@@ -97,30 +78,132 @@ iD.Graph.prototype = {
|
||||
return (this._childNodes[entity.id] = nodes);
|
||||
},
|
||||
|
||||
merge: function(graph) {
|
||||
return this.update(function () {
|
||||
_.defaults(this.entities, graph.entities);
|
||||
});
|
||||
base: function() {
|
||||
return {
|
||||
'entities': iD.util.getPrototypeOf(this.entities),
|
||||
'parentWays': iD.util.getPrototypeOf(this._parentWays),
|
||||
'parentRels': iD.util.getPrototypeOf(this._parentRels)
|
||||
};
|
||||
},
|
||||
|
||||
// Unlike other graph methods, rebase mutates in place. This is because it
|
||||
// is used only during the history operation that merges newly downloaded
|
||||
// data into each state. To external consumers, it should appear as if the
|
||||
// graph always contained the newly downloaded data.
|
||||
rebase: function(entities) {
|
||||
var base = this.base(),
|
||||
i, k, child, id, keys;
|
||||
// Merging of data only needed if graph is the base graph
|
||||
if (!this.inherited) {
|
||||
for (i in entities) {
|
||||
if (!base.entities[i]) {
|
||||
base.entities[i] = entities[i];
|
||||
this._updateCalculated(undefined, entities[i],
|
||||
base.parentWays, base.parentRels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keys = Object.keys(this._parentWays);
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
child = keys[i];
|
||||
if (base.parentWays[child]) {
|
||||
for (k = 0; k < base.parentWays[child].length; k++) {
|
||||
id = base.parentWays[child][k];
|
||||
if (this.entity(id) && !_.contains(this._parentWays[child], id)) {
|
||||
this._parentWays[child].push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keys = Object.keys(this._parentRels);
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
child = keys[i];
|
||||
if (base.parentRels[child]) {
|
||||
for (k = 0; k < base.parentRels[child].length; k++) {
|
||||
id = base.parentRels[child][k];
|
||||
if (this.entity(id) && !_.contains(this._parentRels[child], id)) {
|
||||
this._parentRels[child].push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Updates calculated properties (parentWays, parentRels) for the specified change
|
||||
_updateCalculated: function(oldentity, entity, parentWays, parentRels) {
|
||||
|
||||
parentWays = parentWays || this._parentWays;
|
||||
parentRels = parentRels || this._parentRels;
|
||||
|
||||
var type = entity && entity.type || oldentity && oldentity.type,
|
||||
removed, added, ways, rels, i;
|
||||
|
||||
|
||||
if (type === 'way') {
|
||||
|
||||
// Update parentWays
|
||||
if (oldentity && entity) {
|
||||
removed = _.difference(oldentity.nodes, entity.nodes);
|
||||
added = _.difference(entity.nodes, oldentity.nodes);
|
||||
} else if (oldentity) {
|
||||
removed = oldentity.nodes;
|
||||
added = [];
|
||||
} else if (entity) {
|
||||
removed = [];
|
||||
added = entity.nodes;
|
||||
}
|
||||
for (i = 0; i < removed.length; i++) {
|
||||
parentWays[removed[i]] = _.without(parentWays[removed[i]], oldentity.id);
|
||||
}
|
||||
for (i = 0; i < added.length; i++) {
|
||||
ways = _.without(parentWays[added[i]], entity.id);
|
||||
ways.push(entity.id);
|
||||
parentWays[added[i]] = ways;
|
||||
}
|
||||
} else if (type === 'node') {
|
||||
|
||||
} else if (type === 'relation') {
|
||||
|
||||
// Update parentRels
|
||||
if (oldentity && entity) {
|
||||
removed = _.difference(oldentity.members, entity.members);
|
||||
added = _.difference(entity.members, oldentity);
|
||||
} else if (oldentity) {
|
||||
removed = oldentity.members;
|
||||
added = [];
|
||||
} else if (entity) {
|
||||
removed = [];
|
||||
added = entity.members;
|
||||
}
|
||||
for (i = 0; i < removed.length; i++) {
|
||||
parentRels[removed[i].id] = _.without(parentRels[removed[i].id], oldentity.id);
|
||||
}
|
||||
for (i = 0; i < added.length; i++) {
|
||||
rels = _.without(parentRels[added[i].id], entity.id);
|
||||
rels.push(entity.id);
|
||||
parentRels[added[i].id] = rels;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
replace: function(entity) {
|
||||
return this.update(function () {
|
||||
this._updateCalculated(this.entities[entity.id], entity);
|
||||
this.entities[entity.id] = entity;
|
||||
});
|
||||
},
|
||||
|
||||
remove: function(entity) {
|
||||
return this.update(function () {
|
||||
if (entity.created()) {
|
||||
delete this.entities[entity.id];
|
||||
} else {
|
||||
this.entities[entity.id] = undefined;
|
||||
}
|
||||
this._updateCalculated(entity, undefined);
|
||||
this.entities[entity.id] = undefined;
|
||||
});
|
||||
},
|
||||
|
||||
update: function() {
|
||||
var graph = this.frozen ? iD.Graph(_.clone(this.entities), true) : this;
|
||||
var graph = this.frozen ? iD.Graph(this, true) : this;
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
arguments[i].call(graph, graph);
|
||||
@@ -133,7 +216,6 @@ iD.Graph.prototype = {
|
||||
this.frozen = true;
|
||||
|
||||
if (iD.debug) {
|
||||
Object.freeze(this);
|
||||
Object.freeze(this.entities);
|
||||
}
|
||||
|
||||
@@ -153,9 +235,12 @@ iD.Graph.prototype = {
|
||||
},
|
||||
|
||||
difference: function (graph) {
|
||||
var result = [], entity, oldentity, id;
|
||||
var result = [],
|
||||
keys = Object.keys(this.entities),
|
||||
entity, oldentity, id, i;
|
||||
|
||||
for (id in this.entities) {
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
id = keys[i];
|
||||
entity = this.entities[id];
|
||||
oldentity = graph.entities[id];
|
||||
if (entity !== oldentity) {
|
||||
@@ -177,7 +262,9 @@ iD.Graph.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
for (id in graph.entities) {
|
||||
keys = Object.keys(graph.entities);
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
id = keys[i];
|
||||
entity = graph.entities[id];
|
||||
if (entity && !this.entities.hasOwnProperty(id)) {
|
||||
result.push(id);
|
||||
@@ -189,25 +276,25 @@ iD.Graph.prototype = {
|
||||
},
|
||||
|
||||
modified: function() {
|
||||
var result = [];
|
||||
var result = [], base = this.base().entities;
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (entity && entity.modified()) result.push(id);
|
||||
if (entity && base[id]) result.push(id);
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
created: function() {
|
||||
var result = [];
|
||||
var result = [], base = this.base().entities;
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (entity && entity.created()) result.push(id);
|
||||
if (entity && !base[id]) result.push(id);
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
deleted: function() {
|
||||
var result = [];
|
||||
var result = [], base = this.base().entities;
|
||||
_.each(this.entities, function(entity, id) {
|
||||
if (!entity) result.push(id);
|
||||
if (!entity && base[id]) result.push(id);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ iD.History = function() {
|
||||
return stack[index].graph;
|
||||
},
|
||||
|
||||
merge: function (graph) {
|
||||
merge: function (entities) {
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
stack[i].graph = stack[i].graph.merge(graph);
|
||||
stack[i].graph.rebase(entities);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ iD.Map = function() {
|
||||
for (var i = 0; i < parents.length; i++) {
|
||||
var parent = parents[i];
|
||||
if (only[parent.id] === undefined) {
|
||||
only[parent.id] = graph.entity(parent.id);
|
||||
only[parent.id] = parent;
|
||||
addParents(graph.parentRelations(parent));
|
||||
}
|
||||
}
|
||||
@@ -123,7 +123,7 @@ iD.Map = function() {
|
||||
|
||||
function connectionLoad(err, result) {
|
||||
history.merge(result);
|
||||
redraw(Object.keys(result.entities));
|
||||
redraw(Object.keys(result));
|
||||
}
|
||||
|
||||
function zoomPan() {
|
||||
@@ -165,7 +165,8 @@ iD.Map = function() {
|
||||
}
|
||||
|
||||
function resetTransform() {
|
||||
if (!surface.style(transformProp)) return false;
|
||||
var prop = surface.style(transformProp);
|
||||
if (!prop || prop === 'none') return false;
|
||||
surface.style(transformProp, '');
|
||||
tilegroup.style(transformProp, '');
|
||||
return true;
|
||||
|
||||
@@ -36,7 +36,7 @@ iD.svg.Vertices = function(projection) {
|
||||
groups.attr('transform', iD.svg.PointTransform(projection))
|
||||
.call(iD.svg.TagClasses())
|
||||
.call(iD.svg.MemberClasses(graph))
|
||||
.classed('shared', function(entity) { return graph.parentWays(entity).length > 1; });
|
||||
.classed('shared', function(entity) { return graph.isShared(entity); });
|
||||
|
||||
// Selecting the following implicitly
|
||||
// sets the data (vertix entity) on the elements
|
||||
|
||||
@@ -16,7 +16,7 @@ iD.ui.contributors = function(map) {
|
||||
var l = selection
|
||||
.select('.contributor-list')
|
||||
.selectAll('a.user-link')
|
||||
.data(subset);
|
||||
.data(subset, function(d) { return d; });
|
||||
|
||||
|
||||
l.enter().append('a')
|
||||
@@ -43,6 +43,10 @@ iD.ui.contributors = function(map) {
|
||||
ext[1][0], ext[1][1]];
|
||||
})
|
||||
.text(' and ' + (u.length - limit) + ' others');
|
||||
} else {
|
||||
selection
|
||||
.select('.contributor-count')
|
||||
.html('');
|
||||
}
|
||||
|
||||
if (!u.length) {
|
||||
|
||||
@@ -74,3 +74,5 @@ iD.util.getStyle = function(selector) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
iD.util.getPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
|
||||
|
||||
@@ -26,24 +26,24 @@ describe('iD.Connection', function () {
|
||||
c.loadFromURL('data/node.xml', done);
|
||||
});
|
||||
|
||||
it('returns a graph', function (done) {
|
||||
it('returns an object', function (done) {
|
||||
c.loadFromURL('data/node.xml', function (err, graph) {
|
||||
expect(err).to.not.be.ok;
|
||||
expect(graph).to.be.instanceOf(iD.Graph);
|
||||
expect(typeof graph).to.eql('object');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('parses a node', function (done) {
|
||||
c.loadFromURL('data/node.xml', function (err, graph) {
|
||||
expect(graph.entity('n356552551')).to.be.instanceOf(iD.Entity);
|
||||
expect(graph.n356552551).to.be.instanceOf(iD.Entity);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('parses a way', function (done) {
|
||||
c.loadFromURL('data/way.xml', function (err, graph) {
|
||||
expect(graph.entity('w19698713')).to.be.instanceOf(iD.Entity);
|
||||
expect(graph.w19698713).to.be.instanceOf(iD.Entity);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
+221
-25
@@ -1,25 +1,164 @@
|
||||
describe('iD.Graph', function() {
|
||||
it("can be constructed with an entities Object", function () {
|
||||
var entity = iD.Entity(),
|
||||
graph = iD.Graph({'n-1': entity});
|
||||
expect(graph.entity('n-1')).to.equal(entity);
|
||||
});
|
||||
|
||||
it("can be constructed with an entities Array", function () {
|
||||
var entity = iD.Entity(),
|
||||
graph = iD.Graph([entity]);
|
||||
expect(graph.entity(entity.id)).to.equal(entity);
|
||||
});
|
||||
|
||||
if (iD.debug) {
|
||||
it("is frozen", function () {
|
||||
expect(Object.isFrozen(iD.Graph())).to.be.true;
|
||||
describe("constructor", function () {
|
||||
it("accepts an entities Object", function () {
|
||||
var entity = iD.Entity(),
|
||||
graph = iD.Graph({'n-1': entity});
|
||||
expect(graph.entity('n-1')).to.equal(entity);
|
||||
});
|
||||
|
||||
it("freezes entities", function () {
|
||||
expect(Object.isFrozen(iD.Graph().entities)).to.be.true;
|
||||
it("accepts an entities Array", function () {
|
||||
var entity = iD.Entity(),
|
||||
graph = iD.Graph([entity]);
|
||||
expect(graph.entity(entity.id)).to.equal(entity);
|
||||
});
|
||||
}
|
||||
|
||||
it("accepts a Graph", function () {
|
||||
var entity = iD.Entity(),
|
||||
graph = iD.Graph(iD.Graph([entity]));
|
||||
expect(graph.entity(entity.id)).to.equal(entity);
|
||||
});
|
||||
|
||||
it("copies other's entities", function () {
|
||||
var entity = iD.Entity(),
|
||||
base = iD.Graph([entity]),
|
||||
graph = iD.Graph(base);
|
||||
expect(graph.entities).not.to.equal(base.entities);
|
||||
});
|
||||
|
||||
it("rebases on other's base", function () {
|
||||
var base = iD.Graph(),
|
||||
graph = iD.Graph(base);
|
||||
expect(graph.base().entities).to.equal(base.base().entities);
|
||||
});
|
||||
|
||||
it("freezes by default", function () {
|
||||
expect(iD.Graph().frozen).to.be.true;
|
||||
});
|
||||
|
||||
it("remains mutable if passed true as second argument", function () {
|
||||
expect(iD.Graph([], true).frozen).not.to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe("#freeze", function () {
|
||||
it("sets the frozen flag", function () {
|
||||
expect(iD.Graph([], true).freeze().frozen).to.be.true;
|
||||
});
|
||||
|
||||
if (iD.debug) {
|
||||
it("freezes entities", function () {
|
||||
expect(Object.isFrozen(iD.Graph().entities)).to.be.true;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe("#rebase", function () {
|
||||
it("preserves existing entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
graph = iD.Graph([node]);
|
||||
graph.rebase({});
|
||||
expect(graph.entity('n')).to.equal(node);
|
||||
});
|
||||
|
||||
it("includes new entities", function () {
|
||||
var node = iD.Node({id: 'n'}),
|
||||
graph = iD.Graph();
|
||||
graph.rebase({'n': node});
|
||||
expect(graph.entity('n')).to.equal(node);
|
||||
});
|
||||
|
||||
it("gives precedence to existing entities", function () {
|
||||
var a = iD.Node({id: 'n'}),
|
||||
b = iD.Node({id: 'n'}),
|
||||
graph = iD.Graph([a]);
|
||||
graph.rebase({'n': b});
|
||||
expect(graph.entity('n')).to.equal(a);
|
||||
});
|
||||
|
||||
it("inherits entities from base prototypally", function () {
|
||||
var graph = iD.Graph();
|
||||
graph.rebase({'n': iD.Node()});
|
||||
expect(graph.entities).not.to.have.ownProperty('n');
|
||||
});
|
||||
|
||||
it("updates parentWays", function () {
|
||||
var n = iD.Node({id: 'n'}),
|
||||
w1 = iD.Way({id: 'w1', nodes: ['n']}),
|
||||
w2 = iD.Way({id: 'w2', nodes: ['n']}),
|
||||
graph = iD.Graph([n, w1]);
|
||||
|
||||
graph.rebase({ 'w2': w2 });
|
||||
expect(graph.parentWays(n)).to.eql([w1, w2]);
|
||||
expect(graph._parentWays.hasOwnProperty('n')).to.be.false;
|
||||
});
|
||||
|
||||
it("avoids adding duplicate parentWays", function () {
|
||||
var n = iD.Node({id: 'n'}),
|
||||
w1 = iD.Way({id: 'w1', nodes: ['n']}),
|
||||
graph = iD.Graph([n, w1]);
|
||||
graph.rebase({ 'w1': w1 });
|
||||
expect(graph.parentWays(n)).to.eql([w1]);
|
||||
});
|
||||
|
||||
it("updates parentWays for nodes with modified parentWays", function () {
|
||||
var n = iD.Node({id: 'n'}),
|
||||
w1 = iD.Way({id: 'w1', nodes: ['n']}),
|
||||
w2 = iD.Way({id: 'w2', nodes: ['n']}),
|
||||
w3 = iD.Way({id: 'w3', nodes: ['n']}),
|
||||
graph = iD.Graph([n, w1]),
|
||||
graph2 = graph.replace(w2);
|
||||
graph.rebase({ 'w3': w3 });
|
||||
graph2.rebase({ 'w3': w3 });
|
||||
|
||||
expect(graph2.parentWays(n)).to.eql([w1, w2, w3]);
|
||||
});
|
||||
|
||||
it("avoids re-adding removed parentWays", function() {
|
||||
var n = iD.Node({id: 'n'}),
|
||||
w1 = iD.Way({id: 'w1', nodes: ['n']}),
|
||||
graph = iD.Graph([n, w1]),
|
||||
graph2 = graph.remove(w1);
|
||||
graph.rebase({ 'w1': w1 });
|
||||
graph2.rebase({ 'w1': w1 });
|
||||
expect(graph2.parentWays(n)).to.eql([]);
|
||||
});
|
||||
|
||||
it("updates parentRelations", function () {
|
||||
var n = iD.Node({id: 'n'}),
|
||||
r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}),
|
||||
r2 = iD.Relation({id: 'r2', members: [{id: 'n'}]}),
|
||||
graph = iD.Graph([n, r1]);
|
||||
|
||||
graph.rebase({'r2': r2});
|
||||
|
||||
expect(graph.parentRelations(n)).to.eql([r1, r2]);
|
||||
expect(graph._parentRels.hasOwnProperty('n')).to.be.false;
|
||||
});
|
||||
|
||||
it("avoids re-adding removed parentRels", function() {
|
||||
var n = iD.Node({id: 'n'}),
|
||||
r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}),
|
||||
graph = iD.Graph([n, r1]),
|
||||
graph2 = graph.remove(r1);
|
||||
graph.rebase({ 'w1': r1 });
|
||||
graph2.rebase({ 'w1': r1 });
|
||||
expect(graph2.parentWays(n)).to.eql([]);
|
||||
});
|
||||
|
||||
it("updates parentRels for nodes with modified parentWays", function () {
|
||||
var n = iD.Node({id: 'n'}),
|
||||
r1 = iD.Relation({id: 'r1', members: [{id: 'n'}]}),
|
||||
r2 = iD.Relation({id: 'r2', members: [{id: 'n'}]}),
|
||||
r3 = iD.Relation({id: 'r3', members: [{id: 'n'}]}),
|
||||
graph = iD.Graph([n, r1]),
|
||||
graph2 = graph.replace(r2);
|
||||
|
||||
graph.rebase({'r3': r3});
|
||||
graph2.rebase({'r3': r3});
|
||||
expect(graph2.parentRelations(n)).to.eql([r1, r2, r3]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("#remove", function () {
|
||||
it("returns a new graph", function () {
|
||||
@@ -40,6 +179,20 @@ describe('iD.Graph', function() {
|
||||
graph = iD.Graph([node]);
|
||||
expect(graph.remove(node).entity(node.id)).to.be.undefined;
|
||||
});
|
||||
|
||||
it("removes the entity as a parentWay", function () {
|
||||
var node = iD.Node({id: 'n' }),
|
||||
w1 = iD.Way({id: 'w', nodes: ['n']}),
|
||||
graph = iD.Graph([node, w1]);
|
||||
expect(graph.remove(w1).parentWays(node)).to.eql([]);
|
||||
});
|
||||
|
||||
it("removes the entity as a parentRelation", function () {
|
||||
var node = iD.Node({id: 'n' }),
|
||||
r1 = iD.Relation({id: 'w', members: [{id: 'n' }]}),
|
||||
graph = iD.Graph([node, r1]);
|
||||
expect(graph.remove(r1).parentRelations(node)).to.eql([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#replace", function () {
|
||||
@@ -62,6 +215,49 @@ describe('iD.Graph', function() {
|
||||
graph = iD.Graph([node1]);
|
||||
expect(graph.replace(node2).entity(node2.id)).to.equal(node2);
|
||||
});
|
||||
|
||||
it("adds parentWays", function () {
|
||||
var node = iD.Node({id: 'n' }),
|
||||
w1 = iD.Way({id: 'w', nodes: ['n']}),
|
||||
graph = iD.Graph([node]);
|
||||
expect(graph.replace(w1).parentWays(node)).to.eql([w1]);
|
||||
});
|
||||
|
||||
it("removes parentWays", function () {
|
||||
var node = iD.Node({id: 'n' }),
|
||||
w1 = iD.Way({id: 'w', nodes: ['n']}),
|
||||
graph = iD.Graph([node, w1]);
|
||||
expect(graph.remove(w1).parentWays(node)).to.eql([]);
|
||||
});
|
||||
|
||||
it("doesn't add duplicate parentWays", function () {
|
||||
var node = iD.Node({id: 'n' }),
|
||||
w1 = iD.Way({id: 'w', nodes: ['n']}),
|
||||
graph = iD.Graph([node, w1]);
|
||||
expect(graph.replace(w1).parentWays(node)).to.eql([w1]);
|
||||
});
|
||||
|
||||
it("adds parentRels", function () {
|
||||
var node = iD.Node({id: 'n' }),
|
||||
r1 = iD.Relation({id: 'w', members: [{id: 'n'}]}),
|
||||
graph = iD.Graph([node]);
|
||||
expect(graph.replace(r1).parentRelations(node)).to.eql([r1]);
|
||||
});
|
||||
|
||||
it("removes parentRelations", function () {
|
||||
var node = iD.Node({id: 'n' }),
|
||||
r1 = iD.Relation({id: 'w', members: [{id: 'n'}]}),
|
||||
graph = iD.Graph([node, r1]);
|
||||
expect(graph.remove(r1).parentRelations(node)).to.eql([]);
|
||||
});
|
||||
|
||||
it("doesn't add duplicate parentRelations", function () {
|
||||
var node = iD.Node({id: 'n' }),
|
||||
r1 = iD.Relation({id: 'w', members: [{id: 'n'}]}),
|
||||
graph = iD.Graph([node, r1]);
|
||||
expect(graph.replace(r1).parentRelations(node)).to.eql([r1]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("#update", function () {
|
||||
@@ -159,18 +355,18 @@ describe('iD.Graph', function() {
|
||||
|
||||
describe("#modified", function () {
|
||||
it("returns an Array of ids of modified entities", function () {
|
||||
var node1 = iD.Node({id: 'n1', _updated: true}),
|
||||
node2 = iD.Node({id: 'n2'}),
|
||||
graph = iD.Graph([node1, node2]);
|
||||
expect(graph.modified()).to.eql([node1.id]);
|
||||
var node = iD.Node({id: 'n1'}),
|
||||
node_ = iD.Node({id: 'n1'}),
|
||||
graph = iD.Graph([node]).replace(node_);
|
||||
expect(graph.modified()).to.eql([node.id]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#created", function () {
|
||||
it("returns an Array of ids of created entities", function () {
|
||||
var node1 = iD.Node({id: 'n-1', _updated: true}),
|
||||
var node1 = iD.Node({id: 'n-1'}),
|
||||
node2 = iD.Node({id: 'n2'}),
|
||||
graph = iD.Graph([node1, node2]);
|
||||
graph = iD.Graph([node2]).replace(node1);
|
||||
expect(graph.created()).to.eql([node1.id]);
|
||||
});
|
||||
});
|
||||
@@ -185,7 +381,7 @@ describe('iD.Graph', function() {
|
||||
|
||||
it("doesn't include created entities that were subsequently deleted", function () {
|
||||
var node = iD.Node(),
|
||||
graph = iD.Graph([node]).remove(node);
|
||||
graph = iD.Graph().replace(node).remove(node);
|
||||
expect(graph.deleted()).to.eql([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -153,17 +153,15 @@ describe("iD.History", function () {
|
||||
|
||||
it("includes modified entities", function () {
|
||||
var node1 = iD.Node({id: "n1"}),
|
||||
node2 = node1.update({}),
|
||||
graph = iD.Graph([node1]);
|
||||
history.merge(graph);
|
||||
node2 = node1.update({});
|
||||
history.merge({ n1: node1});
|
||||
history.perform(function (graph) { return graph.replace(node2); });
|
||||
expect(history.changes().modified).to.eql([node2]);
|
||||
});
|
||||
|
||||
it("includes deleted entities", function () {
|
||||
var node = iD.Node({id: "n1"}),
|
||||
graph = iD.Graph([node]);
|
||||
history.merge(graph);
|
||||
var node = iD.Node({id: "n1"});
|
||||
history.merge({ n1: node });
|
||||
history.perform(function (graph) { return graph.remove(node); });
|
||||
expect(history.changes().deleted).to.eql([node]);
|
||||
});
|
||||
@@ -189,7 +187,7 @@ describe("iD.History", function () {
|
||||
it("is the sum of all types of changes", function() {
|
||||
var node1 = iD.Node({id: "n1"}),
|
||||
node2 = iD.Node();
|
||||
history.merge(iD.Graph([node1]));
|
||||
history.merge({ n1: node1 });
|
||||
history.perform(function (graph) { return graph.remove(node1); });
|
||||
expect(history.numChanges()).to.eql(1);
|
||||
history.perform(function (graph) { return graph.replace(node2); });
|
||||
|
||||
Reference in New Issue
Block a user