Order deletions in osmChange XML (fixes #541)

This relies on iteration order of JS objects, which
is technically undefined. But currently all relevant
browsers implement first-defined-first-iterated order
for non-numeric keys. And I've written the specs so that
they will fail on browsers that don't adhere to this.
This commit is contained in:
John Firebaugh
2013-01-28 11:47:59 -05:00
parent 05e3dd73a8
commit e69f613b51
2 changed files with 52 additions and 15 deletions
+4 -9
View File
@@ -200,14 +200,13 @@ iD.Connection = function() {
// Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
// XML. Returns a string.
connection.osmChangeJXON = function(userid, changeset_id, changes) {
function nest(x) {
function nest(x, order) {
var groups = {};
for (var i = 0; i < x.length; i++) {
var tagName = Object.keys(x[i])[0];
if (!groups[tagName]) groups[tagName] = [];
groups[tagName].push(x[i][tagName]);
}
var order = ['node', 'way', 'relation'];
var ordered = {};
order.forEach(function(o) {
if (groups[o]) ordered[o] = groups[o];
@@ -223,13 +222,9 @@ iD.Connection = function() {
osmChange: {
'@version': 0.3,
'@generator': 'iD',
'create': nest(changes.created.map(rep)),
'modify': changes.modified.map(rep),
'delete': changes.deleted.map(function(x) {
x = rep(x);
x['@if-unused'] = true;
return x;
})
'create': nest(changes.created.map(rep), ['node', 'way', 'relation']),
'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
'delete': _.extend(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
}
};
};
+48 -6
View File
@@ -51,18 +51,60 @@ describe('iD.Connection', function () {
describe('#osmChangeJXON', function() {
it('converts change data to JXON', function() {
var node = iD.Node({ id: 'n-1', type: 'node', loc: [-77, 38] }),
way = iD.Way({ id: 'w-1', type: 'way', nodes: [] }),
jxon = c.osmChangeJXON('jfire', '1234', {created: [node], modified: [way], deleted: []});
var jxon = c.osmChangeJXON('jfire', '1234', {created: [], modified: [], deleted: []});
expect(jxon).to.eql({
osmChange: {
'@version': 0.3,
'@generator': 'iD',
'create': {node: [node.asJXON('1234').node]},
'modify': [way.asJXON('1234')],
'delete': []
'create': {},
'modify': {},
'delete': {'@if-unused': true}
}
});
});
it('includes creations ordered by nodes, ways, relations', function() {
var n = iD.Node({loc: [0, 0]}),
w = iD.Way(),
r = iD.Relation(),
changes = {created: [r, w, n], modified: [], deleted: []},
jxon = c.osmChangeJXON('jfire', '1234', changes);
expect(d3.entries(jxon.osmChange['create'])).to.eql([
{key: 'node', value: [n.asJXON('1234').node]},
{key: 'way', value: [w.asJXON('1234').way]},
{key: 'relation', value: [r.asJXON('1234').relation]}
]);
});
it('includes modifications', function() {
var n = iD.Node({loc: [0, 0]}),
w = iD.Way(),
r = iD.Relation(),
changes = {created: [], modified: [r, w, n], deleted: []},
jxon = c.osmChangeJXON('jfire', '1234', changes);
expect(jxon.osmChange['modify']).to.eql({
node: [n.asJXON('1234').node],
way: [w.asJXON('1234').way],
relation: [r.asJXON('1234').relation]
});
});
it('includes deletions ordered by relations, ways, nodes', function() {
var n = iD.Node({loc: [0, 0]}),
w = iD.Way(),
r = iD.Relation(),
changes = {created: [], modified: [], deleted: [n, w, r]},
jxon = c.osmChangeJXON('jfire', '1234', changes);
expect(d3.entries(jxon.osmChange['delete'])).to.eql([
{key: 'relation', value: [r.asJXON('1234').relation]},
{key: 'way', value: [w.asJXON('1234').way]},
{key: 'node', value: [n.asJXON('1234').node]},
{key: '@if-unused', value: true}
]);
});
});
});