5 class UploadsControllerTest < ActionDispatch::IntegrationTest
7 # test all routes which lead to this controller
10 { :path => "/api/0.6/changeset/1/upload", :method => :post },
11 { :controller => "api/changesets/uploads", :action => "create", :changeset_id => "1" }
15 def test_upload_when_unauthorized
16 changeset = create(:changeset)
17 node = create(:node, :latitude => 0, :longitude => 0)
22 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
27 post api_changeset_upload_path(changeset), :params => diff
29 assert_response :unauthorized
32 assert_equal 0, changeset.num_changes
34 assert_equal 1, node.version
35 assert_equal 0, node.latitude
36 assert_equal 0, node.longitude
39 def test_upload_by_private_user
40 user = create(:user, :data_public => false)
41 changeset = create(:changeset, :user => user)
42 node = create(:node, :latitude => 0, :longitude => 0)
47 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
52 auth_header = bearer_authorization_header user
54 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
56 assert_response :forbidden
59 assert_equal 0, changeset.num_changes
61 assert_equal 1, node.version
62 assert_equal 0, node.latitude
63 assert_equal 0, node.longitude
66 def test_upload_without_required_scope
68 changeset = create(:changeset, :user => user)
69 node = create(:node, :latitude => 0, :longitude => 0)
74 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
79 auth_header = bearer_authorization_header user, :scopes => %w[read_prefs]
81 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
83 assert_response :forbidden
86 assert_equal 0, changeset.num_changes
88 assert_equal 1, node.version
89 assert_equal 0, node.latitude
90 assert_equal 0, node.longitude
93 def test_upload_with_required_scope
95 changeset = create(:changeset, :user => user)
96 node = create(:node, :latitude => 0, :longitude => 0)
101 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
106 auth_header = bearer_authorization_header user, :scopes => %w[write_api]
108 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
110 assert_response :success
112 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
113 assert_dom "> node", 1 do
114 assert_dom "> @old_id", node.id.to_s
115 assert_dom "> @new_id", node.id.to_s
116 assert_dom "> @new_version", "2"
121 assert_equal 1, changeset.num_changes
123 assert_equal 2, node.version
124 assert_equal 2 * GeoRecord::SCALE, node.latitude
125 assert_equal 1 * GeoRecord::SCALE, node.longitude
129 # try to upload with commands other than create, modify, or delete
130 def test_upload_unknown_action
131 changeset = create(:changeset)
136 <node id='1' lon='1' lat='1' changeset='#{changeset.id}' />
141 auth_header = bearer_authorization_header changeset.user
143 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
145 assert_response :bad_request
146 assert_equal "Unknown action ping, choices are create, modify, delete", @response.body
150 # test for issues in https://github.com/openstreetmap/trac-tickets/issues/1568
151 def test_upload_empty_changeset
152 changeset = create(:changeset)
154 auth_header = bearer_authorization_header changeset.user
157 "<osmChange></osmChange>",
158 "<osmChange><modify/></osmChange>",
159 "<osmChange><modify></modify></osmChange>"].each do |diff|
160 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
162 assert_response :success
166 # -------------------------------------
167 # Test creating elements.
168 # -------------------------------------
170 def test_upload_create_elements
172 changeset = create(:changeset, :user => user)
174 way = create(:way_with_nodes, :nodes_count => 2)
175 relation = create(:relation)
180 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
181 <tag k='foo' v='bar'/>
182 <tag k='baz' v='bat'/>
184 <way id='-1' changeset='#{changeset.id}'>
185 <nd ref='#{node.id}'/>
189 <relation id='-1' changeset='#{changeset.id}'>
190 <member type='way' role='some' ref='#{way.id}'/>
191 <member type='node' role='some' ref='#{node.id}'/>
192 <member type='relation' role='some' ref='#{relation.id}'/>
198 auth_header = bearer_authorization_header user
200 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
202 assert_response :success
204 new_node_id, new_way_id, new_rel_id = nil
205 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
206 # inspect the response to find out what the new element IDs are
207 # check the old IDs are all present and negative one
208 # check the versions are present and equal one
209 assert_dom "> node", 1 do |(node_el)|
210 new_node_id = node_el["new_id"].to_i
211 assert_dom "> @old_id", "-1"
212 assert_dom "> @new_version", "1"
214 assert_dom "> way", 1 do |(way_el)|
215 new_way_id = way_el["new_id"].to_i
216 assert_dom "> @old_id", "-1"
217 assert_dom "> @new_version", "1"
219 assert_dom "> relation", 1 do |(rel_el)|
220 new_rel_id = rel_el["new_id"].to_i
221 assert_dom "> @old_id", "-1"
222 assert_dom "> @new_version", "1"
226 assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
227 assert_equal 0, Way.find(new_way_id).tags.size, "new way should have no tags"
228 assert_equal 0, Relation.find(new_rel_id).tags.size, "new relation should have no tags"
232 # upload an element with a really long tag value
233 def test_upload_create_node_with_tag_too_long
234 changeset = create(:changeset)
239 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
240 <tag k='foo' v='#{'x' * 256}'/>
246 auth_header = bearer_authorization_header changeset.user
248 assert_no_difference "Node.count" do
249 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
251 assert_response :bad_request
255 def test_upload_create_nodes_with_invalid_placeholder_reuse_in_one_action_block
256 changeset = create(:changeset)
261 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}' version='1'/>
262 <node id='-1' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
267 auth_header = bearer_authorization_header changeset.user
269 assert_no_difference "Node.count" do
270 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
272 assert_response :bad_request
276 def test_upload_create_nodes_with_invalid_placeholder_reuse_in_two_action_blocks
277 changeset = create(:changeset)
282 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}' version='1'/>
285 <node id='-1' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
290 auth_header = bearer_authorization_header changeset.user
292 assert_no_difference "Node.count" do
293 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
295 assert_response :bad_request
299 def test_upload_create_way_referring_node_placeholder_defined_later
300 changeset = create(:changeset)
305 <way id="-1" changeset="#{changeset.id}">
308 <node id="-1" lat="1" lon="2" changeset="#{changeset.id}"/>
313 auth_header = bearer_authorization_header changeset.user
315 assert_no_difference "Node.count" do
316 assert_no_difference "Way.count" do
317 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
319 assert_response :bad_request
322 assert_equal "Placeholder node not found for reference -1 in way -1", @response.body
325 def test_upload_create_way_referring_undefined_node_placeholder
326 changeset = create(:changeset)
331 <way id="-1" changeset="#{changeset.id}">
338 auth_header = bearer_authorization_header changeset.user
340 assert_no_difference "Way.count" do
341 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
343 assert_response :bad_request
345 assert_equal "Placeholder node not found for reference -1 in way -1", @response.body
348 def test_upload_create_existing_way_referring_undefined_node_placeholder
349 changeset = create(:changeset)
355 <way id="#{way.id}" changeset="#{changeset.id}" version="1">
362 auth_header = bearer_authorization_header changeset.user
364 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
366 assert_response :bad_request
367 assert_equal "Placeholder node not found for reference -1 in way #{way.id}", @response.body
370 assert_equal 1, way.version
373 def test_upload_create_relation_referring_undefined_node_placeholder
374 changeset = create(:changeset)
379 <relation id="-1" changeset="#{changeset.id}" version="1">
380 <member type="node" role="foo" ref="-1"/>
386 auth_header = bearer_authorization_header changeset.user
388 assert_no_difference "Relation.count" do
389 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
391 assert_response :bad_request
393 assert_equal "Placeholder Node not found for reference -1 in relation -1.", @response.body
396 def test_upload_create_existing_relation_referring_undefined_way_placeholder
397 changeset = create(:changeset)
398 relation = create(:relation)
403 <relation id="#{relation.id}" changeset="#{changeset.id}" version="1">
404 <member type="way" role="bar" ref="-1"/>
410 auth_header = bearer_authorization_header changeset.user
412 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
414 assert_response :bad_request
415 assert_equal "Placeholder Way not found for reference -1 in relation #{relation.id}.", @response.body
418 assert_equal 1, relation.version
421 def test_upload_create_relations_with_circular_references
422 changeset = create(:changeset)
425 <osmChange version='0.6'>
427 <relation id='-2' version='0' changeset='#{changeset.id}'>
428 <member type='relation' role='' ref='-4' />
429 <tag k='type' v='route' />
430 <tag k='name' v='AtoB' />
432 <relation id='-3' version='0' changeset='#{changeset.id}'>
433 <tag k='type' v='route' />
434 <tag k='name' v='BtoA' />
436 <relation id='-4' version='0' changeset='#{changeset.id}'>
437 <member type='relation' role='' ref='-2' />
438 <member type='relation' role='' ref='-3' />
439 <tag k='type' v='route_master' />
440 <tag k='name' v='master' />
446 auth_header = bearer_authorization_header changeset.user
448 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
450 assert_response :bad_request
451 assert_equal "Placeholder Relation not found for reference -4 in relation -2.", @response.body
454 # -------------------------------------
455 # Test modifying elements.
456 # -------------------------------------
458 def test_upload_modify_elements
460 changeset = create(:changeset, :user => user)
461 node = create(:node, :latitude => 0, :longitude => 0)
463 relation = create(:relation)
464 other_relation = create(:relation)
466 # create some tags, since we test that they are removed later
467 create(:node_tag, :node => node)
468 create(:way_tag, :way => way)
469 create(:relation_tag, :relation => relation)
471 # simple diff to change a node, way and relation by removing their tags
475 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
476 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
477 <nd ref='#{node.id}'/>
481 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'>
482 <member type='way' role='some' ref='#{way.id}'/>
483 <member type='node' role='some' ref='#{node.id}'/>
484 <member type='relation' role='some' ref='#{other_relation.id}'/>
490 auth_header = bearer_authorization_header user
492 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
494 assert_response :success
496 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
497 assert_dom "> node", 1 do
498 assert_dom "> @old_id", node.id.to_s
499 assert_dom "> @new_id", node.id.to_s
500 assert_dom "> @new_version", "2"
502 assert_dom "> way", 1 do
503 assert_dom "> @old_id", way.id.to_s
504 assert_dom "> @new_id", way.id.to_s
505 assert_dom "> @new_version", "2"
507 assert_dom "> relation", 1 do
508 assert_dom "> @old_id", relation.id.to_s
509 assert_dom "> @new_id", relation.id.to_s
510 assert_dom "> @new_version", "2"
515 assert_equal 3, changeset.num_changes
517 assert_equal 2, node.version
518 assert_equal 2 * GeoRecord::SCALE, node.latitude
519 assert_equal 1 * GeoRecord::SCALE, node.longitude
520 assert_equal 0, node.tags.size, "node #{node.id} should now have no tags"
522 assert_equal 2, way.version
523 assert_equal 0, way.tags.size, "way #{way.id} should now have no tags"
524 assert_equal [node], way.nodes
526 assert_equal 2, relation.version
527 assert_equal 0, relation.tags.size, "relation #{relation.id} should now have no tags"
528 assert_equal [["Way", way.id, "some"], ["Node", node.id, "some"], ["Relation", other_relation.id, "some"]], relation.members
532 # upload multiple versions of the same element in the same diff.
533 def test_upload_modify_multiple_node_versions
535 changeset = create(:changeset)
537 # change the location of a node multiple times, each time referencing
538 # the last version. doesn't this depend on version numbers being
543 <node id='#{node.id}' lon='0.0' lat='0.0' changeset='#{changeset.id}' version='1'/>
544 <node id='#{node.id}' lon='0.1' lat='0.0' changeset='#{changeset.id}' version='2'/>
545 <node id='#{node.id}' lon='0.1' lat='0.1' changeset='#{changeset.id}' version='3'/>
546 <node id='#{node.id}' lon='0.1' lat='0.2' changeset='#{changeset.id}' version='4'/>
547 <node id='#{node.id}' lon='0.2' lat='0.2' changeset='#{changeset.id}' version='5'/>
548 <node id='#{node.id}' lon='0.3' lat='0.2' changeset='#{changeset.id}' version='6'/>
549 <node id='#{node.id}' lon='0.3' lat='0.3' changeset='#{changeset.id}' version='7'/>
550 <node id='#{node.id}' lon='0.9' lat='0.9' changeset='#{changeset.id}' version='8'/>
555 auth_header = bearer_authorization_header changeset.user
557 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
559 assert_response :success
561 assert_dom "diffResult>node", 8
564 assert_equal 9, node.version
565 assert_equal 0.9 * GeoRecord::SCALE, node.latitude
566 assert_equal 0.9 * GeoRecord::SCALE, node.longitude
570 # upload multiple versions of the same element in the same diff, but
571 # keep the version numbers the same.
572 def test_upload_modify_duplicate_node_versions
573 node = create(:node, :latitude => 0, :longitude => 0)
574 changeset = create(:changeset)
579 <node id='#{node.id}' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
580 <node id='#{node.id}' lon='2' lat='2' changeset='#{changeset.id}' version='1'/>
585 auth_header = bearer_authorization_header changeset.user
587 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
589 assert_response :conflict
592 assert_equal 1, node.version
593 assert_equal 0, node.latitude
594 assert_equal 0, node.longitude
598 # try to upload some elements without specifying the version
599 def test_upload_modify_missing_node_version
600 node = create(:node, :latitude => 0, :longitude => 0)
601 changeset = create(:changeset)
606 <node id='#{node.id}' lon='1' lat='1' changeset='#{changeset.id}'/>
611 auth_header = bearer_authorization_header changeset.user
613 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
615 assert_response :bad_request
618 assert_equal 1, node.version
619 assert_equal 0, node.latitude
620 assert_equal 0, node.longitude
624 # create a diff which references several changesets, which should cause
625 # a rollback and none of the diff gets committed
626 def test_upload_modify_with_references_to_different_changesets
627 changeset1 = create(:changeset)
628 changeset2 = create(:changeset, :user => changeset1.user)
629 node1 = create(:node)
630 node2 = create(:node)
632 # simple diff to create a node way and relation using placeholders
636 <node id='#{node1.id}' lon='0' lat='0' changeset='#{changeset1.id}' version='1'/>
639 <node id='#{node2.id}' lon='0' lat='0' changeset='#{changeset2.id}' version='1'/>
644 auth_header = bearer_authorization_header changeset1.user
646 post api_changeset_upload_path(changeset1), :params => diff, :headers => auth_header
648 assert_response :conflict
650 assert_nodes_are_equal(node1, Node.find(node1.id))
651 assert_nodes_are_equal(node2, Node.find(node2.id))
655 # upload a valid changeset which has a mixture of whitespace
656 # to check a bug https://github.com/openstreetmap/trac-tickets/issues/1565
657 def test_upload_modify_with_mixed_whitespace
658 changeset = create(:changeset)
660 way = create(:way_with_nodes, :nodes_count => 2)
661 relation = create(:relation)
662 other_relation = create(:relation)
663 create(:relation_tag, :relation => relation)
667 <modify><node id='#{node.id}' lon='0' lat='0' changeset='#{changeset.id}'
669 <node id='#{node.id}' lon='1' lat='1' changeset='#{changeset.id}' version='2'><tag k='k' v='v'/></node></modify>
671 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'><member
672 type='way' role='some' ref='#{way.id}'/><member
673 type='node' role='some' ref='#{node.id}'/>
674 <member type='relation' role='some' ref='#{other_relation.id}'/>
676 </modify></osmChange>
679 auth_header = bearer_authorization_header changeset.user
681 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
683 assert_response :success
685 assert_dom "diffResult>node", 2
686 assert_dom "diffResult>relation", 1
688 assert_equal 1, Node.find(node.id).tags.size, "node #{node.id} should now have one tag"
689 assert_equal 0, Relation.find(relation.id).tags.size, "relation #{relation.id} should now have no tags"
692 # -------------------------------------
693 # Test deleting elements.
694 # -------------------------------------
697 # test a complex delete where we delete elements which rely on each other
698 # in the same transaction.
699 def test_upload_delete_elements
700 changeset = create(:changeset)
701 super_relation = create(:relation)
702 used_relation = create(:relation)
703 used_way = create(:way)
704 used_node = create(:node)
705 create(:relation_member, :relation => super_relation, :member => used_relation)
706 create(:relation_member, :relation => super_relation, :member => used_way)
707 create(:relation_member, :relation => super_relation, :member => used_node)
709 diff = XML::Document.new
710 diff.root = XML::Node.new "osmChange"
711 delete = XML::Node.new "delete"
713 delete << xml_node_for_relation(super_relation)
714 delete << xml_node_for_relation(used_relation)
715 delete << xml_node_for_way(used_way)
716 delete << xml_node_for_node(used_node)
717 %w[node way relation].each do |type|
718 delete.find("//osmChange/delete/#{type}").each do |n|
719 n["changeset"] = changeset.id.to_s
723 auth_header = bearer_authorization_header changeset.user
725 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
727 assert_response :success
729 assert_dom "diffResult", 1 do
730 assert_dom "> node", 1
731 assert_dom "> way", 1
732 assert_dom "> relation", 2
735 assert_not Node.find(used_node.id).visible
736 assert_not Way.find(used_way.id).visible
737 assert_not Relation.find(super_relation.id).visible
738 assert_not Relation.find(used_relation.id).visible
742 # test uploading a delete with no lat/lon, as they are optional in the osmChange spec.
743 def test_upload_delete_node_without_latlon
745 changeset = create(:changeset)
747 diff = "<osmChange><delete><node id='#{node.id}' version='#{node.version}' changeset='#{changeset.id}'/></delete></osmChange>"
749 auth_header = bearer_authorization_header changeset.user
751 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
753 assert_response :success
755 assert_dom "diffResult", 1 do
756 assert_dom "> node", 1 do
757 assert_dom "> @old_id", node.id.to_s
758 assert_dom "> @new_id", 0
759 assert_dom "> @new_version", 0
764 assert_not node.visible
768 # test that deleting stuff in a transaction doesn't bypass the checks
769 # to ensure that used elements are not deleted.
770 def test_upload_delete_referenced_elements
771 changeset = create(:changeset)
772 relation = create(:relation)
773 other_relation = create(:relation)
774 used_way = create(:way)
775 used_node = create(:node)
776 create(:relation_member, :relation => relation, :member => used_way)
777 create(:relation_member, :relation => relation, :member => used_node)
779 diff = XML::Document.new
780 diff.root = XML::Node.new "osmChange"
781 delete = XML::Node.new "delete"
783 delete << xml_node_for_relation(other_relation)
784 delete << xml_node_for_way(used_way)
785 delete << xml_node_for_node(used_node)
786 %w[node way relation].each do |type|
787 delete.find("//osmChange/delete/#{type}").each do |n|
788 n["changeset"] = changeset.id.to_s
792 auth_header = bearer_authorization_header changeset.user
794 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
796 assert_response :precondition_failed
797 assert_equal "Precondition failed: Way #{used_way.id} is still used by relations #{relation.id}.", @response.body
799 assert Node.find(used_node.id).visible
800 assert Way.find(used_way.id).visible
801 assert Relation.find(relation.id).visible
802 assert Relation.find(other_relation.id).visible
806 # test that a conditional delete of an in use object works.
807 def test_upload_delete_if_unused
808 changeset = create(:changeset)
809 super_relation = create(:relation)
810 used_relation = create(:relation)
811 used_way = create(:way)
812 used_node = create(:node)
813 create(:relation_member, :relation => super_relation, :member => used_relation)
814 create(:relation_member, :relation => super_relation, :member => used_way)
815 create(:relation_member, :relation => super_relation, :member => used_node)
817 diff = XML::Document.new
818 diff.root = XML::Node.new "osmChange"
819 delete = XML::Node.new "delete"
821 delete["if-unused"] = ""
822 delete << xml_node_for_relation(used_relation)
823 delete << xml_node_for_way(used_way)
824 delete << xml_node_for_node(used_node)
825 %w[node way relation].each do |type|
826 delete.find("//osmChange/delete/#{type}").each do |n|
827 n["changeset"] = changeset.id.to_s
831 auth_header = bearer_authorization_header changeset.user
833 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
835 assert_response :success
837 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
838 assert_dom "> node", 1 do
839 assert_dom "> @old_id", used_node.id.to_s
840 assert_dom "> @new_id", used_node.id.to_s
841 assert_dom "> @new_version", used_node.version.to_s
843 assert_dom "> way", 1 do
844 assert_dom "> @old_id", used_way.id.to_s
845 assert_dom "> @new_id", used_way.id.to_s
846 assert_dom "> @new_version", used_way.version.to_s
848 assert_dom "> relation", 1 do
849 assert_dom "> @old_id", used_relation.id.to_s
850 assert_dom "> @new_id", used_relation.id.to_s
851 assert_dom "> @new_version", used_relation.version.to_s
855 assert Node.find(used_node.id).visible
856 assert Way.find(used_way.id).visible
857 assert Relation.find(used_relation.id).visible
860 def test_upload_delete_with_multiple_blocks_and_if_unused
861 changeset = create(:changeset)
864 create(:way_node, :way => way, :node => node)
865 alone_node = create(:node)
868 <osmChange version='0.6'>
869 <delete version="0.6">
870 <node id="#{node.id}" version="#{node.version}" changeset="#{changeset.id}"/>
872 <delete version="0.6" if-unused="true">
873 <node id="#{alone_node.id}" version="#{alone_node.version}" changeset="#{changeset.id}"/>
878 auth_header = bearer_authorization_header changeset.user
880 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
882 assert_response :precondition_failed
884 assert_equal "Precondition failed: Node #{node.id} is still used by ways #{way.id}.", @response.body
887 # -------------------------------------
888 # Test combined element changes.
889 # -------------------------------------
892 # upload something which creates new objects and inserts them into
893 # existing containers using placeholders.
894 def test_upload_create_and_insert_elements
897 relation = create(:relation)
898 create(:way_node, :way => way, :node => node)
899 changeset = create(:changeset)
904 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
905 <tag k='foo' v='bar'/>
906 <tag k='baz' v='bat'/>
910 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
912 <nd ref='#{node.id}'/>
914 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'>
915 <member type='way' role='some' ref='#{way.id}'/>
916 <member type='node' role='some' ref='-1'/>
917 <member type='relation' role='some' ref='#{relation.id}'/>
923 auth_header = bearer_authorization_header changeset.user
925 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
927 assert_response :success
930 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
931 assert_dom "> node", 1 do |(node_el)|
932 new_node_id = node_el["new_id"].to_i
934 assert_dom "> way", 1
935 assert_dom "> relation", 1
938 assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
939 assert_equal [new_node_id, node.id], Way.find(way.id).nds, "way nodes should match"
940 Relation.find(relation.id).members.each do |type, id, _role|
941 assert_equal new_node_id, id, "relation should contain new node" if type == "node"
946 # test that a placeholder can be reused within the same upload.
947 def test_upload_create_modify_delete_node_reusing_placeholder
948 changeset = create(:changeset)
953 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
954 <tag k="foo" v="bar"/>
958 <node id='-1' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
961 <node id='-1' lon='2' lat='2' changeset='#{changeset.id}' version='2'/>
966 auth_header = bearer_authorization_header changeset.user
968 assert_difference "Node.count", 1 do
969 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
971 assert_response :success
974 assert_dom "diffResult>node", 3
975 assert_dom "diffResult>node[old_id='-1']", 3
978 assert_equal 3, node.version
979 assert_not node.visible
982 def test_upload_create_and_duplicate_delete
983 changeset = create(:changeset)
988 <node id="-1" lat="39" lon="116" changeset="#{changeset.id}" />
991 <node id="-1" version="1" changeset="#{changeset.id}" />
992 <node id="-1" version="1" changeset="#{changeset.id}" />
997 auth_header = bearer_authorization_header changeset.user
999 assert_no_difference "Node.count" do
1000 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1002 assert_response :gone
1006 def test_upload_create_and_duplicate_delete_if_unused
1007 changeset = create(:changeset)
1012 <node id="-1" lat="39" lon="116" changeset="#{changeset.id}" />
1014 <delete if-unused="true">
1015 <node id="-1" version="1" changeset="#{changeset.id}" />
1016 <node id="-1" version="1" changeset="#{changeset.id}" />
1021 auth_header = bearer_authorization_header changeset.user
1023 assert_difference "Node.count", 1 do
1024 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1026 assert_response :success
1029 assert_dom "diffResult>node", 3
1030 assert_dom "diffResult>node[old_id='-1']", 3
1031 assert_dom "diffResult>node[new_version='1']", 1
1032 assert_dom "diffResult>node[new_version='2']", 1
1035 assert_equal 2, node.version
1036 assert_not node.visible