1 # frozen_string_literal: true
4 require_relative "elements_test_helper"
7 class WaysControllerTest < ActionDispatch::IntegrationTest
8 include ElementsTestHelper
11 # test all routes which lead to this controller
14 { :path => "/api/0.6/ways", :method => :get },
15 { :controller => "api/ways", :action => "index" }
18 { :path => "/api/0.6/ways.json", :method => :get },
19 { :controller => "api/ways", :action => "index", :format => "json" }
22 { :path => "/api/0.6/ways", :method => :post },
23 { :controller => "api/ways", :action => "create" }
26 { :path => "/api/0.6/way/1", :method => :get },
27 { :controller => "api/ways", :action => "show", :id => "1" }
30 { :path => "/api/0.6/way/1.json", :method => :get },
31 { :controller => "api/ways", :action => "show", :id => "1", :format => "json" }
34 { :path => "/api/0.6/way/1/full", :method => :get },
35 { :controller => "api/ways", :action => "show", :full => true, :id => "1" }
38 { :path => "/api/0.6/way/1/full.json", :method => :get },
39 { :controller => "api/ways", :action => "show", :full => true, :id => "1", :format => "json" }
42 { :path => "/api/0.6/way/1", :method => :put },
43 { :controller => "api/ways", :action => "update", :id => "1" }
46 { :path => "/api/0.6/way/1", :method => :delete },
47 { :controller => "api/ways", :action => "destroy", :id => "1" }
51 { :controller => "api/ways", :action => "create" },
52 { :path => "/api/0.6/way/create", :method => :put }
57 # test fetching multiple ways
60 way2 = create(:way, :deleted)
64 # check error when no parameter provided
66 assert_response :bad_request
68 # check error when no parameter value provided
69 get api_ways_path(:ways => "")
70 assert_response :bad_request
73 get api_ways_path(:ways => "#{way1.id},#{way2.id},#{way3.id},#{way4.id}")
74 assert_response :success
75 assert_select "osm" do
76 assert_select "way", :count => 4
77 assert_select "way[id='#{way1.id}'][visible='true']", :count => 1
78 assert_select "way[id='#{way2.id}'][visible='false']", :count => 1
79 assert_select "way[id='#{way3.id}'][visible='true']", :count => 1
80 assert_select "way[id='#{way4.id}'][visible='true']", :count => 1
83 # test a working call with json format
84 get api_ways_path(:ways => "#{way1.id},#{way2.id},#{way3.id},#{way4.id}", :format => "json")
86 js = ActiveSupport::JSON.decode(@response.body)
88 assert_equal 4, js["elements"].count
89 assert_equal(4, js["elements"].count { |a| a["type"] == "way" })
90 assert_equal(1, js["elements"].count { |a| a["id"] == way1.id && a["visible"].nil? })
91 assert_equal(1, js["elements"].count { |a| a["id"] == way2.id && a["visible"] == false })
92 assert_equal(1, js["elements"].count { |a| a["id"] == way3.id && a["visible"].nil? })
93 assert_equal(1, js["elements"].count { |a| a["id"] == way4.id && a["visible"].nil? })
95 # check error when a non-existent way is included
96 get api_ways_path(:ways => "#{way1.id},#{way2.id},#{way3.id},#{way4.id},0")
97 assert_response :not_found
100 # -------------------------------------
102 # -------------------------------------
104 def test_show_not_found
106 assert_response :not_found
109 def test_show_deleted
110 get api_way_path(create(:way, :deleted))
111 assert_response :gone
115 way = create(:way, :timestamp => "2021-02-03T00:00:00Z")
116 node = create(:node, :timestamp => "2021-04-05T00:00:00Z")
117 create(:way_node, :way => way, :node => node)
119 get api_way_path(way)
121 assert_response :success
122 assert_not_nil @response.header["Last-Modified"]
123 assert_equal "2021-02-03T00:00:00Z", Time.parse(@response.header["Last-Modified"]).utc.xmlschema
127 way = create(:way_with_nodes, :nodes_count => 3)
129 get api_way_path(way, :format => "json")
131 assert_response :success
133 js = ActiveSupport::JSON.decode(@response.body)
135 assert_equal 1, js["elements"].count
136 js_ways = js["elements"].filter { |e| e["type"] == "way" }
137 assert_equal 1, js_ways.count
138 assert_equal way.id, js_ways[0]["id"]
139 assert_equal 1, js_ways[0]["version"]
143 # check the "full" mode
145 way = create(:way_with_nodes, :nodes_count => 3)
147 get api_way_path(way, :full => true)
149 assert_response :success
151 # Check the way is correctly returned
152 assert_select "osm way[id='#{way.id}'][version='1'][visible='true']", 1
154 # check that each node in the way appears once in the output as a
155 # reference and as the node element.
156 way.nodes.each do |n|
157 assert_select "osm way nd[ref='#{n.id}']", 1
158 assert_select "osm node[id='#{n.id}'][version='1'][lat='#{format('%<lat>.7f', :lat => n.lat)}'][lon='#{format('%<lon>.7f', :lon => n.lon)}']", 1
162 def test_show_full_json
163 way = create(:way_with_nodes, :nodes_count => 3)
165 get api_way_path(way, :full => true, :format => "json")
167 assert_response :success
169 # Check the way is correctly returned
170 js = ActiveSupport::JSON.decode(@response.body)
172 assert_equal 4, js["elements"].count
173 js_ways = js["elements"].filter { |e| e["type"] == "way" }
174 assert_equal 1, js_ways.count
175 assert_equal way.id, js_ways[0]["id"]
176 assert_equal 1, js_ways[0]["version"]
178 # check that each node in the way appears once in the output as a
179 # reference and as the node element.
180 js_nodes = js["elements"].filter { |e| e["type"] == "node" }
181 assert_equal 3, js_nodes.count
183 way.nodes.each_with_index do |n, i|
184 assert_equal n.id, js_ways[0]["nodes"][i]
185 js_nodes_with_id = js_nodes.filter { |e| e["id"] == n.id }
186 assert_equal 1, js_nodes_with_id.count
187 assert_equal n.id, js_nodes_with_id[0]["id"]
188 assert_equal 1, js_nodes_with_id[0]["version"]
189 assert_equal n.lat, js_nodes_with_id[0]["lat"]
190 assert_equal n.lon, js_nodes_with_id[0]["lon"]
194 def test_show_full_deleted
195 way = create(:way, :deleted)
197 get api_way_path(way, :full => true)
199 assert_response :gone
202 # -------------------------------------
203 # Test creating ways.
204 # -------------------------------------
206 def test_create_by_private_user
207 node1 = create(:node)
208 node2 = create(:node)
210 with_unchanging_request([:data_public => false]) do |headers, changeset|
213 <way changeset='#{changeset.id}'>
214 <nd ref='#{node1.id}'/>
215 <nd ref='#{node2.id}'/>
216 <tag k='test' v='yes' />
221 post api_ways_path, :params => osm, :headers => headers
223 assert_response :forbidden, "way upload did not return forbidden status"
228 node1 = create(:node)
229 node2 = create(:node)
231 with_request do |headers, changeset|
232 assert_difference "Way.count" => 1,
233 "WayNode.count" => 2 do
236 <way changeset='#{changeset.id}'>
237 <nd ref='#{node1.id}'/>
238 <nd ref='#{node2.id}'/>
239 <tag k='test' v='yes' />
244 post api_ways_path, :params => osm, :headers => headers
246 assert_response :success, "way upload did not return success status"
249 created_way_id = @response.body
250 way = Way.find(created_way_id)
251 assert_equal [node1, node2], way.nodes
252 assert_equal changeset.id, way.changeset_id, "saved way does not belong to the correct changeset"
253 assert way.visible, "saved way is not visible"
256 assert_equal 1, changeset.num_changes
257 assert_predicate changeset, :num_type_changes_in_sync?
258 assert_equal 1, changeset.num_created_ways
262 def test_create_in_missing_changeset
263 node1 = create(:node)
264 node2 = create(:node)
266 with_unchanging_request do |headers|
270 <nd ref='#{node1.id}'/>
271 <nd ref='#{node2.id}'/>
276 post api_ways_path, :params => osm, :headers => headers
278 assert_response :conflict
282 def test_create_with_missing_node_by_private_user
283 with_unchanging_request([:data_public => false]) do |headers, changeset|
286 <way changeset='#{changeset.id}'>
292 post api_ways_path, :params => osm, :headers => headers
294 assert_response :forbidden, "way upload with invalid node using a private user did not return 'forbidden'"
298 def test_create_without_nodes_by_private_user
299 with_unchanging_request([:data_public => false]) do |headers, changeset|
302 <way changeset='#{changeset.id}' />
306 post api_ways_path, :params => osm, :headers => headers
308 assert_response :forbidden, "way upload with no node using a private user did not return 'forbidden'"
312 def test_create_in_closed_changeset_by_private_user
315 with_unchanging_request([:data_public => false]) do |headers, changeset|
318 <way changeset='#{changeset.id}'>
319 <nd ref='#{node.id}'/>
324 post api_ways_path, :params => osm, :headers => headers
326 assert_response :forbidden, "way upload to closed changeset with a private user did not return 'forbidden'"
330 def test_create_with_missing_node
331 with_unchanging_request do |headers, changeset|
334 <way changeset='#{changeset.id}'>
340 post api_ways_path, :params => osm, :headers => headers
342 assert_response :precondition_failed, "way upload with invalid node did not return 'precondition failed'"
343 assert_equal "Precondition failed: Way requires the nodes with id in (0), which either do not exist, or are not visible.", @response.body
347 def test_create_without_nodes
348 with_unchanging_request do |headers, changeset|
351 <way changeset='#{changeset.id}' />
355 post api_ways_path, :params => osm, :headers => headers
357 assert_response :precondition_failed, "way upload with no node did not return 'precondition failed'"
358 assert_equal "Precondition failed: Cannot create way: data is invalid.", @response.body
362 def test_create_in_closed_changeset
365 with_unchanging_request([], [:closed]) do |headers, changeset|
368 <way changeset='#{changeset.id}'>
369 <nd ref='#{node.id}'/>
374 post api_ways_path, :params => osm, :headers => headers
376 assert_response :conflict, "way upload to closed changeset did not return 'conflict'"
380 def test_create_with_tag_too_long
383 with_unchanging_request do |headers, changeset|
386 <way changeset='#{changeset.id}'>
387 <nd ref='#{node.id}'/>
388 <tag k='foo' v='#{'x' * 256}'/>
393 post api_ways_path, :params => osm, :headers => headers
395 assert_response :bad_request, "way upload to with too long tag did not return 'bad_request'"
399 def test_create_with_duplicate_tags_by_private_user
402 with_unchanging_request([:data_public => false]) do |headers, changeset|
405 <way changeset='#{changeset.id}'>
406 <nd ref='#{node.id}'/>
407 <tag k='addr:housenumber' v='1'/>
408 <tag k='addr:housenumber' v='2'/>
413 post api_ways_path, :params => osm, :headers => headers
415 assert_response :forbidden, "adding new duplicate tags to a way with a non-public user should fail with 'forbidden'"
419 def test_create_with_duplicate_tags
422 with_unchanging_request do |headers, changeset|
425 <way changeset='#{changeset.id}'>
426 <nd ref='#{node.id}'/>
427 <tag k='addr:housenumber' v='1'/>
428 <tag k='addr:housenumber' v='2'/>
433 post api_ways_path, :params => osm, :headers => headers
435 assert_response :bad_request, "adding new duplicate tags to a way should fail with 'bad request'"
436 assert_equal "Element way/ has duplicate tags with key addr:housenumber", @response.body
440 def test_create_race_condition
442 changeset = create(:changeset, :user => user)
444 auth_header = bearer_authorization_header user
446 concurrency_level = 16
448 threads = Array.new(concurrency_level) do
452 <way changeset='#{changeset.id}'>
453 <nd ref='#{node.id}'/>
457 post path, :params => osm, :headers => auth_header
463 assert_equal concurrency_level, changeset.num_changes
464 assert_predicate changeset, :num_type_changes_in_sync?
465 assert_equal concurrency_level, changeset.num_created_ways
468 # -------------------------------------
469 # Test deleting ways.
470 # -------------------------------------
472 def test_destroy_when_unauthorized
473 with_unchanging(:way) do |way|
474 delete api_way_path(way)
476 assert_response :unauthorized
480 def test_destroy_without_payload_by_private_user
481 with_unchanging(:way) do |way|
482 with_unchanging_request([:data_public => false]) do |headers|
483 delete api_way_path(way), :headers => headers
485 assert_response :forbidden
490 def test_destroy_without_changeset_id_by_private_user
491 with_unchanging(:way) do |way|
492 with_unchanging_request([:data_public => false]) do |headers|
493 osm = "<osm><way id='#{way.id}'/></osm>"
495 delete api_way_path(way), :params => osm, :headers => headers
497 assert_response :forbidden
502 def test_destroy_in_closed_changeset_by_private_user
503 with_unchanging(:way) do |way|
504 with_unchanging_request([:data_public => false], [:closed]) do |headers, changeset|
505 osm_xml = xml_for_way way
506 osm_xml = update_changeset osm_xml, changeset.id
508 delete api_way_path(way), :params => osm_xml.to_s, :headers => headers
510 assert_response :forbidden
515 def test_destroy_in_missing_changeset_by_private_user
516 with_unchanging(:way) do |way|
517 with_unchanging_request([:data_public => false]) do |headers|
518 osm_xml = xml_for_way way
519 osm_xml = update_changeset osm_xml, 0
521 delete api_way_path(way), :params => osm_xml.to_s, :headers => headers
523 assert_response :forbidden
528 def test_destroy_by_private_user
529 with_unchanging(:way) do |way|
530 with_unchanging_request([:data_public => false]) do |headers, changeset|
531 osm_xml = xml_for_way way
532 osm_xml = update_changeset osm_xml, changeset.id
534 delete api_way_path(way), :params => osm_xml.to_s, :headers => headers
536 assert_response :forbidden
541 def test_destroy_deleted_way_by_private_user
542 with_unchanging(:way, :deleted) do |way|
543 with_unchanging_request([:data_public => false]) do |headers, changeset|
544 osm_xml = xml_for_way way
545 osm_xml = update_changeset osm_xml, changeset.id
547 delete api_way_path(way), :params => osm_xml.to_s, :headers => headers
549 assert_response :forbidden
554 def test_destroy_way_in_relation_by_private_user
555 with_unchanging(:way) do |way|
556 create(:relation_member, :member => way)
558 with_unchanging_request([:data_public => false]) do |headers, changeset|
559 osm_xml = xml_for_way way
560 osm_xml = update_changeset osm_xml, changeset.id
562 delete api_way_path(way), :params => osm_xml.to_s, :headers => headers
564 assert_response :forbidden, "shouldn't be able to delete a way used in a relation (#{@response.body}), when done by a private user"
569 def test_destroy_missing_way_by_private_user
570 with_unchanging_request([:data_public => false]) do |headers|
571 delete api_way_path(0), :headers => headers
573 assert_response :forbidden
577 def test_destroy_without_payload
578 with_unchanging(:way) do |way|
579 with_unchanging_request do |headers|
580 delete api_way_path(way), :headers => headers
582 assert_response :bad_request
587 def test_destroy_without_changeset_id
588 with_unchanging(:way) do |way|
589 with_unchanging_request do |headers|
590 osm = "<osm><way id='#{way.id}'/></osm>"
592 delete api_way_path(way), :params => osm, :headers => headers
594 assert_response :bad_request
599 def test_destroy_in_closed_changeset
600 with_unchanging(:way) do |way|
601 with_unchanging_request([], [:closed]) do |headers, changeset|
602 osm_xml = xml_for_way way
603 osm_xml = update_changeset osm_xml, changeset.id
605 delete api_way_path(way), :params => osm_xml.to_s, :headers => headers
607 assert_response :conflict
612 def test_destroy_in_missing_changeset
613 with_unchanging(:way) do |way|
614 with_unchanging_request do |headers|
615 osm_xml = xml_for_way way
616 osm_xml = update_changeset osm_xml, 0
618 delete api_way_path(way), :params => osm_xml.to_s, :headers => headers
620 assert_response :conflict
628 with_request do |headers, changeset|
629 osm_xml = xml_for_way way
630 osm_xml = update_changeset osm_xml, changeset.id
632 delete api_way_path(way), :params => osm_xml.to_s, :headers => headers
634 assert_response :success
636 response_way_version = @response.body.to_i
637 assert_operator response_way_version, :>, way.version, "delete request should return a new version number for way"
639 assert_not_predicate way, :visible?
640 assert_equal response_way_version, way.version
643 assert_equal 1, changeset.num_changes
644 assert_predicate changeset, :num_type_changes_in_sync?
645 assert_equal 1, changeset.num_deleted_ways
649 def test_destroy_deleted_way
650 with_unchanging(:way, :deleted) do |way|
651 with_unchanging_request do |headers, changeset|
652 osm_xml = xml_for_way way
653 osm_xml = update_changeset osm_xml, changeset.id
655 delete api_way_path(way), :params => osm_xml.to_s, :headers => headers
657 assert_response :gone
662 def test_destroy_way_in_relation
663 with_unchanging(:way) do |way|
664 relation_member = create(:relation_member, :member => way)
666 with_unchanging_request do |headers, changeset|
667 osm_xml = xml_for_way way
668 osm_xml = update_changeset osm_xml, changeset.id
670 delete api_way_path(way), :params => osm_xml.to_s, :headers => headers
672 assert_response :precondition_failed, "shouldn't be able to delete a way used in a relation (#{@response.body})"
673 assert_equal "Precondition failed: Way #{way.id} is still used by relations #{relation_member.relation.id}.", @response.body
678 def test_destroy_missing_way_with_payload
679 with_unchanging(:way) do |way|
680 with_unchanging_request do |headers, changeset|
681 osm_xml = xml_for_way way
682 osm_xml = update_changeset osm_xml, changeset.id
684 delete api_way_path(0), :params => osm_xml.to_s, :headers => headers
686 assert_response :not_found
691 # -------------------------------------
692 # Test updating ways.
693 # -------------------------------------
695 def test_update_when_unauthorized
696 with_unchanging(:way_with_nodes) do |way|
697 osm_xml = xml_for_way way
699 put api_way_path(way), :params => osm_xml.to_s
701 assert_response :unauthorized
705 def test_update_in_changeset_of_other_user_by_private_user
706 with_unchanging(:way_with_nodes) do |way|
707 other_user = create(:user)
709 with_unchanging_request([:data_public => false], [:user => other_user]) do |headers, changeset|
710 osm_xml = xml_for_way way
711 osm_xml = update_changeset osm_xml, changeset.id
713 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
715 assert_require_public_data "update with other user's changeset should be forbidden when date isn't public"
720 def test_update_in_closed_changeset_by_private_user
721 with_unchanging(:way_with_nodes) do |way|
722 with_unchanging_request([:data_public => false], [:closed]) do |headers, changeset|
723 osm_xml = xml_for_way way
724 osm_xml = update_changeset osm_xml, changeset.id
726 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
728 assert_require_public_data "update with closed changeset should be forbidden, when data isn't public"
733 def test_update_in_missing_changeset_by_private_user
734 with_unchanging(:way_with_nodes) do |way|
735 with_unchanging_request([:data_public => false]) do |headers|
736 osm_xml = xml_for_way way
737 osm_xml = update_changeset osm_xml, 0
739 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
741 assert_require_public_data "update with changeset=0 should be forbidden, when data isn't public"
746 def test_update_with_missing_node_by_private_user
747 with_unchanging(:way) do |way|
749 create(:way_node, :way => way, :node => node)
751 with_unchanging_request([:data_public => false]) do |headers, changeset|
752 osm_xml = xml_for_way way
753 osm_xml = xml_replace_node osm_xml, node.id, 9999
754 osm_xml = update_changeset osm_xml, changeset.id
756 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
758 assert_require_public_data "way with non-existent node should be forbidden, when data isn't public"
763 def test_update_with_deleted_node_by_private_user
764 with_unchanging(:way) do |way|
766 deleted_node = create(:node, :deleted)
767 create(:way_node, :way => way, :node => node)
769 with_unchanging_request([:data_public => false]) do |headers, changeset|
770 osm_xml = xml_for_way way
771 osm_xml = xml_replace_node osm_xml, node.id, deleted_node.id
772 osm_xml = update_changeset osm_xml, changeset.id
774 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
776 assert_require_public_data "way with deleted node should be forbidden, when data isn't public"
781 def test_update_by_private_user
782 with_unchanging(:way_with_nodes) do |way|
783 with_unchanging_request([:data_public => false]) do |headers, changeset|
784 osm_xml = xml_for_way way
785 osm_xml = update_changeset osm_xml, changeset.id
787 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
789 assert_require_public_data "should have failed with a forbidden when data isn't public"
794 def test_update_in_changeset_of_other_user
795 with_unchanging(:way_with_nodes) do |way|
796 other_user = create(:user)
798 with_unchanging_request([], [:user => other_user]) do |headers, changeset|
799 osm_xml = xml_for_way way
800 osm_xml = update_changeset osm_xml, changeset.id
802 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
804 assert_response :conflict, "update with other user's changeset should be rejected"
809 def test_update_in_closed_changeset
810 with_unchanging(:way_with_nodes) do |way|
811 with_unchanging_request([], [:closed]) do |headers, changeset|
812 osm_xml = xml_for_way way
813 osm_xml = update_changeset osm_xml, changeset.id
815 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
817 assert_response :conflict, "update with closed changeset should be rejected"
822 def test_update_in_missing_changeset
823 with_unchanging(:way_with_nodes) do |way|
824 with_unchanging_request do |headers|
825 osm_xml = xml_for_way way
826 osm_xml = update_changeset osm_xml, 0
828 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
830 assert_response :conflict, "update with changeset=0 should be rejected"
835 def test_update_with_missing_node
836 with_unchanging(:way) do |way|
838 create(:way_node, :way => way, :node => node)
840 with_unchanging_request do |headers, changeset|
841 osm_xml = xml_for_way way
842 osm_xml = xml_replace_node osm_xml, node.id, 9999
843 osm_xml = update_changeset osm_xml, changeset.id
845 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
847 assert_response :precondition_failed, "way with non-existent node should be rejected"
852 def test_update_with_deleted_node
853 with_unchanging(:way) do |way|
855 deleted_node = create(:node, :deleted)
856 create(:way_node, :way => way, :node => node)
858 with_unchanging_request do |headers, changeset|
859 osm_xml = xml_for_way way
860 osm_xml = xml_replace_node osm_xml, node.id, deleted_node.id
861 osm_xml = update_changeset osm_xml, changeset.id
863 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
865 assert_response :precondition_failed, "way with deleted node should be rejected"
870 def test_update_with_version_behind
871 with_unchanging(:way_with_nodes, :version => 2) do |way|
872 with_unchanging_request do |headers, changeset|
873 osm_xml = xml_for_way way
874 osm_xml = xml_attr_rewrite osm_xml, "version", way.version - 1
875 osm_xml = update_changeset osm_xml, changeset.id
877 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
879 assert_response :conflict, "should have failed on old version number"
884 def test_update_with_version_ahead
885 with_unchanging(:way_with_nodes, :version => 2) do |way|
886 with_unchanging_request do |headers, changeset|
887 osm_xml = xml_for_way way
888 osm_xml = xml_attr_rewrite osm_xml, "version", way.version + 1
889 osm_xml = update_changeset osm_xml, changeset.id
891 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
893 assert_response :conflict, "should have failed on skipped version number"
898 def test_update_with_invalid_version
899 with_unchanging(:way_with_nodes) do |way|
900 with_unchanging_request do |headers, changeset|
901 osm_xml = xml_for_way way
902 osm_xml = xml_attr_rewrite osm_xml, "version", "p1r4t3s!"
903 osm_xml = update_changeset osm_xml, changeset.id
905 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
907 assert_response :conflict, "should not be able to put 'p1r4at3s!' in the version field"
912 def test_update_other_way
913 with_unchanging(:way_with_nodes) do |way|
914 with_unchanging(:way_with_nodes) do |other_way|
915 with_unchanging_request do |headers, changeset|
916 osm_xml = xml_for_way other_way
917 osm_xml = update_changeset osm_xml, changeset.id
919 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
921 assert_response :bad_request, "should not be able to update a way with a different ID from the XML"
927 def test_update_with_invalid_osm_structure
928 with_unchanging(:way_with_nodes) do |way|
929 with_unchanging_request do |headers|
932 put api_way_path(way), :params => osm, :headers => headers
934 assert_response :bad_request, "should not be able to update a way with non-OSM XML doc."
940 way = create(:way_with_nodes)
942 with_request do |headers, changeset|
943 osm_xml = xml_for_way way
944 osm_xml = update_changeset osm_xml, changeset.id
946 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
948 assert_response :success, "a valid update request failed"
951 assert_equal 1, changeset.num_changes
952 assert_predicate changeset, :num_type_changes_in_sync?
953 assert_equal 1, changeset.num_modified_ways
957 def test_update_with_new_tags_by_private_user
958 with_unchanging(:way_with_nodes, :nodes_count => 2) do |way|
959 with_unchanging_request([:data_public => false]) do |headers, changeset|
960 tag_xml = XML::Node.new("tag")
964 osm_xml = xml_for_way way
965 osm_xml.find("//osm/way").first << tag_xml
966 osm_xml = update_changeset osm_xml, changeset.id
968 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
970 assert_response :forbidden, "adding a tag to a way for a non-public should fail with 'forbidden'"
975 def test_update_with_new_tags
976 way = create(:way_with_nodes, :nodes_count => 2)
978 with_request do |headers, changeset|
979 tag_xml = XML::Node.new("tag")
983 osm_xml = xml_for_way way
984 osm_xml.find("//osm/way").first << tag_xml
985 osm_xml = update_changeset osm_xml, changeset.id
987 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
989 assert_response :success, "adding a new tag to a way should succeed"
990 assert_equal way.version + 1, @response.body.to_i
993 assert_equal 1, changeset.num_changes
994 assert_predicate changeset, :num_type_changes_in_sync?
995 assert_equal 1, changeset.num_modified_ways
999 def test_update_with_duplicated_existing_tags_by_private_user
1000 with_unchanging(:way_with_nodes) do |way|
1001 create(:way_tag, :way => way, :k => "key_to_duplicate", :v => "value_to_duplicate")
1003 with_unchanging_request([:data_public => false]) do |headers, changeset|
1004 tag_xml = XML::Node.new("tag")
1005 tag_xml["k"] = "key_to_duplicate"
1006 tag_xml["v"] = "value_to_duplicate"
1008 osm_xml = xml_for_way way
1009 osm_xml.find("//osm/way").first << tag_xml
1010 osm_xml = update_changeset osm_xml, changeset.id
1012 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
1014 assert_response :forbidden, "adding a duplicate tag to a way for a non-public should fail with 'forbidden'"
1019 def test_update_with_duplicated_existing_tags
1020 with_unchanging(:way_with_nodes) do |way|
1021 create(:way_tag, :way => way, :k => "key_to_duplicate", :v => "value_to_duplicate")
1023 with_unchanging_request do |headers, changeset|
1024 tag_xml = XML::Node.new("tag")
1025 tag_xml["k"] = "key_to_duplicate"
1026 tag_xml["v"] = "value_to_duplicate"
1028 osm_xml = xml_for_way way
1029 osm_xml.find("//osm/way").first << tag_xml
1030 osm_xml = update_changeset osm_xml, changeset.id
1032 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
1034 assert_response :bad_request, "adding a duplicate tag to a way should fail with 'bad request'"
1035 assert_equal "Element way/#{way.id} has duplicate tags with key key_to_duplicate", @response.body
1040 def test_update_with_new_duplicate_tags_by_private_user
1041 with_unchanging(:way_with_nodes) do |way|
1042 with_unchanging_request([:data_public => false]) do |headers, changeset|
1043 tag_xml = XML::Node.new("tag")
1044 tag_xml["k"] = "i_am_a_duplicate"
1045 tag_xml["v"] = "foobar"
1047 osm_xml = xml_for_way way
1048 osm_xml.find("//osm/way").first << tag_xml.copy(true) << tag_xml
1049 osm_xml = update_changeset osm_xml, changeset.id
1051 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
1053 assert_response :forbidden, "adding new duplicate tags to a way using a non-public user should fail with 'forbidden'"
1058 def test_update_with_new_duplicate_tags
1059 with_unchanging(:way_with_nodes) do |way|
1060 with_unchanging_request do |headers, changeset|
1061 tag_xml = XML::Node.new("tag")
1062 tag_xml["k"] = "i_am_a_duplicate"
1063 tag_xml["v"] = "foobar"
1065 osm_xml = xml_for_way way
1066 osm_xml.find("//osm/way").first << tag_xml.copy(true) << tag_xml
1067 osm_xml = update_changeset osm_xml, changeset.id
1069 put api_way_path(way), :params => osm_xml.to_s, :headers => headers
1071 assert_response :bad_request, "adding new duplicate tags to a way should fail with 'bad request'"
1072 assert_equal "Element way/#{way.id} has duplicate tags with key i_am_a_duplicate", @response.body
1078 # test initial rate limit
1079 def test_initial_rate_limit
1081 user = create(:user)
1084 node1 = create(:node)
1085 node2 = create(:node)
1087 # create a changeset that puts us near the initial rate limit
1088 changeset = create(:changeset, :user => user,
1089 :created_at => Time.now.utc - 5.minutes,
1090 :num_changes => Settings.initial_changes_per_hour - 1)
1092 # create authentication header
1093 auth_header = bearer_authorization_header user
1095 # try creating a way
1098 <way changeset='#{changeset.id}'>
1099 <nd ref='#{node1.id}'/>
1100 <nd ref='#{node2.id}'/>
1104 post api_ways_path, :params => xml, :headers => auth_header
1105 assert_response :success, "way create did not return success status"
1107 # get the id of the way we created
1108 wayid = @response.body
1110 # try updating the way, which should be rate limited
1113 <way id='#{wayid}' version='1' changeset='#{changeset.id}'>
1114 <nd ref='#{node2.id}'/>
1115 <nd ref='#{node1.id}'/>
1119 put api_way_path(wayid), :params => xml, :headers => auth_header
1120 assert_response :too_many_requests, "way update did not hit rate limit"
1122 # try deleting the way, which should be rate limited
1123 xml = "<osm><way id='#{wayid}' version='2' changeset='#{changeset.id}'/></osm>"
1124 delete api_way_path(wayid), :params => xml, :headers => auth_header
1125 assert_response :too_many_requests, "way delete did not hit rate limit"
1127 # try creating a way, which should be rate limited
1130 <way changeset='#{changeset.id}'>
1131 <nd ref='#{node1.id}'/>
1132 <nd ref='#{node2.id}'/>
1136 post api_ways_path, :params => xml, :headers => auth_header
1137 assert_response :too_many_requests, "way create did not hit rate limit"
1141 # test maximum rate limit
1142 def test_maximum_rate_limit
1144 user = create(:user)
1147 node1 = create(:node)
1148 node2 = create(:node)
1150 # create a changeset to establish our initial edit time
1151 changeset = create(:changeset, :user => user,
1152 :created_at => Time.now.utc - 28.days)
1154 # create changeset to put us near the maximum rate limit
1155 total_changes = Settings.max_changes_per_hour - 1
1156 while total_changes.positive?
1157 changes = [total_changes, Changeset::MAX_ELEMENTS].min
1158 changeset = create(:changeset, :user => user,
1159 :created_at => Time.now.utc - 5.minutes,
1160 :num_changes => changes)
1161 total_changes -= changes
1164 # create authentication header
1165 auth_header = bearer_authorization_header user
1167 # try creating a way
1170 <way changeset='#{changeset.id}'>
1171 <nd ref='#{node1.id}'/>
1172 <nd ref='#{node2.id}'/>
1176 post api_ways_path, :params => xml, :headers => auth_header
1177 assert_response :success, "way create did not return success status"
1179 # get the id of the way we created
1180 wayid = @response.body
1182 # try updating the way, which should be rate limited
1185 <way id='#{wayid}' version='1' changeset='#{changeset.id}'>
1186 <nd ref='#{node2.id}'/>
1187 <nd ref='#{node1.id}'/>
1191 put api_way_path(wayid), :params => xml, :headers => auth_header
1192 assert_response :too_many_requests, "way update did not hit rate limit"
1194 # try deleting the way, which should be rate limited
1195 xml = "<osm><way id='#{wayid}' version='2' changeset='#{changeset.id}'/></osm>"
1196 delete api_way_path(wayid), :params => xml, :headers => auth_header
1197 assert_response :too_many_requests, "way delete did not hit rate limit"
1199 # try creating a way, which should be rate limited
1202 <way changeset='#{changeset.id}'>
1203 <nd ref='#{node1.id}'/>
1204 <nd ref='#{node2.id}'/>
1208 post api_ways_path, :params => xml, :headers => auth_header
1209 assert_response :too_many_requests, "way create did not hit rate limit"
1215 [Way, WayNode, WayTag,
1216 OldWay, OldWayNode, OldWayTag]
1220 # update an attribute in the way element
1221 def xml_attr_rewrite(xml, name, value)
1222 xml.find("//osm/way").first[name] = value.to_s
1227 # replace a node in a way element
1228 def xml_replace_node(xml, old_node, new_node)
1229 xml.find("//osm/way/nd[@ref='#{old_node}']").first["ref"] = new_node.to_s