mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-17 22:24:49 +02:00
improvements to iD.actions.MergeRemoteChanges
* if remote entity is deleted, log to conflicts() array * if remote tag was deleted, delete from tags (not set undefined) * update tests..
This commit is contained in:
+1
-1
@@ -324,7 +324,6 @@ en:
|
||||
next: 'Next >'
|
||||
keep_local: Keep mine
|
||||
keep_remote: Use theirs
|
||||
deleted: 'This object has been deleted.'
|
||||
restore: Restore
|
||||
delete: Leave Deleted
|
||||
download_changes: Download your changes.
|
||||
@@ -335,6 +334,7 @@ en:
|
||||
your changes or the other user's changes.
|
||||
merge_remote_changes:
|
||||
conflict:
|
||||
deleted: 'This object has been deleted.'
|
||||
location: 'This object was moved by both you and {user}.'
|
||||
nodelist: 'Nodes were changed by both you and {user}.'
|
||||
memberlist: 'Relation members were changed by both you and {user}.'
|
||||
|
||||
Vendored
+1
-1
@@ -398,7 +398,6 @@
|
||||
"next": "Next >",
|
||||
"keep_local": "Keep mine",
|
||||
"keep_remote": "Use theirs",
|
||||
"deleted": "This object has been deleted.",
|
||||
"restore": "Restore",
|
||||
"delete": "Leave Deleted",
|
||||
"download_changes": "Download your changes.",
|
||||
@@ -408,6 +407,7 @@
|
||||
},
|
||||
"merge_remote_changes": {
|
||||
"conflict": {
|
||||
"deleted": "This object has been deleted.",
|
||||
"location": "This object was moved by both you and {user}.",
|
||||
"nodelist": "Nodes were changed by both you and {user}.",
|
||||
"memberlist": "Relation members were changed by both you and {user}.",
|
||||
|
||||
@@ -155,12 +155,18 @@ iD.actions.MergeRemoteChanges = function(id, localGraph, remoteGraph, formatUser
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var k = keys[i];
|
||||
if (o[k] !== b[k] && a[k] !== b[k]) { // changed remotely..
|
||||
if (o[k] !== a[k]) { // changed locally..
|
||||
|
||||
if (o[k] !== b[k] && a[k] !== b[k]) { // changed remotely..
|
||||
if (o[k] !== a[k]) { // changed locally..
|
||||
conflicts.push(t('merge_remote_changes.conflict.tags',
|
||||
{ tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
|
||||
} else {
|
||||
tags[k] = b[k]; // unchanged locally, accept remote tag..
|
||||
|
||||
} else { // unchanged locally, accept remote change..
|
||||
if (b.hasOwnProperty(k)) {
|
||||
tags[k] = b[k];
|
||||
} else {
|
||||
delete tags[k];
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
@@ -201,6 +207,7 @@ iD.actions.MergeRemoteChanges = function(id, localGraph, remoteGraph, formatUser
|
||||
return graph.replace(target);
|
||||
|
||||
} else {
|
||||
conflicts.push(t('merge_remote_changes.conflict.deleted'));
|
||||
return graph; // do nothing
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ iD.modes.Save = function(context) {
|
||||
conflicts.push({
|
||||
id: id,
|
||||
name: entityName(local),
|
||||
details: [ t('save.conflict.deleted') ],
|
||||
details: [ t('merge_remote_changes.conflict.deleted') ],
|
||||
chosen: 1,
|
||||
choices: [
|
||||
choice(id, t('save.conflict.restore'), forceLocal),
|
||||
|
||||
@@ -65,9 +65,10 @@ describe("iD.actions.MergeRemoteChanges", function () {
|
||||
locale = {
|
||||
_current: 'en',
|
||||
en: {
|
||||
"merge_remote_changes": {
|
||||
'merge_remote_changes': {
|
||||
"annotation": "Merged remote changes from server.",
|
||||
"conflict": {
|
||||
"deleted": "This object has been deleted.",
|
||||
"location": "This object was moved by both you and {user}.",
|
||||
"nodelist": "Nodes were changed by both you and {user}.",
|
||||
"memberlist": "Relation members were changed by both you and {user}.",
|
||||
@@ -90,379 +91,380 @@ describe("iD.actions.MergeRemoteChanges", function () {
|
||||
}
|
||||
|
||||
describe("non-destuctive merging", function () {
|
||||
describe("nodes", function () {
|
||||
it("doesn't merge nodes if location is different", function () {
|
||||
var localTags = {foo: 'foo_local'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote'}, // didn't change tag foo, added tag bar
|
||||
localLoc = [1, 1], // didn't move node
|
||||
remoteLoc = [3, 3], // moved node
|
||||
local = iD.Node({id: 'a', loc: localLoc, version: '1', v: 2, tags: localTags }),
|
||||
remote = iD.Node({id: 'a', loc: remoteLoc, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local]),
|
||||
describe("tags", function() {
|
||||
it("doesn't merge tags if conflict (local change, remote change)", function () {
|
||||
var localTags = {foo: 'foo_local'}, // changed foo
|
||||
remoteTags = {foo: 'foo_remote'}, // changed foo
|
||||
local = base.entity('a').update({tags: localTags}),
|
||||
remote = base.entity('a').update({tags: remoteTags, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('a', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('a')).to.eql(local);
|
||||
expect(result).to.eql(localGraph);
|
||||
});
|
||||
|
||||
it("doesn't merge nodes if changed tags conflict (tag change)", function () {
|
||||
var localTags = {foo: 'foo_local'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo_remote', bar: 'bar_remote'}, // changed tag foo, added tag bar
|
||||
localLoc = [1, 1], // didn't move node
|
||||
remoteLoc = [1, 1], // didn't move node
|
||||
local = iD.Node({id: 'a', loc: localLoc, version: '1', v: 2, tags: localTags }),
|
||||
remote = iD.Node({id: 'a', loc: remoteLoc, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local]),
|
||||
it("doesn't merge tags if conflict (local change, remote delete)", function () {
|
||||
var localTags = {foo: 'foo_local'}, // changed foo
|
||||
remoteTags = {}, // deleted foo
|
||||
local = base.entity('a').update({tags: localTags}),
|
||||
remote = base.entity('a').update({tags: remoteTags, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('a', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('a')).to.eql(local);
|
||||
expect(result).to.eql(localGraph);
|
||||
});
|
||||
|
||||
it("doesn't merge nodes if changed tags conflict (tag delete)", function () {
|
||||
var localTags = {}, // deleted tag foo
|
||||
remoteTags = {foo: 'foo_remote'}, // changed tag foo
|
||||
localLoc = [1, 1], // didn't move node
|
||||
remoteLoc = [1, 1], // didn't move node
|
||||
local = iD.Node({id: 'a', loc: localLoc, version: '1', v: 2, tags: localTags }),
|
||||
remote = iD.Node({id: 'a', loc: remoteLoc, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local]),
|
||||
it("doesn't merge tags if conflict (local delete, remote change)", function () {
|
||||
var localTags = {}, // deleted foo
|
||||
remoteTags = {foo: 'foo_remote'}, // changed foo
|
||||
local = base.entity('a').update({tags: localTags}),
|
||||
remote = base.entity('a').update({tags: remoteTags, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('a', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('a')).to.eql(local);
|
||||
expect(result).to.eql(localGraph);
|
||||
});
|
||||
|
||||
it("merges nodes if location is same and changed tags don't conflict (tag change)", function () {
|
||||
var localTags = {foo: 'foo_local'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote'}, // didn't change tag foo, added tag bar
|
||||
localLoc = [1, 1], // didn't move node
|
||||
remoteLoc = [1, 1], // didn't move node
|
||||
local = iD.Node({id: 'a', loc: localLoc, version: '1', v: 2, tags: localTags }),
|
||||
remote = iD.Node({id: 'a', loc: remoteLoc, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local]),
|
||||
it("doesn't merge tags if conflict (local add, remote add)", function () {
|
||||
var localTags = {foo: 'foo', bar: 'bar_local'}, // same foo, added bar
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote'}, // same foo, added bar
|
||||
local = base.entity('a').update({tags: localTags}),
|
||||
remote = base.entity('a').update({tags: remoteTags, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('a', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('a').version).to.eql('2');
|
||||
expect(graph.entity('a').tags).to.eql({foo: 'foo_local', bar: 'bar_remote'});
|
||||
expect(result).to.eql(localGraph);
|
||||
});
|
||||
|
||||
it("merges nodes if location is same and changed tags don't conflict (tag delete)", function () {
|
||||
var localTags = {}, // deleted tag foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote'}, // didn't change tag foo, added tag bar
|
||||
localLoc = [1, 1], // didn't move node
|
||||
remoteLoc = [1, 1], // didn't move node
|
||||
local = iD.Node({id: 'a', loc: localLoc, version: '1', v: 2, tags: localTags }),
|
||||
remote = iD.Node({id: 'a', loc: remoteLoc, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local]),
|
||||
it("merges tags if no conflict (remote delete)", function () {
|
||||
var localTags = {foo: 'foo', bar: 'bar_local'}, // same foo, added bar
|
||||
remoteTags = {}, // deleted foo
|
||||
mergedTags = {bar: 'bar_local'},
|
||||
local = base.entity('a').update({tags: localTags}),
|
||||
remote = base.entity('a').update({tags: remoteTags, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('a', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
expect(result.entity('a').version).to.eql('2');
|
||||
expect(result.entity('a').tags).to.eql(mergedTags);
|
||||
});
|
||||
|
||||
expect(graph.entity('a').version).to.eql('2');
|
||||
expect(graph.entity('a').tags).to.eql({bar: 'bar_remote'});
|
||||
it("merges tags if no conflict (local delete)", function () {
|
||||
var localTags = {}, // deleted foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote'}, // same foo, added bar
|
||||
mergedTags = {bar: 'bar_remote'},
|
||||
local = base.entity('a').update({tags: localTags}),
|
||||
remote = base.entity('a').update({tags: remoteTags, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
expect(result.entity('a').version).to.eql('2');
|
||||
expect(result.entity('a').tags).to.eql(mergedTags);
|
||||
});
|
||||
});
|
||||
|
||||
describe("ways", function () {
|
||||
it("doesn't merge ways if changed tags conflict", function () {
|
||||
var localNodes = ['p1', 'p2', 'p3', 'p4', 'p1'], // didn't change nodes
|
||||
remoteNodes = ['p1', 'p2', 'p3', 'p4', 'p1'], // didn't change nodes
|
||||
localTags = {foo: 'foo_local', area: 'yes'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo_remote', bar: 'bar_remote', area: 'yes'}, // changed tag foo, added tag bar
|
||||
local = iD.Way({id: 'w1', nodes: localNodes, version: '1', v: 2, tags: localTags}),
|
||||
remote = iD.Way({id: 'w1', nodes: remoteNodes, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local]),
|
||||
|
||||
describe("nodes", function () {
|
||||
it("doesn't merge nodes if location is different", function () {
|
||||
var localTags = {foo: 'foo_local'}, // changed foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote'}, // same foo, added bar
|
||||
localLoc = [2, 2], // moved node
|
||||
remoteLoc = [3, 3], // moved node
|
||||
local = base.entity('a').update({tags: localTags, loc: localLoc}),
|
||||
remote = base.entity('a').update({tags: remoteTags, loc: remoteLoc, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('w1')).to.eql(local);
|
||||
expect(result).to.eql(localGraph);
|
||||
});
|
||||
|
||||
it("merges ways if nodelist is same and tags don't conflict", function () {
|
||||
var localNodes = ['p1', 'p2', 'p3', 'p4', 'p1'], // didn't change nodes
|
||||
remoteNodes = ['p1', 'p2', 'p3', 'p4', 'p1'], // didn't change nodes
|
||||
localTags = {foo: 'foo_local', area: 'yes'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', area: 'yes'}, // didn't change tag foo, added tag bar
|
||||
local = iD.Way({id: 'w1', nodes: localNodes, version: '1', v: 2, tags: localTags}),
|
||||
remote = iD.Way({id: 'w1', nodes: remoteNodes, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local]),
|
||||
it("merges nodes if location is same", function () {
|
||||
var localTags = {foo: 'foo_local'}, // changed foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote'}, // same foo, added bar
|
||||
mergedTags = {foo: 'foo_local', bar: 'bar_remote'},
|
||||
localLoc = [2, 2], // moved node
|
||||
remoteLoc = [2, 2], // moved node
|
||||
local = base.entity('a').update({tags: localTags, loc: localLoc}),
|
||||
remote = base.entity('a').update({tags: remoteTags, loc: remoteLoc, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
expect(result.entity('a').version).to.eql('2');
|
||||
expect(result.entity('a').tags).to.eql(mergedTags);
|
||||
expect(result.entity('a').loc).to.eql([2, 2]);
|
||||
});
|
||||
});
|
||||
|
||||
expect(graph.entity('w1').version).to.eql('2');
|
||||
expect(graph.entity('w1').tags).to.eql({foo: 'foo_local', bar: 'bar_remote', area: 'yes'});
|
||||
|
||||
describe("ways", function () {
|
||||
it("merges ways if nodelist is same", function () {
|
||||
var localTags = {foo: 'foo_local', area: 'yes'}, // changed foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', area: 'yes'}, // same foo, added bar
|
||||
mergedTags = {foo: 'foo_local', bar: 'bar_remote', area: 'yes'},
|
||||
local = base.entity('w1').update({tags: localTags}),
|
||||
remote = base.entity('w1').update({tags: remoteTags, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
expect(result.entity('w1').version).to.eql('2');
|
||||
expect(result.entity('w1').tags).to.eql(mergedTags);
|
||||
});
|
||||
|
||||
it("merges ways if nodelist changed only remotely", function () {
|
||||
var localNodes = ['p1', 'p2', 'p3', 'p4', 'p1'], // didn't change nodes
|
||||
remoteNodes = ['p1', 'r2', 'r3', 'p4', 'p1'], // changed nodes
|
||||
localTags = {foo: 'foo_local', area: 'yes'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', area: 'yes'}, // didn't change tag foo, added tag bar
|
||||
local = iD.Way({id: 'w1', nodes: localNodes, version: '1', v: 2, tags: localTags}),
|
||||
remote = iD.Way({id: 'w1', nodes: remoteNodes, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local]),
|
||||
var localTags = {foo: 'foo_local', area: 'yes'}, // changed foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', area: 'yes'}, // same foo, added bar
|
||||
mergedTags = {foo: 'foo_local', bar: 'bar_remote', area: 'yes'},
|
||||
localNodes = ['p1', 'p2', 'p3', 'p4', 'p1'], // didn't change nodes
|
||||
remoteNodes = ['p1', 'r2', 'r3', 'p4', 'p1'], // changed nodes
|
||||
local = base.entity('w1').update({tags: localTags, nodes: localNodes}),
|
||||
remote = base.entity('w1').update({tags: remoteTags, nodes: remoteNodes, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote, r2, r3]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('w1', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('w1').version).to.eql('2');
|
||||
expect(graph.entity('w1').tags).to.eql({foo: 'foo_local', bar: 'bar_remote', area: 'yes'});
|
||||
expect(graph.entity('w1').nodes).to.eql(remoteNodes);
|
||||
expect(graph.hasEntity('r2')).to.eql(r2);
|
||||
expect(graph.hasEntity('r3')).to.eql(r3);
|
||||
expect(result.entity('w1').version).to.eql('2');
|
||||
expect(result.entity('w1').tags).to.eql(mergedTags);
|
||||
expect(result.entity('w1').nodes).to.eql(remoteNodes);
|
||||
expect(result.hasEntity('r2')).to.eql(r2);
|
||||
expect(result.hasEntity('r3')).to.eql(r3);
|
||||
});
|
||||
|
||||
it("merges ways if nodelist changed only locally", function () {
|
||||
var localNodes = ['p1', 'r2', 'r3', 'p4', 'p1'], // changed nodes
|
||||
remoteNodes = ['p1', 'p2', 'p3', 'p4', 'p1'], // didn't change nodes
|
||||
localTags = {foo: 'foo_local', area: 'yes'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', area: 'yes'}, // didn't change tag foo, added tag bar
|
||||
local = iD.Way({id: 'w1', nodes: localNodes, version: '1', v: 2, tags: localTags}),
|
||||
remote = iD.Way({id: 'w1', nodes: remoteNodes, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local, r2, r3]),
|
||||
var localTags = {foo: 'foo_local', area: 'yes'}, // changed foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', area: 'yes'}, // same foo, added bar
|
||||
mergedTags = {foo: 'foo_local', bar: 'bar_remote', area: 'yes'},
|
||||
localNodes = ['p1', 'r2', 'r3', 'p4', 'p1'], // changed nodes
|
||||
remoteNodes = ['p1', 'p2', 'p3', 'p4', 'p1'], // didn't change nodes
|
||||
local = base.entity('w1').update({tags: localTags, nodes: localNodes}),
|
||||
remote = base.entity('w1').update({tags: remoteTags, nodes: remoteNodes, version: '2'}),
|
||||
localGraph = makeGraph([local, r2, r3]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('w1', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('w1').version).to.eql('2');
|
||||
expect(graph.entity('w1').tags).to.eql({foo: 'foo_local', bar: 'bar_remote', area: 'yes'});
|
||||
expect(graph.entity('w1').nodes).to.eql(localNodes);
|
||||
expect(result.entity('w1').version).to.eql('2');
|
||||
expect(result.entity('w1').tags).to.eql(mergedTags);
|
||||
expect(result.entity('w1').nodes).to.eql(localNodes);
|
||||
});
|
||||
|
||||
it("merges ways if nodelist changes don't overlap", function () {
|
||||
var localNodes = ['p1', 'r1', 'r2', 'p3', 'p4', 'p1'], // changed p2 -> r1, r2
|
||||
remoteNodes = ['p1', 'p2', 'p3', 'r3', 'r4', 'p1'], // changed p4 -> r3, r4
|
||||
localTags = {foo: 'foo_local', area: 'yes'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', area: 'yes'}, // didn't change tag foo, added tag bar
|
||||
local = iD.Way({id: 'w1', nodes: localNodes, version: '1', v: 2, tags: localTags}),
|
||||
remote = iD.Way({id: 'w1', nodes: remoteNodes, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local, r1, r2]),
|
||||
var localTags = {foo: 'foo_local', area: 'yes'}, // changed foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', area: 'yes'}, // same foo, added bar
|
||||
mergedTags = {foo: 'foo_local', bar: 'bar_remote', area: 'yes'},
|
||||
localNodes = ['p1', 'r1', 'r2', 'p3', 'p4', 'p1'], // changed p2 -> r1, r2
|
||||
remoteNodes = ['p1', 'p2', 'p3', 'r3', 'r4', 'p1'], // changed p4 -> r3, r4
|
||||
mergedNodes = ['p1', 'r1', 'r2', 'p3', 'r3', 'r4', 'p1'],
|
||||
local = base.entity('w1').update({tags: localTags, nodes: localNodes}),
|
||||
remote = base.entity('w1').update({tags: remoteTags, nodes: remoteNodes, version: '2'}),
|
||||
localGraph = makeGraph([local, r1, r2]),
|
||||
remoteGraph = makeGraph([remote, r3, r4]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('w1', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('w1').version).to.eql('2');
|
||||
expect(graph.entity('w1').tags).to.eql({foo: 'foo_local', bar: 'bar_remote', area: 'yes'});
|
||||
expect(graph.entity('w1').nodes).to.eql(['p1', 'r1', 'r2', 'p3', 'r3', 'r4', 'p1']);
|
||||
expect(graph.hasEntity('r3')).to.eql(r3);
|
||||
expect(graph.hasEntity('r4')).to.eql(r4);
|
||||
expect(result.entity('w1').version).to.eql('2');
|
||||
expect(result.entity('w1').tags).to.eql(mergedTags);
|
||||
expect(result.entity('w1').nodes).to.eql(mergedNodes);
|
||||
expect(result.hasEntity('r3')).to.eql(r3);
|
||||
expect(result.hasEntity('r4')).to.eql(r4);
|
||||
});
|
||||
|
||||
it("doesn't merge ways if nodelist changes overlap", function () {
|
||||
var localNodes = ['p1', 'r1', 'r2', 'p3', 'p4', 'p1'], // changed p2 -> r1, r2
|
||||
remoteNodes = ['p1', 'r3', 'r4', 'p3', 'p4', 'p1'], // changed p2 -> r3, r4
|
||||
localTags = {foo: 'foo_local', area: 'yes'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', area: 'yes'}, // didn't change tag foo, added tag bar
|
||||
local = iD.Way({id: 'w1', nodes: localNodes, version: '1', v: 2, tags: localTags}),
|
||||
remote = iD.Way({id: 'w1', nodes: remoteNodes, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local, r1, r2]),
|
||||
var localTags = {foo: 'foo_local', area: 'yes'}, // changed foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', area: 'yes'}, // same foo, added bar
|
||||
localNodes = ['p1', 'r1', 'r2', 'p3', 'p4', 'p1'], // changed p2 -> r1, r2
|
||||
remoteNodes = ['p1', 'r3', 'r4', 'p3', 'p4', 'p1'], // changed p2 -> r3, r4
|
||||
local = base.entity('w1').update({tags: localTags, nodes: localNodes}),
|
||||
remote = base.entity('w1').update({tags: remoteTags, nodes: remoteNodes, version: '2'}),
|
||||
localGraph = makeGraph([local, r1, r2]),
|
||||
remoteGraph = makeGraph([remote, r3, r4]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', graph, remoteGraph);
|
||||
action = iD.actions.MergeRemoteChanges('w1', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('w1')).to.eql(local);
|
||||
expect(result).to.eql(localGraph);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe("relations", function () {
|
||||
it("doesn't merge relations if members have changed", function () {
|
||||
var localMembers = [{id: 'w1', role: 'outer'}, {id: 'w2', role: 'inner'}], // didn't change members
|
||||
var localTags = {foo: 'foo_local', type: 'multipolygon'}, // changed foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', type: 'multipolygon'}, // same foo, added bar
|
||||
localMembers = [{id: 'w1', role: 'outer'}, {id: 'w2', role: 'inner'}], // same members
|
||||
remoteMembers = [{id: 'w1', role: 'outer'}, {id: 'w4', role: 'inner'}], // changed inner to w4
|
||||
localRelTags = {type: 'multipolygon', foo: 'foo_local'}, // changed tag foo
|
||||
remoteRelTags = {type: 'multipolygon', foo: 'foo', bar: 'bar_remote'}, // didn't change tag foo, added tag bar
|
||||
local = iD.Relation({id: 'r', members: localMembers, version: '1', v: 2, tags: localRelTags}),
|
||||
remote = iD.Relation({id: 'r', members: remoteMembers, version: '2', tags: remoteRelTags}),
|
||||
graph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([s1, s2, s3, s4, w4]);
|
||||
action = iD.actions.MergeRemoteChanges('r', graph, remoteGraph);
|
||||
local = base.entity('r').update({tags: localTags, members: localMembers}),
|
||||
remote = base.entity('r').update({tags: remoteTags, members: remoteMembers, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote, s1, s2, s3, s4, w4]),
|
||||
action = iD.actions.MergeRemoteChanges('r', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('r')).to.eql(local);
|
||||
});
|
||||
|
||||
it("doesn't merge relations if changed tags conflict", function () {
|
||||
var relMembers = [{id: 'w1', role: 'outer'}, {id: 'w2', role: 'inner'}], // didn't change members
|
||||
localRelTags = {type: 'multipolygon', foo: 'foo_local'}, // changed tag foo
|
||||
remoteRelTags = {type: 'multipolygon', foo: 'foo_remote', bar: 'bar_remote'}, // changed tag foo, added tag bar
|
||||
local = iD.Relation({id: 'r', members: relMembers, version: '1', v: 2, tags: localRelTags}),
|
||||
remote = iD.Relation({id: 'r', members: relMembers, version: '2', tags: remoteRelTags}),
|
||||
graph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]);
|
||||
action = iD.actions.MergeRemoteChanges('r', graph, remoteGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('r')).to.eql(local);
|
||||
expect(result).to.eql(localGraph);
|
||||
});
|
||||
|
||||
it("merges relations if members are same and changed tags don't conflict", function () {
|
||||
var relMembers = [{id: 'w1', role: 'outer'}, {id: 'w2', role: 'inner'}], // didn't change members
|
||||
localRelTags = {type: 'multipolygon', foo: 'foo_local'}, // changed tag foo
|
||||
remoteRelTags = {type: 'multipolygon', foo: 'foo', bar: 'bar_remote'}, // didn't change tag foo, added tag bar
|
||||
local = iD.Relation({id: 'r', members: relMembers, version: '1', v: 2, tags: localRelTags}),
|
||||
remote = iD.Relation({id: 'r', members: relMembers, version: '2', tags: remoteRelTags}),
|
||||
graph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]);
|
||||
action = iD.actions.MergeRemoteChanges('r', graph, remoteGraph);
|
||||
var localTags = {foo: 'foo_local', type: 'multipolygon'}, // changed foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote', type: 'multipolygon'}, // same foo, added bar
|
||||
mergedTags = {foo: 'foo_local', bar: 'bar_remote', type: 'multipolygon'},
|
||||
localMembers = [{id: 'w1', role: 'outer'}, {id: 'w2', role: 'inner'}], // same members
|
||||
remoteMembers = [{id: 'w1', role: 'outer'}, {id: 'w2', role: 'inner'}], // same members
|
||||
local = base.entity('r').update({tags: localTags, members: localMembers}),
|
||||
remote = base.entity('r').update({tags: remoteTags, members: remoteMembers, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('r', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('r').version).to.eql('2');
|
||||
expect(graph.entity('r').tags).to.eql({type: 'multipolygon', foo: 'foo_local', bar: 'bar_remote'});
|
||||
expect(result.entity('r').version).to.eql('2');
|
||||
expect(result.entity('r').tags).to.eql(mergedTags);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("#conflicts", function () {
|
||||
it("returns conflict details", function () {
|
||||
var localLoc = [1, 1], // didn't move node
|
||||
remoteLoc = [3, 3], // moved node
|
||||
local = iD.Node({id: 'a', loc: localLoc, version: '1', v: 2}),
|
||||
remote = iD.Node({id: 'a', loc: remoteLoc, version: '2'}),
|
||||
graph = makeGraph([local]),
|
||||
var localTags = {foo: 'foo_local'}, // changed foo
|
||||
remoteTags = {foo: 'foo', bar: 'bar_remote'}, // same foo, added bar
|
||||
remoteLoc = [2, 2], // moved node
|
||||
local = base.entity('a').update({tags: localTags}),
|
||||
remote = base.entity('a').update({tags: remoteTags, loc: remoteLoc, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('a', graph, remoteGraph);
|
||||
|
||||
graph = action(graph);
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph),
|
||||
result = action(localGraph);
|
||||
|
||||
expect(action.conflicts()).not.to.be.empty;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("destuctive merging", function () {
|
||||
describe("nodes", function () {
|
||||
it("merges nodes with 'force_local' option", function () {
|
||||
var localTags = {foo: 'foo_local'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo_remote'}, // changed tag foo
|
||||
localLoc = [2, 2], // moved node
|
||||
remoteLoc = [3, 3], // moved node
|
||||
local = iD.Node({id: 'a', loc: localLoc, version: '1', v: 2, tags: localTags}),
|
||||
remote = iD.Node({id: 'a', loc: remoteLoc, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local]),
|
||||
var localTags = {foo: 'foo_local'}, // changed foo
|
||||
remoteTags = {foo: 'foo_remote'}, // changed foo
|
||||
localLoc = [2, 2], // moved node
|
||||
remoteLoc = [3, 3], // moved node
|
||||
local = base.entity('a').update({tags: localTags, loc: localLoc}),
|
||||
remote = base.entity('a').update({tags: remoteTags, loc: remoteLoc, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('a', graph, remoteGraph).withOption('force_local');
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph).withOption('force_local'),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('a').version).to.eql('2');
|
||||
expect(graph.entity('a').loc).to.eql(localLoc);
|
||||
expect(graph.entity('a').tags).to.eql(localTags);
|
||||
expect(result.entity('a').version).to.eql('2');
|
||||
expect(result.entity('a').tags).to.eql(localTags);
|
||||
expect(result.entity('a').loc).to.eql(localLoc);
|
||||
});
|
||||
|
||||
it("merges nodes with 'force_remote' option", function () {
|
||||
var localTags = {foo: 'foo_local'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo_remote'}, // changed tag foo
|
||||
localLoc = [2, 2], // moved node
|
||||
remoteLoc = [3, 3], // moved node
|
||||
local = iD.Node({id: 'a', loc: localLoc, version: '1', v: 2, tags: localTags}),
|
||||
remote = iD.Node({id: 'a', loc: remoteLoc, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local]),
|
||||
var localTags = {foo: 'foo_local'}, // changed foo
|
||||
remoteTags = {foo: 'foo_remote'}, // changed foo
|
||||
localLoc = [2, 2], // moved node
|
||||
remoteLoc = [3, 3], // moved node
|
||||
local = base.entity('a').update({tags: localTags, loc: localLoc}),
|
||||
remote = base.entity('a').update({tags: remoteTags, loc: remoteLoc, version: '2'}),
|
||||
localGraph = makeGraph([local]),
|
||||
remoteGraph = makeGraph([remote]),
|
||||
action = iD.actions.MergeRemoteChanges('a', graph, remoteGraph).withOption('force_remote');
|
||||
action = iD.actions.MergeRemoteChanges('a', localGraph, remoteGraph).withOption('force_remote'),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('a').version).to.eql('2');
|
||||
expect(graph.entity('a').loc).to.eql(remoteLoc);
|
||||
expect(graph.entity('a').tags).to.eql(remoteTags);
|
||||
expect(result.entity('a').version).to.eql('2');
|
||||
expect(result.entity('a').tags).to.eql(remoteTags);
|
||||
expect(result.entity('a').loc).to.eql(remoteLoc);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("ways", function () {
|
||||
it("merges ways with 'force_local' option", function () {
|
||||
var localNodes = ['p1', 'r1', 'p2', 'p3', 'p4', 'p1'], // inserted node r1
|
||||
remoteNodes = ['p1', 'p2', 'p3', 's3', 'p4', 'p1'], // inserted node s3
|
||||
localTags = {foo: 'foo_local', area: 'yes'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo_remote', area: 'yes'}, // changed tag foo
|
||||
local = iD.Way({id: 'w1', nodes: localNodes, version: '1', v: 2, tags: localTags}),
|
||||
remote = iD.Way({id: 'w1', nodes: remoteNodes, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local, r1]),
|
||||
remoteGraph = makeGraph([remote, s3]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', graph, remoteGraph).withOption('force_local');
|
||||
var localTags = {foo: 'foo_local', area: 'yes'}, // changed foo
|
||||
remoteTags = {foo: 'foo_remote', area: 'yes'}, // changed foo
|
||||
localNodes = ['p1', 'r1', 'r2', 'p3', 'p4', 'p1'], // changed p2 -> r1, r2
|
||||
remoteNodes = ['p1', 'r3', 'r4', 'p3', 'p4', 'p1'], // changed p2 -> r3, r4
|
||||
local = base.entity('w1').update({tags: localTags, nodes: localNodes}),
|
||||
remote = base.entity('w1').update({tags: remoteTags, nodes: remoteNodes, version: '2'}),
|
||||
localGraph = makeGraph([local, r1, r2]),
|
||||
remoteGraph = makeGraph([remote, r3, r4]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', localGraph, remoteGraph).withOption('force_local'),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('w1').version).to.eql('2');
|
||||
expect(graph.entity('w1').nodes).to.eql(localNodes);
|
||||
expect(graph.entity('w1').tags).to.eql(localTags);
|
||||
expect(result.entity('w1').version).to.eql('2');
|
||||
expect(result.entity('w1').tags).to.eql(localTags);
|
||||
expect(result.entity('w1').nodes).to.eql(localNodes);
|
||||
});
|
||||
|
||||
it("merges ways with 'force_remote' option", function () {
|
||||
var localNodes = ['p1', 'r1', 'p2', 'p3', 'p4', 'p1'], // inserted node r1
|
||||
remoteNodes = ['p1', 'p2', 'p3', 's3', 'p4', 'p1'], // inserted node s3
|
||||
localTags = {foo: 'foo_local', area: 'yes'}, // changed tag foo
|
||||
remoteTags = {foo: 'foo_remote', area: 'yes'}, // changed tag foo
|
||||
local = iD.Way({id: 'w1', nodes: localNodes, version: '1', v: 2, tags: localTags}),
|
||||
remote = iD.Way({id: 'w1', nodes: remoteNodes, version: '2', tags: remoteTags}),
|
||||
graph = makeGraph([local, r1]),
|
||||
remoteGraph = makeGraph([remote, s3]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', graph, remoteGraph).withOption('force_remote');
|
||||
var localTags = {foo: 'foo_local', area: 'yes'}, // changed foo
|
||||
remoteTags = {foo: 'foo_remote', area: 'yes'}, // changed foo
|
||||
localNodes = ['p1', 'r1', 'r2', 'p3', 'p4', 'p1'], // changed p2 -> r1, r2
|
||||
remoteNodes = ['p1', 'r3', 'r4', 'p3', 'p4', 'p1'], // changed p2 -> r3, r4
|
||||
local = base.entity('w1').update({tags: localTags, nodes: localNodes}),
|
||||
remote = base.entity('w1').update({tags: remoteTags, nodes: remoteNodes, version: '2'}),
|
||||
localGraph = makeGraph([local, r1, r2]),
|
||||
remoteGraph = makeGraph([remote, r3, r4]),
|
||||
action = iD.actions.MergeRemoteChanges('w1', localGraph, remoteGraph).withOption('force_remote'),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('w1').version).to.eql('2');
|
||||
expect(graph.hasEntity('s3')).to.eql(s3);
|
||||
expect(graph.entity('w1').nodes).to.eql(remoteNodes);
|
||||
expect(graph.entity('w1').tags).to.eql(remoteTags);
|
||||
expect(result.entity('w1').version).to.eql('2');
|
||||
expect(result.entity('w1').tags).to.eql(remoteTags);
|
||||
expect(result.entity('w1').nodes).to.eql(remoteNodes);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("relations", function () {
|
||||
it("merges relations with 'force_local' option", function () {
|
||||
var localMembers = [{id: 'w3', role: 'outer'}, {id: 'w2', role: 'inner'}], // changed outer to w3
|
||||
remoteMembers = [{id: 'w4', role: 'outer'}, {id: 'w2', role: 'inner'}], // changed outer to w4
|
||||
localRelTags = {type: 'multipolygon', foo: 'foo_local'}, // changed tag foo
|
||||
remoteRelTags = {type: 'multipolygon', foo: 'foo_remote'}, // changed tag foo
|
||||
local = iD.Relation({id: 'r', members: localMembers, version: '1', v: 2, tags: localRelTags}),
|
||||
remote = iD.Relation({id: 'r', members: remoteMembers, version: '2', tags: remoteRelTags}),
|
||||
graph = makeGraph([local, r1, r2, r3, r4, w3]),
|
||||
var localTags = {foo: 'foo_local', type: 'multipolygon'}, // changed foo
|
||||
remoteTags = {foo: 'foo_remote', type: 'multipolygon'}, // changed foo
|
||||
localMembers = [{id: 'w3', role: 'outer'}, {id: 'w2', role: 'inner'}], // changed outer to w3
|
||||
remoteMembers = [{id: 'w1', role: 'outer'}, {id: 'w4', role: 'inner'}], // changed inner to w4
|
||||
local = base.entity('r').update({tags: localTags, members: localMembers}),
|
||||
remote = base.entity('r').update({tags: remoteTags, members: remoteMembers, version: '2'}),
|
||||
localGraph = makeGraph([local, r1, r2, r3, r4, w3]),
|
||||
remoteGraph = makeGraph([remote, s1, s2, s3, s4, w4]),
|
||||
action = iD.actions.MergeRemoteChanges('r', graph, remoteGraph).withOption('force_local');
|
||||
action = iD.actions.MergeRemoteChanges('r', localGraph, remoteGraph).withOption('force_local'),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('r').version).to.eql('2');
|
||||
expect(graph.entity('r').members).to.eql(localMembers);
|
||||
expect(graph.entity('r').tags).to.eql(localRelTags);
|
||||
expect(result.entity('r').version).to.eql('2');
|
||||
expect(result.entity('r').tags).to.eql(localTags);
|
||||
expect(result.entity('r').members).to.eql(localMembers);
|
||||
});
|
||||
|
||||
it("merges relations with 'force_remote' option", function () {
|
||||
var localMembers = [{id: 'w3', role: 'outer'}, {id: 'w2', role: 'inner'}], // changed outer to w3
|
||||
remoteMembers = [{id: 'w4', role: 'outer'}, {id: 'w2', role: 'inner'}], // changed outer to w4
|
||||
localRelTags = {type: 'multipolygon', foo: 'foo_local'}, // changed tag foo
|
||||
remoteRelTags = {type: 'multipolygon', foo: 'foo_remote'}, // changed tag foo
|
||||
local = iD.Relation({id: 'r', members: localMembers, version: '1', v: 2, tags: localRelTags}),
|
||||
remote = iD.Relation({id: 'r', members: remoteMembers, version: '2', tags: remoteRelTags}),
|
||||
graph = makeGraph([local, r1, r2, r3, r4, w3]),
|
||||
var localTags = {foo: 'foo_local', type: 'multipolygon'}, // changed foo
|
||||
remoteTags = {foo: 'foo_remote', type: 'multipolygon'}, // changed foo
|
||||
localMembers = [{id: 'w3', role: 'outer'}, {id: 'w2', role: 'inner'}], // changed outer to w3
|
||||
remoteMembers = [{id: 'w1', role: 'outer'}, {id: 'w4', role: 'inner'}], // changed inner to w4
|
||||
local = base.entity('r').update({tags: localTags, members: localMembers}),
|
||||
remote = base.entity('r').update({tags: remoteTags, members: remoteMembers, version: '2'}),
|
||||
localGraph = makeGraph([local, r1, r2, r3, r4, w3]),
|
||||
remoteGraph = makeGraph([remote, s1, s2, s3, s4, w4]),
|
||||
action = iD.actions.MergeRemoteChanges('r', graph, remoteGraph).withOption('force_remote');
|
||||
action = iD.actions.MergeRemoteChanges('r', localGraph, remoteGraph).withOption('force_remote'),
|
||||
result = action(localGraph);
|
||||
|
||||
graph = action(graph);
|
||||
|
||||
expect(graph.entity('r').version).to.eql('2');
|
||||
expect(graph.entity('r').members).to.eql(remoteMembers);
|
||||
expect(graph.entity('r').tags).to.eql(remoteRelTags);
|
||||
expect(result.entity('r').version).to.eql('2');
|
||||
expect(result.entity('r').tags).to.eql(remoteTags);
|
||||
expect(result.entity('r').members).to.eql(remoteMembers);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user