Files
iD/test/spec/actions/merge_remote_changes.js
T
Bryan Housel 977e29cfdb Most iD.actions.MergeRemoteChanges features complete
(todo: merging ways where nodelist has not been reordered)
2014-12-11 23:52:53 -05:00

340 lines
19 KiB
JavaScript

describe("iD.actions.MergeRemoteChanges", function () {
var base = iD.Graph([
iD.Node({id: 'a', loc: [1, 1], version: '1', tags: {foo: 'foo'}}),
iD.Node({id: 'p1', loc: [ 10, 10], version: '1', tags: {foo: 'foo'}}),
iD.Node({id: 'p2', loc: [ 10, -10], version: '1', tags: {foo: 'foo'}}),
iD.Node({id: 'p3', loc: [-10, -10], version: '1', tags: {foo: 'foo'}}),
iD.Node({id: 'p4', loc: [-10, 10], version: '1', tags: {foo: 'foo'}}),
iD.Way({
id: 'w1',
nodes: ['p1', 'p2', 'p3', 'p4', 'p1'],
version: '1',
tags: {foo: 'foo', area: 'yes'}
}),
iD.Node({id: 'q1', loc: [ 5, 5], version: '1', tags: {foo: 'foo'}}),
iD.Node({id: 'q2', loc: [ 5, -5], version: '1', tags: {foo: 'foo'}}),
iD.Node({id: 'q3', loc: [-5, -5], version: '1', tags: {foo: 'foo'}}),
iD.Node({id: 'q4', loc: [-5, 5], version: '1', tags: {foo: 'foo'}}),
iD.Way({
id: 'w2',
nodes: ['q1', 'q2', 'q3', 'q4', 'q1'],
version: '1',
tags: {foo: 'foo', area: 'yes'}
}),
iD.Relation({
id: 'r',
members: [{id: 'w1', role: 'outer'}, {id: 'w2', role: 'inner'}],
version: '1',
tags: {type: 'multipolygon', foo: 'foo'}
})
]),
// some new objects not in the graph yet..
r1 = iD.Node({id: 'r1', loc: [ 12, 12], version: '1', tags: {foo: 'foo_new'}}),
r2 = iD.Node({id: 'r2', loc: [ 12, -12], version: '1', tags: {foo: 'foo_new'}}),
r3 = iD.Node({id: 'r3', loc: [-12, -12], version: '1', tags: {foo: 'foo_new'}}),
r4 = iD.Node({id: 'r4', loc: [-12, 12], version: '1', tags: {foo: 'foo_new'}}),
w3 = iD.Way({
id: 'w3',
nodes: ['r1', 'r2', 'r3', 'r4', 'r1'],
version: '1',
tags: {foo: 'foo_new', area: 'yes'}
}),
s1 = iD.Node({id: 's1', loc: [ 6, 6], version: '1', tags: {foo: 'foo_new'}}),
s2 = iD.Node({id: 's2', loc: [ 6, -6], version: '1', tags: {foo: 'foo_new'}}),
s3 = iD.Node({id: 's3', loc: [-6, -6], version: '1', tags: {foo: 'foo_new'}}),
s4 = iD.Node({id: 's4', loc: [-6, 6], version: '1', tags: {foo: 'foo_new'}}),
w4 = iD.Way({
id: 'w4',
nodes: ['s1', 's2', 's3', 's4', 's1'],
version: '1',
tags: {foo: 'foo_new', area: 'yes'}
});
function makeGraph(entities) {
return _.reduce(entities, function(graph, entity) {
return graph.replace(entity);
}, iD.Graph(base));
}
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]),
altGraph = makeGraph([remote]),
action = iD.actions.MergeRemoteChanges('a', graph, altGraph);
graph = action(graph);
expect(graph.entity('a')).to.eql(local);
});
it("doesn't merge nodes if changed tags conflict", 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]),
altGraph = makeGraph([remote]),
action = iD.actions.MergeRemoteChanges('a', graph, altGraph);
graph = action(graph);
expect(graph.entity('a')).to.eql(local);
});
it("merges nodes if location is same and changed tags don't conflict", 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]),
altGraph = makeGraph([remote]),
action = iD.actions.MergeRemoteChanges('a', graph, altGraph);
graph = action(graph);
expect(graph.entity('a').version).to.eql('2');
expect(graph.entity('a').tags).to.eql({foo: 'foo_local', bar: 'bar_remote'});
});
});
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]),
altGraph = makeGraph([remote]),
action = iD.actions.MergeRemoteChanges('w1', graph, altGraph);
graph = action(graph);
expect(graph.entity('w1')).to.eql(local);
});
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]),
altGraph = makeGraph([remote]),
action = iD.actions.MergeRemoteChanges('w1', graph, altGraph);
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'});
});
it("doesn't merge ways if nodelist reordered", function () {
var localNodes = ['p1', 'p2', 'p3', 'p4', 'p1'], // didn't change nodes
remoteNodes = ['p1', 'p3', 'p4', 'p2', 'p1'], // reordered 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]),
altGraph = makeGraph([remote]),
action = iD.actions.MergeRemoteChanges('w1', graph, altGraph);
graph = action(graph);
expect(graph.entity('w1')).to.eql(local);
});
it("merges ways if nodelist order preserved");
});
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
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]),
altGraph = makeGraph([s1, s2, s3, s4, w4]);
action = iD.actions.MergeRemoteChanges('r', graph, altGraph);
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]),
altGraph = makeGraph([remote]);
action = iD.actions.MergeRemoteChanges('r', graph, altGraph);
graph = action(graph);
expect(graph.entity('r')).to.eql(local);
});
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]),
altGraph = makeGraph([remote]);
action = iD.actions.MergeRemoteChanges('r', graph, altGraph);
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'});
});
});
});
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]),
altGraph = makeGraph([remote]),
action = iD.actions.MergeRemoteChanges('a', graph, altGraph).withOption('force_local');
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);
});
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]),
altGraph = makeGraph([remote]),
action = iD.actions.MergeRemoteChanges('a', graph, altGraph).withOption('force_remote');
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);
});
});
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]),
altGraph = makeGraph([remote, s3]),
action = iD.actions.MergeRemoteChanges('w1', graph, altGraph).withOption('force_local');
graph = action(graph);
expect(graph.entity('w1').version).to.eql('2');
expect(graph.hasEntity('s3')).to.be.undefined;
expect(graph.entity('w1').nodes).to.eql(localNodes);
expect(graph.entity('w1').tags).to.eql(localTags);
});
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]),
altGraph = makeGraph([remote, s3]),
action = iD.actions.MergeRemoteChanges('w1', graph, altGraph).withOption('force_remote');
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);
});
});
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]),
altGraph = makeGraph([remote, s1, s2, s3, s4, w4]),
action = iD.actions.MergeRemoteChanges('r', graph, altGraph).withOption('force_local');
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);
});
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]),
altGraph = makeGraph([remote, s1, s2, s3, s4, w4]),
action = iD.actions.MergeRemoteChanges('r', graph, altGraph).withOption('force_remote');
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);
});
});
});
});