1 require File.dirname(__FILE__) + '/../test_helper'
2 require 'changeset_controller'
4 class ChangesetControllerTest < ActionController::TestCase
8 # test all routes which lead to this controller
11 { :path => "/api/0.6/changeset/create", :method => :put },
12 { :controller => "changeset", :action => "create" }
15 { :path => "/api/0.6/changeset/1/upload", :method => :post },
16 { :controller => "changeset", :action => "upload", :id => "1" }
19 { :path => "/api/0.6/changeset/1/download", :method => :get },
20 { :controller => "changeset", :action => "download", :id => "1" }
23 { :path => "/api/0.6/changeset/1/expand_bbox", :method => :post },
24 { :controller => "changeset", :action => "expand_bbox", :id => "1" }
27 { :path => "/api/0.6/changeset/1", :method => :get },
28 { :controller => "changeset", :action => "read", :id => "1" }
31 { :path => "/api/0.6/changeset/1", :method => :put },
32 { :controller => "changeset", :action => "update", :id => "1" }
35 { :path => "/api/0.6/changeset/1/close", :method => :put },
36 { :controller => "changeset", :action => "close", :id => "1" }
39 { :path => "/api/0.6/changesets", :method => :get },
40 { :controller => "changeset", :action => "query" }
43 { :path => "/user/name/edits", :method => :get },
44 { :controller => "changeset", :action => "list", :display_name => "name" }
47 { :path => "/user/name/edits/feed", :method => :get },
48 { :controller => "changeset", :action => "feed", :display_name => "name", :format => :atom }
51 { :path => "/browse/friends", :method => :get },
52 { :controller => "changeset", :action => "list", :friends => true }
55 { :path => "/browse/nearby", :method => :get },
56 { :controller => "changeset", :action => "list", :nearby => true }
59 { :path => "/browse/changesets", :method => :get },
60 { :controller => "changeset", :action => "list" }
63 { :path => "/browse/changesets/feed", :method => :get },
64 { :controller => "changeset", :action => "feed", :format => :atom }
67 { :controller => "changeset", :action => "list" },
68 { :path => "/browse", :method => :get }
71 { :controller => "changeset", :action => "list" },
72 { :path => "/history", :method => :get }
75 { :controller => "changeset", :action => "feed", :format => :atom },
76 { :path => "/history/feed", :method => :get }
80 # -----------------------
81 # Test simple changeset creation
82 # -----------------------
85 basic_authorization users(:normal_user).email, "test"
86 # Create the first user's changeset
87 content "<osm><changeset>" +
88 "<tag k='created_by' v='osm test suite checking changesets'/>" +
91 assert_require_public_data
94 basic_authorization users(:public_user).email, "test"
95 # Create the first user's changeset
96 content "<osm><changeset>" +
97 "<tag k='created_by' v='osm test suite checking changesets'/>" +
101 assert_response :success, "Creation of changeset did not return sucess status"
102 newid = @response.body.to_i
104 # check end time, should be an hour ahead of creation time
105 cs = Changeset.find(newid)
106 duration = cs.closed_at - cs.created_at
107 # the difference can either be a rational, or a floating point number
108 # of seconds, depending on the code path taken :-(
109 if duration.class == Rational
110 assert_equal Rational(1,24), duration , "initial idle timeout should be an hour (#{cs.created_at} -> #{cs.closed_at})"
112 # must be number of seconds...
113 assert_equal 3600, duration.round, "initial idle timeout should be an hour (#{cs.created_at} -> #{cs.closed_at})"
117 def test_create_invalid
118 basic_authorization users(:normal_user).email, "test"
119 content "<osm><changeset></osm>"
121 assert_require_public_data
123 ## Try the public user
124 basic_authorization users(:public_user).email, "test"
125 content "<osm><changeset></osm>"
127 assert_response :bad_request, "creating a invalid changeset should fail"
130 def test_create_invalid_no_content
131 ## First check with no auth
133 assert_response :unauthorized, "shouldn't be able to create a changeset with no auth"
135 ## Now try to with the non-public user
136 basic_authorization users(:normal_user).email, "test"
138 assert_require_public_data
140 ## Try the inactive user
141 basic_authorization users(:inactive_user).email, "test"
145 ## Now try to use the public user
146 basic_authorization users(:public_user).email, "test"
148 assert_response :bad_request, "creating a changeset with no content should fail"
151 def test_create_wrong_method
152 basic_authorization users(:public_user).email, "test"
154 assert_response :method_not_allowed
156 assert_response :method_not_allowed
160 # check that the changeset can be read and returns the correct
161 # document structure.
163 changeset_id = changesets(:normal_user_first_change).id
164 get :read, :id => changeset_id
165 assert_response :success, "cannot get first changeset"
167 assert_select "osm[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
168 assert_select "osm>changeset[id=#{changeset_id}]", 1
172 # check that a changeset that doesn't exist returns an appropriate message
173 def test_read_not_found
174 [0, -32, 233455644, "afg", "213"].each do |id|
177 assert_response :not_found, "should get a not found"
178 rescue ActionController::RoutingError => ex
179 assert_match /No route matches/, ex.to_s
185 # test that the user who opened a change can close it
187 ## Try without authentication
188 put :close, :id => changesets(:public_user_first_change).id
189 assert_response :unauthorized
192 ## Try using the non-public user
193 basic_authorization users(:normal_user).email, "test"
194 put :close, :id => changesets(:normal_user_first_change).id
195 assert_require_public_data
198 ## The try with the public user
199 basic_authorization users(:public_user).email, "test"
201 cs_id = changesets(:public_user_first_change).id
202 put :close, :id => cs_id
203 assert_response :success
205 # test that it really is closed now
206 cs = Changeset.find(cs_id)
208 "changeset should be closed now (#{cs.closed_at} > #{Time.now.getutc}.")
212 # test that a different user can't close another user's changeset
213 def test_close_invalid
214 basic_authorization users(:public_user).email, "test"
216 put :close, :id => changesets(:normal_user_first_change).id
217 assert_response :conflict
218 assert_equal "The user doesn't own that changeset", @response.body
222 # test that you can't close using another method
223 def test_close_method_invalid
224 basic_authorization users(:public_user).email, "test"
226 cs_id = changesets(:public_user_first_change).id
227 get :close, :id => cs_id
228 assert_response :method_not_allowed
230 post :close, :id => cs_id
231 assert_response :method_not_allowed
235 # check that you can't close a changeset that isn't found
236 def test_close_not_found
237 cs_ids = [0, -132, "123"]
239 # First try to do it with no auth
242 put :close, :id => id
243 assert_response :unauthorized, "Shouldn't be able close the non-existant changeset #{id}, when not authorized"
244 rescue ActionController::RoutingError => ex
245 assert_match /No route matches/, ex.to_s
250 basic_authorization users(:public_user).email, "test"
253 put :close, :id => id
254 assert_response :not_found, "The changeset #{id} doesn't exist, so can't be closed"
255 rescue ActionController::RoutingError => ex
256 assert_match /No route matches/, ex.to_s
262 # upload something simple, but valid and check that it can
264 # Also try without auth and another user.
265 def test_upload_simple_valid
267 changeset_id = changesets(:public_user_first_change).id
269 # simple diff to change a node, way and relation by removing
274 <node id='1' lon='0' lat='0' changeset='#{changeset_id}' version='1'/>
275 <way id='1' changeset='#{changeset_id}' version='1'>
280 <relation id='1' changeset='#{changeset_id}' version='1'>
281 <member type='way' role='some' ref='3'/>
282 <member type='node' role='some' ref='5'/>
283 <member type='relation' role='some' ref='3'/>
291 post :upload, :id => changeset_id
292 assert_response :unauthorized,
293 "shouldnn't be able to upload a simple valid diff to changeset: #{@response.body}"
297 ## Now try with a private user
298 basic_authorization users(:normal_user).email, "test"
299 changeset_id = changesets(:normal_user_first_change).id
301 # simple diff to change a node, way and relation by removing
306 <node id='1' lon='0' lat='0' changeset='#{changeset_id}' version='1'/>
307 <way id='1' changeset='#{changeset_id}' version='1'>
312 <relation id='1' changeset='#{changeset_id}' version='1'>
313 <member type='way' role='some' ref='3'/>
314 <member type='node' role='some' ref='5'/>
315 <member type='relation' role='some' ref='3'/>
323 post :upload, :id => changeset_id
324 assert_response :forbidden,
325 "can't upload a simple valid diff to changeset: #{@response.body}"
329 ## Now try with the public user
330 basic_authorization users(:public_user).email, "test"
331 changeset_id = changesets(:public_user_first_change).id
333 # simple diff to change a node, way and relation by removing
338 <node id='1' lon='0' lat='0' changeset='#{changeset_id}' version='1'/>
339 <way id='1' changeset='#{changeset_id}' version='1'>
344 <relation id='1' changeset='#{changeset_id}' version='1'>
345 <member type='way' role='some' ref='3'/>
346 <member type='node' role='some' ref='5'/>
347 <member type='relation' role='some' ref='3'/>
355 post :upload, :id => changeset_id
356 assert_response :success,
357 "can't upload a simple valid diff to changeset: #{@response.body}"
359 # check that the changes made it into the database
360 assert_equal 0, Node.find(1).tags.size, "node 1 should now have no tags"
361 assert_equal 0, Way.find(1).tags.size, "way 1 should now have no tags"
362 assert_equal 0, Relation.find(1).tags.size, "relation 1 should now have no tags"
366 # upload something which creates new objects using placeholders
367 def test_upload_create_valid
368 basic_authorization users(:public_user).email, "test"
369 cs_id = changesets(:public_user_first_change).id
371 # simple diff to create a node way and relation using placeholders
375 <node id='-1' lon='0' lat='0' changeset='#{cs_id}'>
376 <tag k='foo' v='bar'/>
377 <tag k='baz' v='bat'/>
379 <way id='-1' changeset='#{cs_id}'>
384 <relation id='-1' changeset='#{cs_id}'>
385 <member type='way' role='some' ref='3'/>
386 <member type='node' role='some' ref='5'/>
387 <member type='relation' role='some' ref='3'/>
395 post :upload, :id => cs_id
396 assert_response :success,
397 "can't upload a simple valid creation to changeset: #{@response.body}"
399 # check the returned payload
400 assert_select "diffResult[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
401 assert_select "diffResult>node", 1
402 assert_select "diffresult>way", 1
403 assert_select "diffResult>relation", 1
405 # inspect the response to find out what the new element IDs are
406 doc = XML::Parser.string(@response.body).parse
407 new_node_id = doc.find("//diffResult/node").first["new_id"].to_i
408 new_way_id = doc.find("//diffResult/way").first["new_id"].to_i
409 new_rel_id = doc.find("//diffResult/relation").first["new_id"].to_i
411 # check the old IDs are all present and negative one
412 assert_equal -1, doc.find("//diffResult/node").first["old_id"].to_i
413 assert_equal -1, doc.find("//diffResult/way").first["old_id"].to_i
414 assert_equal -1, doc.find("//diffResult/relation").first["old_id"].to_i
416 # check the versions are present and equal one
417 assert_equal 1, doc.find("//diffResult/node").first["new_version"].to_i
418 assert_equal 1, doc.find("//diffResult/way").first["new_version"].to_i
419 assert_equal 1, doc.find("//diffResult/relation").first["new_version"].to_i
421 # check that the changes made it into the database
422 assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
423 assert_equal 0, Way.find(new_way_id).tags.size, "new way should have no tags"
424 assert_equal 0, Relation.find(new_rel_id).tags.size, "new relation should have no tags"
428 # test a complex delete where we delete elements which rely on eachother
429 # in the same transaction.
430 def test_upload_delete
431 basic_authorization users(:public_user).display_name, "test"
433 diff = XML::Document.new
434 diff.root = XML::Node.new "osmChange"
435 delete = XML::Node.new "delete"
437 delete << current_relations(:visible_relation).to_xml_node
438 delete << current_relations(:used_relation).to_xml_node
439 delete << current_ways(:used_way).to_xml_node
440 delete << current_nodes(:node_used_by_relationship).to_xml_node
442 # update the changeset to one that this user owns
443 changeset_id = changesets(:public_user_first_change).id
444 ["node", "way", "relation"].each do |type|
445 delete.find("//osmChange/delete/#{type}").each do |n|
446 n['changeset'] = changeset_id.to_s
452 post :upload, :id => changeset_id
453 assert_response :success,
454 "can't upload a deletion diff to changeset: #{@response.body}"
456 # check the response is well-formed
457 assert_select "diffResult>node", 1
458 assert_select "diffResult>way", 1
459 assert_select "diffResult>relation", 2
461 # check that everything was deleted
462 assert_equal false, Node.find(current_nodes(:node_used_by_relationship).id).visible
463 assert_equal false, Way.find(current_ways(:used_way).id).visible
464 assert_equal false, Relation.find(current_relations(:visible_relation).id).visible
465 assert_equal false, Relation.find(current_relations(:used_relation).id).visible
469 # test uploading a delete with no lat/lon, as they are optional in
470 # the osmChange spec.
471 def test_upload_nolatlon_delete
472 basic_authorization users(:public_user).display_name, "test"
474 node = current_nodes(:public_visible_node)
475 cs = changesets(:public_user_first_change)
476 diff = "<osmChange><delete><node id='#{node.id}' version='#{node.version}' changeset='#{cs.id}'/></delete></osmChange>"
480 post :upload, :id => cs.id
481 assert_response :success,
482 "can't upload a deletion diff to changeset: #{@response.body}"
484 # check the response is well-formed
485 assert_select "diffResult>node", 1
487 # check that everything was deleted
488 assert_equal false, Node.find(node.id).visible
491 def test_repeated_changeset_create
493 basic_authorization users(:public_user).email, "test"
495 # create a temporary changeset
496 content "<osm><changeset>" +
497 "<tag k='created_by' v='osm test suite checking changesets'/>" +
499 assert_difference('Changeset.count', 1) do
502 assert_response :success
503 changeset_id = @response.body.to_i
507 def test_upload_large_changeset
508 basic_authorization users(:public_user).email, "test"
511 content "<osm><changeset/></osm>"
513 assert_response :success, "Should be able to create a changeset: #{@response.body}"
514 changeset_id = @response.body.to_i
516 # upload some widely-spaced nodes, spiralling positive and negative to cause
517 # largest bbox over-expansion possible.
521 <node id='-1' lon='-20' lat='-10' changeset='#{changeset_id}'/>
522 <node id='-10' lon='20' lat='10' changeset='#{changeset_id}'/>
523 <node id='-2' lon='-40' lat='-20' changeset='#{changeset_id}'/>
524 <node id='-11' lon='40' lat='20' changeset='#{changeset_id}'/>
525 <node id='-3' lon='-60' lat='-30' changeset='#{changeset_id}'/>
526 <node id='-12' lon='60' lat='30' changeset='#{changeset_id}'/>
527 <node id='-4' lon='-80' lat='-40' changeset='#{changeset_id}'/>
528 <node id='-13' lon='80' lat='40' changeset='#{changeset_id}'/>
529 <node id='-5' lon='-100' lat='-50' changeset='#{changeset_id}'/>
530 <node id='-14' lon='100' lat='50' changeset='#{changeset_id}'/>
531 <node id='-6' lon='-120' lat='-60' changeset='#{changeset_id}'/>
532 <node id='-15' lon='120' lat='60' changeset='#{changeset_id}'/>
533 <node id='-7' lon='-140' lat='-70' changeset='#{changeset_id}'/>
534 <node id='-16' lon='140' lat='70' changeset='#{changeset_id}'/>
535 <node id='-8' lon='-160' lat='-80' changeset='#{changeset_id}'/>
536 <node id='-17' lon='160' lat='80' changeset='#{changeset_id}'/>
537 <node id='-9' lon='-179.9' lat='-89.9' changeset='#{changeset_id}'/>
538 <node id='-18' lon='179.9' lat='89.9' changeset='#{changeset_id}'/>
543 # upload it, which used to cause an error like "PGError: ERROR:
544 # integer out of range" (bug #2152). but shouldn't any more.
546 post :upload, :id => changeset_id
547 assert_response :success,
548 "can't upload a spatially-large diff to changeset: #{@response.body}"
550 # check that the changeset bbox is within bounds
551 cs = Changeset.find(changeset_id)
552 assert cs.min_lon >= -180 * SCALE, "Minimum longitude (#{cs.min_lon / SCALE}) should be >= -180 to be valid."
553 assert cs.max_lon <= 180 * SCALE, "Maximum longitude (#{cs.max_lon / SCALE}) should be <= 180 to be valid."
554 assert cs.min_lat >= -90 * SCALE, "Minimum latitude (#{cs.min_lat / SCALE}) should be >= -90 to be valid."
555 assert cs.max_lat >= 90 * SCALE, "Maximum latitude (#{cs.max_lat / SCALE}) should be <= 90 to be valid."
559 # test that deleting stuff in a transaction doesn't bypass the checks
560 # to ensure that used elements are not deleted.
561 def test_upload_delete_invalid
562 basic_authorization users(:public_user).email, "test"
564 diff = XML::Document.new
565 diff.root = XML::Node.new "osmChange"
566 delete = XML::Node.new "delete"
568 delete << current_relations(:public_visible_relation).to_xml_node
569 delete << current_ways(:used_way).to_xml_node
570 delete << current_nodes(:node_used_by_relationship).to_xml_node
574 post :upload, :id => 2
575 assert_response :precondition_failed,
576 "shouldn't be able to upload a invalid deletion diff: #{@response.body}"
577 assert_equal "Precondition failed: Way 3 is still used by relations 1.", @response.body
579 # check that nothing was, in fact, deleted
580 assert_equal true, Node.find(current_nodes(:node_used_by_relationship).id).visible
581 assert_equal true, Way.find(current_ways(:used_way).id).visible
582 assert_equal true, Relation.find(current_relations(:visible_relation).id).visible
586 # test that a conditional delete of an in use object works.
587 def test_upload_delete_if_unused
588 basic_authorization users(:public_user).email, "test"
590 diff = XML::Document.new
591 diff.root = XML::Node.new "osmChange"
592 delete = XML::Node.new "delete"
594 delete["if-unused"] = ""
595 delete << current_relations(:public_used_relation).to_xml_node
596 delete << current_ways(:used_way).to_xml_node
597 delete << current_nodes(:node_used_by_relationship).to_xml_node
601 post :upload, :id => 2
602 assert_response :success,
603 "can't do a conditional delete of in use objects: #{@response.body}"
605 # check the returned payload
606 assert_select "diffResult[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
607 assert_select "diffResult>node", 1
608 assert_select "diffresult>way", 1
609 assert_select "diffResult>relation", 1
612 doc = XML::Parser.string(@response.body).parse
614 # check the old IDs are all present and what we expect
615 assert_equal current_nodes(:node_used_by_relationship).id, doc.find("//diffResult/node").first["old_id"].to_i
616 assert_equal current_ways(:used_way).id, doc.find("//diffResult/way").first["old_id"].to_i
617 assert_equal current_relations(:public_used_relation).id, doc.find("//diffResult/relation").first["old_id"].to_i
619 # check the new IDs are all present and unchanged
620 assert_equal current_nodes(:node_used_by_relationship).id, doc.find("//diffResult/node").first["new_id"].to_i
621 assert_equal current_ways(:used_way).id, doc.find("//diffResult/way").first["new_id"].to_i
622 assert_equal current_relations(:public_used_relation).id, doc.find("//diffResult/relation").first["new_id"].to_i
624 # check the new versions are all present and unchanged
625 assert_equal current_nodes(:node_used_by_relationship).version, doc.find("//diffResult/node").first["new_version"].to_i
626 assert_equal current_ways(:used_way).version, doc.find("//diffResult/way").first["new_version"].to_i
627 assert_equal current_relations(:public_used_relation).version, doc.find("//diffResult/relation").first["new_version"].to_i
629 # check that nothing was, in fact, deleted
630 assert_equal true, Node.find(current_nodes(:node_used_by_relationship).id).visible
631 assert_equal true, Way.find(current_ways(:used_way).id).visible
632 assert_equal true, Relation.find(current_relations(:public_used_relation).id).visible
636 # upload an element with a really long tag value
637 def test_upload_invalid_too_long_tag
638 basic_authorization users(:public_user).email, "test"
639 cs_id = changesets(:public_user_first_change).id
641 # simple diff to create a node way and relation using placeholders
645 <node id='-1' lon='0' lat='0' changeset='#{cs_id}'>
646 <tag k='foo' v='#{"x"*256}'/>
654 post :upload, :id => cs_id
655 assert_response :bad_request,
656 "shoudln't be able to upload too long a tag to changeset: #{@response.body}"
661 # upload something which creates new objects and inserts them into
662 # existing containers using placeholders.
663 def test_upload_complex
664 basic_authorization users(:public_user).email, "test"
665 cs_id = changesets(:public_user_first_change).id
667 # simple diff to create a node way and relation using placeholders
671 <node id='-1' lon='0' lat='0' changeset='#{cs_id}'>
672 <tag k='foo' v='bar'/>
673 <tag k='baz' v='bat'/>
677 <way id='1' changeset='#{cs_id}' version='1'>
681 <relation id='1' changeset='#{cs_id}' version='1'>
682 <member type='way' role='some' ref='3'/>
683 <member type='node' role='some' ref='-1'/>
684 <member type='relation' role='some' ref='3'/>
692 post :upload, :id => cs_id
693 assert_response :success,
694 "can't upload a complex diff to changeset: #{@response.body}"
696 # check the returned payload
697 assert_select "diffResult[version=#{API_VERSION}][generator=\"#{GENERATOR}\"]", 1
698 assert_select "diffResult>node", 1
699 assert_select "diffResult>way", 1
700 assert_select "diffResult>relation", 1
702 # inspect the response to find out what the new element IDs are
703 doc = XML::Parser.string(@response.body).parse
704 new_node_id = doc.find("//diffResult/node").first["new_id"].to_i
706 # check that the changes made it into the database
707 assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
708 assert_equal [new_node_id, 3], Way.find(1).nds, "way nodes should match"
709 Relation.find(1).members.each do |type,id,role|
711 assert_equal new_node_id, id, "relation should contain new node"
717 # create a diff which references several changesets, which should cause
718 # a rollback and none of the diff gets committed
719 def test_upload_invalid_changesets
720 basic_authorization users(:public_user).email, "test"
721 cs_id = changesets(:public_user_first_change).id
723 # simple diff to create a node way and relation using placeholders
727 <node id='1' lon='0' lat='0' changeset='#{cs_id}' version='1'/>
728 <way id='1' changeset='#{cs_id}' version='1'>
733 <relation id='1' changeset='#{cs_id}' version='1'>
734 <member type='way' role='some' ref='3'/>
735 <member type='node' role='some' ref='5'/>
736 <member type='relation' role='some' ref='3'/>
740 <node id='-1' lon='0' lat='0' changeset='4'>
741 <tag k='foo' v='bar'/>
742 <tag k='baz' v='bat'/>
747 # cache the objects before uploading them
748 node = current_nodes(:visible_node)
749 way = current_ways(:visible_way)
750 rel = current_relations(:visible_relation)
754 post :upload, :id => cs_id
755 assert_response :conflict,
756 "uploading a diff with multiple changsets should have failed"
758 # check that objects are unmodified
759 assert_nodes_are_equal(node, Node.find(1))
760 assert_ways_are_equal(way, Way.find(1))
764 # upload multiple versions of the same element in the same diff.
765 def test_upload_multiple_valid
766 basic_authorization users(:public_user).email, "test"
767 cs_id = changesets(:public_user_first_change).id
769 # change the location of a node multiple times, each time referencing
770 # the last version. doesn't this depend on version numbers being
775 <node id='1' lon='0' lat='0' changeset='#{cs_id}' version='1'/>
776 <node id='1' lon='1' lat='0' changeset='#{cs_id}' version='2'/>
777 <node id='1' lon='1' lat='1' changeset='#{cs_id}' version='3'/>
778 <node id='1' lon='1' lat='2' changeset='#{cs_id}' version='4'/>
779 <node id='1' lon='2' lat='2' changeset='#{cs_id}' version='5'/>
780 <node id='1' lon='3' lat='2' changeset='#{cs_id}' version='6'/>
781 <node id='1' lon='3' lat='3' changeset='#{cs_id}' version='7'/>
782 <node id='1' lon='9' lat='9' changeset='#{cs_id}' version='8'/>
789 post :upload, :id => cs_id
790 assert_response :success,
791 "can't upload multiple versions of an element in a diff: #{@response.body}"
793 # check the response is well-formed. its counter-intuitive, but the
794 # API will return multiple elements with the same ID and different
795 # version numbers for each change we made.
796 assert_select "diffResult>node", 8
800 # upload multiple versions of the same element in the same diff, but
801 # keep the version numbers the same.
802 def test_upload_multiple_duplicate
803 basic_authorization users(:public_user).email, "test"
804 cs_id = changesets(:public_user_first_change).id
809 <node id='1' lon='0' lat='0' changeset='#{cs_id}' version='1'/>
810 <node id='1' lon='1' lat='1' changeset='#{cs_id}' version='1'/>
817 post :upload, :id => cs_id
818 assert_response :conflict,
819 "shouldn't be able to upload the same element twice in a diff: #{@response.body}"
823 # try to upload some elements without specifying the version
824 def test_upload_missing_version
825 basic_authorization users(:public_user).email, "test"
826 cs_id = changesets(:public_user_first_change).id
831 <node id='1' lon='1' lat='1' changeset='cs_id'/>
838 post :upload, :id => cs_id
839 assert_response :bad_request,
840 "shouldn't be able to upload an element without version: #{@response.body}"
844 # try to upload with commands other than create, modify, or delete
845 def test_action_upload_invalid
846 basic_authorization users(:public_user).email, "test"
847 cs_id = changesets(:public_user_first_change).id
852 <node id='1' lon='1' lat='1' changeset='#{cs_id}' />
857 post :upload, :id => cs_id
858 assert_response :bad_request, "Shouldn't be able to upload a diff with the action ping"
859 assert_equal @response.body, "Unknown action ping, choices are create, modify, delete"
863 # upload a valid changeset which has a mixture of whitespace
864 # to check a bug reported by ivansanchez (#1565).
865 def test_upload_whitespace_valid
866 basic_authorization users(:public_user).email, "test"
867 changeset_id = changesets(:public_user_first_change).id
871 <modify><node id='1' lon='0' lat='0' changeset='#{changeset_id}'
873 <node id='1' lon='1' lat='1' changeset='#{changeset_id}' version='2'><tag k='k' v='v'/></node></modify>
875 <relation id='1' changeset='#{changeset_id}' version='1'><member
876 type='way' role='some' ref='3'/><member
877 type='node' role='some' ref='5'/>
878 <member type='relation' role='some' ref='3'/>
880 </modify></osmChange>
885 post :upload, :id => changeset_id
886 assert_response :success,
887 "can't upload a valid diff with whitespace variations to changeset: #{@response.body}"
889 # check the response is well-formed
890 assert_select "diffResult>node", 2
891 assert_select "diffResult>relation", 1
893 # check that the changes made it into the database
894 assert_equal 1, Node.find(1).tags.size, "node 1 should now have one tag"
895 assert_equal 0, Relation.find(1).tags.size, "relation 1 should now have no tags"
899 # upload a valid changeset which has a mixture of whitespace
900 # to check a bug reported by ivansanchez.
901 def test_upload_reuse_placeholder_valid
902 basic_authorization users(:public_user).email, "test"
903 changeset_id = changesets(:public_user_first_change).id
908 <node id='-1' lon='0' lat='0' changeset='#{changeset_id}'>
909 <tag k="foo" v="bar"/>
913 <node id='-1' lon='1' lat='1' changeset='#{changeset_id}' version='1'/>
916 <node id='-1' lon='2' lat='2' changeset='#{changeset_id}' version='2'/>
923 post :upload, :id => changeset_id
924 assert_response :success,
925 "can't upload a valid diff with re-used placeholders to changeset: #{@response.body}"
927 # check the response is well-formed
928 assert_select "diffResult>node", 3
929 assert_select "diffResult>node[old_id=-1]", 3
933 # test what happens if a diff upload re-uses placeholder IDs in an
935 def test_upload_placeholder_invalid
936 basic_authorization users(:public_user).email, "test"
937 changeset_id = changesets(:public_user_first_change).id
942 <node id='-1' lon='0' lat='0' changeset='#{changeset_id}' version='1'/>
943 <node id='-1' lon='1' lat='1' changeset='#{changeset_id}' version='1'/>
944 <node id='-1' lon='2' lat='2' changeset='#{changeset_id}' version='2'/>
951 post :upload, :id => changeset_id
952 assert_response :bad_request,
953 "shouldn't be able to re-use placeholder IDs"
957 # test that uploading a way referencing invalid placeholders gives a
958 # proper error, not a 500.
959 def test_upload_placeholder_invalid_way
960 basic_authorization users(:public_user).email, "test"
961 changeset_id = changesets(:public_user_first_change).id
966 <node id="-1" lon="0" lat="0" changeset="#{changeset_id}" version="1"/>
967 <node id="-2" lon="1" lat="1" changeset="#{changeset_id}" version="1"/>
968 <node id="-3" lon="2" lat="2" changeset="#{changeset_id}" version="1"/>
969 <way id="-1" changeset="#{changeset_id}" version="1">
981 post :upload, :id => changeset_id
982 assert_response :bad_request,
983 "shouldn't be able to use invalid placeholder IDs"
984 assert_equal "Placeholder node not found for reference -4 in way -1", @response.body
986 # the same again, but this time use an existing way
990 <node id="-1" lon="0" lat="0" changeset="#{changeset_id}" version="1"/>
991 <node id="-2" lon="1" lat="1" changeset="#{changeset_id}" version="1"/>
992 <node id="-3" lon="2" lat="2" changeset="#{changeset_id}" version="1"/>
993 <way id="1" changeset="#{changeset_id}" version="1">
1005 post :upload, :id => changeset_id
1006 assert_response :bad_request,
1007 "shouldn't be able to use invalid placeholder IDs"
1008 assert_equal "Placeholder node not found for reference -4 in way 1", @response.body
1012 # test that uploading a relation referencing invalid placeholders gives a
1013 # proper error, not a 500.
1014 def test_upload_placeholder_invalid_relation
1015 basic_authorization users(:public_user).email, "test"
1016 changeset_id = changesets(:public_user_first_change).id
1021 <node id="-1" lon="0" lat="0" changeset="#{changeset_id}" version="1"/>
1022 <node id="-2" lon="1" lat="1" changeset="#{changeset_id}" version="1"/>
1023 <node id="-3" lon="2" lat="2" changeset="#{changeset_id}" version="1"/>
1024 <relation id="-1" changeset="#{changeset_id}" version="1">
1025 <member type="node" role="foo" ref="-1"/>
1026 <member type="node" role="foo" ref="-2"/>
1027 <member type="node" role="foo" ref="-3"/>
1028 <member type="node" role="foo" ref="-4"/>
1036 post :upload, :id => changeset_id
1037 assert_response :bad_request,
1038 "shouldn't be able to use invalid placeholder IDs"
1039 assert_equal "Placeholder Node not found for reference -4 in relation -1.", @response.body
1041 # the same again, but this time use an existing way
1045 <node id="-1" lon="0" lat="0" changeset="#{changeset_id}" version="1"/>
1046 <node id="-2" lon="1" lat="1" changeset="#{changeset_id}" version="1"/>
1047 <node id="-3" lon="2" lat="2" changeset="#{changeset_id}" version="1"/>
1048 <relation id="1" changeset="#{changeset_id}" version="1">
1049 <member type="node" role="foo" ref="-1"/>
1050 <member type="node" role="foo" ref="-2"/>
1051 <member type="node" role="foo" ref="-3"/>
1052 <member type="way" role="bar" ref="-1"/>
1060 post :upload, :id => changeset_id
1061 assert_response :bad_request,
1062 "shouldn't be able to use invalid placeholder IDs"
1063 assert_equal "Placeholder Way not found for reference -1 in relation 1.", @response.body
1067 # test what happens if a diff is uploaded containing only a node
1069 def test_upload_node_move
1070 basic_authorization users(:public_user).email, "test"
1072 content "<osm><changeset>" +
1073 "<tag k='created_by' v='osm test suite checking changesets'/>" +
1074 "</changeset></osm>"
1076 assert_response :success
1077 changeset_id = @response.body.to_i
1079 old_node = current_nodes(:visible_node)
1081 diff = XML::Document.new
1082 diff.root = XML::Node.new "osmChange"
1083 modify = XML::Node.new "modify"
1084 xml_old_node = old_node.to_xml_node
1085 xml_old_node["lat"] = (2.0).to_s
1086 xml_old_node["lon"] = (2.0).to_s
1087 xml_old_node["changeset"] = changeset_id.to_s
1088 modify << xml_old_node
1093 post :upload, :id => changeset_id
1094 assert_response :success,
1095 "diff should have uploaded OK"
1098 changeset = Changeset.find(changeset_id)
1099 assert_equal 1*SCALE, changeset.min_lon, "min_lon should be 1 degree"
1100 assert_equal 2*SCALE, changeset.max_lon, "max_lon should be 2 degrees"
1101 assert_equal 1*SCALE, changeset.min_lat, "min_lat should be 1 degree"
1102 assert_equal 2*SCALE, changeset.max_lat, "max_lat should be 2 degrees"
1106 # test what happens if a diff is uploaded adding a node to a way.
1107 def test_upload_way_extend
1108 basic_authorization users(:public_user).email, "test"
1110 content "<osm><changeset>" +
1111 "<tag k='created_by' v='osm test suite checking changesets'/>" +
1112 "</changeset></osm>"
1114 assert_response :success
1115 changeset_id = @response.body.to_i
1117 old_way = current_ways(:visible_way)
1119 diff = XML::Document.new
1120 diff.root = XML::Node.new "osmChange"
1121 modify = XML::Node.new "modify"
1122 xml_old_way = old_way.to_xml_node
1123 nd_ref = XML::Node.new "nd"
1124 nd_ref["ref"] = current_nodes(:visible_node).id.to_s
1125 xml_old_way << nd_ref
1126 xml_old_way["changeset"] = changeset_id.to_s
1127 modify << xml_old_way
1132 post :upload, :id => changeset_id
1133 assert_response :success,
1134 "diff should have uploaded OK"
1137 changeset = Changeset.find(changeset_id)
1138 assert_equal 1*SCALE, changeset.min_lon, "min_lon should be 1 degree"
1139 assert_equal 3*SCALE, changeset.max_lon, "max_lon should be 3 degrees"
1140 assert_equal 1*SCALE, changeset.min_lat, "min_lat should be 1 degree"
1141 assert_equal 3*SCALE, changeset.max_lat, "max_lat should be 3 degrees"
1145 # test for more issues in #1568
1146 def test_upload_empty_invalid
1147 basic_authorization users(:public_user).email, "test"
1150 "<osmChange></osmChange>",
1151 "<osmChange><modify/></osmChange>",
1152 "<osmChange><modify></modify></osmChange>"
1156 post :upload, :id => changesets(:public_user_first_change).id
1157 assert_response(:success, "should be able to upload " +
1158 "empty changeset: " + diff)
1163 # test that the X-Error-Format header works to request XML errors
1164 def test_upload_xml_errors
1165 basic_authorization users(:public_user).email, "test"
1167 # try and delete a node that is in use
1168 diff = XML::Document.new
1169 diff.root = XML::Node.new "osmChange"
1170 delete = XML::Node.new "delete"
1172 delete << current_nodes(:node_used_by_relationship).to_xml_node
1177 post :upload, :id => 2
1178 assert_response :success,
1179 "failed to return error in XML format"
1181 # check the returned payload
1182 assert_select "osmError[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
1183 assert_select "osmError>status", 1
1184 assert_select "osmError>message", 1
1189 # when we make some simple changes we get the same changes back from the
1191 def test_diff_download_simple
1192 ## First try with the normal user, which should get a forbidden
1193 basic_authorization(users(:normal_user).email, "test")
1195 # create a temporary changeset
1196 content "<osm><changeset>" +
1197 "<tag k='created_by' v='osm test suite checking changesets'/>" +
1198 "</changeset></osm>"
1200 assert_response :forbidden
1204 ## Now try with the public user
1205 basic_authorization(users(:public_user).email, "test")
1207 # create a temporary changeset
1208 content "<osm><changeset>" +
1209 "<tag k='created_by' v='osm test suite checking changesets'/>" +
1210 "</changeset></osm>"
1212 assert_response :success
1213 changeset_id = @response.body.to_i
1219 <node id='1' lon='0' lat='0' changeset='#{changeset_id}' version='1'/>
1220 <node id='1' lon='1' lat='0' changeset='#{changeset_id}' version='2'/>
1221 <node id='1' lon='1' lat='1' changeset='#{changeset_id}' version='3'/>
1222 <node id='1' lon='1' lat='2' changeset='#{changeset_id}' version='4'/>
1223 <node id='1' lon='2' lat='2' changeset='#{changeset_id}' version='5'/>
1224 <node id='1' lon='3' lat='2' changeset='#{changeset_id}' version='6'/>
1225 <node id='1' lon='3' lat='3' changeset='#{changeset_id}' version='7'/>
1226 <node id='1' lon='9' lat='9' changeset='#{changeset_id}' version='8'/>
1233 post :upload, :id => changeset_id
1234 assert_response :success,
1235 "can't upload multiple versions of an element in a diff: #{@response.body}"
1237 get :download, :id => changeset_id
1238 assert_response :success
1240 assert_select "osmChange", 1
1241 assert_select "osmChange>modify", 8
1242 assert_select "osmChange>modify>node", 8
1246 # culled this from josm to ensure that nothing in the way that josm
1247 # is formatting the request is causing it to fail.
1249 # NOTE: the error turned out to be something else completely!
1250 def test_josm_upload
1251 basic_authorization(users(:public_user).email, "test")
1253 # create a temporary changeset
1254 content "<osm><changeset>" +
1255 "<tag k='created_by' v='osm test suite checking changesets'/>" +
1256 "</changeset></osm>"
1258 assert_response :success
1259 changeset_id = @response.body.to_i
1262 <osmChange version="0.6" generator="JOSM">
1263 <create version="0.6" generator="JOSM">
1264 <node id='-1' visible='true' changeset='#{changeset_id}' lat='51.49619982187321' lon='-0.18722061869438314' />
1265 <node id='-2' visible='true' changeset='#{changeset_id}' lat='51.496359883909605' lon='-0.18653093576241928' />
1266 <node id='-3' visible='true' changeset='#{changeset_id}' lat='51.49598132358285' lon='-0.18719613290981638' />
1267 <node id='-4' visible='true' changeset='#{changeset_id}' lat='51.4961591711078' lon='-0.18629015888084607' />
1268 <node id='-5' visible='true' changeset='#{changeset_id}' lat='51.49582126021711' lon='-0.18708186591517145' />
1269 <node id='-6' visible='true' changeset='#{changeset_id}' lat='51.49591018437858' lon='-0.1861432441734455' />
1270 <node id='-7' visible='true' changeset='#{changeset_id}' lat='51.49560784152179' lon='-0.18694719410005425' />
1271 <node id='-8' visible='true' changeset='#{changeset_id}' lat='51.49567389979617' lon='-0.1860289771788006' />
1272 <node id='-9' visible='true' changeset='#{changeset_id}' lat='51.49543761398892' lon='-0.186820684213126' />
1273 <way id='-10' action='modiy' visible='true' changeset='#{changeset_id}'>
1283 <tag k='highway' v='residential' />
1284 <tag k='name' v='Foobar Street' />
1292 post :upload, :id => changeset_id
1293 assert_response :success,
1294 "can't upload a diff from JOSM: #{@response.body}"
1296 get :download, :id => changeset_id
1297 assert_response :success
1299 assert_select "osmChange", 1
1300 assert_select "osmChange>create>node", 9
1301 assert_select "osmChange>create>way", 1
1302 assert_select "osmChange>create>way>nd", 9
1303 assert_select "osmChange>create>way>tag", 2
1307 # when we make some complex changes we get the same changes back from the
1309 def test_diff_download_complex
1310 basic_authorization(users(:public_user).email, "test")
1312 # create a temporary changeset
1313 content "<osm><changeset>" +
1314 "<tag k='created_by' v='osm test suite checking changesets'/>" +
1315 "</changeset></osm>"
1317 assert_response :success
1318 changeset_id = @response.body.to_i
1324 <node id='1' lon='0' lat='0' changeset='#{changeset_id}' version='1'/>
1327 <node id='-1' lon='9' lat='9' changeset='#{changeset_id}' version='0'/>
1328 <node id='-2' lon='8' lat='9' changeset='#{changeset_id}' version='0'/>
1329 <node id='-3' lon='7' lat='9' changeset='#{changeset_id}' version='0'/>
1332 <node id='3' lon='20' lat='15' changeset='#{changeset_id}' version='1'/>
1333 <way id='1' changeset='#{changeset_id}' version='1'>
1345 post :upload, :id => changeset_id
1346 assert_response :success,
1347 "can't upload multiple versions of an element in a diff: #{@response.body}"
1349 get :download, :id => changeset_id
1350 assert_response :success
1352 assert_select "osmChange", 1
1353 assert_select "osmChange>create", 3
1354 assert_select "osmChange>delete", 1
1355 assert_select "osmChange>modify", 2
1356 assert_select "osmChange>create>node", 3
1357 assert_select "osmChange>delete>node", 1
1358 assert_select "osmChange>modify>node", 1
1359 assert_select "osmChange>modify>way", 1
1362 def test_changeset_download
1363 get :download, :id => changesets(:normal_user_first_change).id
1364 assert_response :success
1366 #print @response.body
1367 # FIXME needs more assert_select tests
1368 assert_select "osmChange[version='#{API_VERSION}'][generator='#{GENERATOR}']" do
1369 assert_select "create", :count => 5
1370 assert_select "create>node[id=#{nodes(:used_node_2).node_id}][visible=#{nodes(:used_node_2).visible?}][version=#{nodes(:used_node_2).version}]" do
1371 assert_select "tag[k=#{node_tags(:t3).k}][v=#{node_tags(:t3).v}]"
1373 assert_select "create>node[id=#{nodes(:visible_node).node_id}]"
1378 # check that the bounding box of a changeset gets updated correctly
1379 ## FIXME: This should really be moded to a integration test due to the with_controller
1380 def test_changeset_bbox
1381 basic_authorization users(:public_user).email, "test"
1383 # create a new changeset
1384 content "<osm><changeset/></osm>"
1386 assert_response :success, "Creating of changeset failed."
1387 changeset_id = @response.body.to_i
1389 # add a single node to it
1390 with_controller(NodeController.new) do
1391 content "<osm><node lon='1' lat='2' changeset='#{changeset_id}'/></osm>"
1393 assert_response :success, "Couldn't create node."
1396 # get the bounding box back from the changeset
1397 get :read, :id => changeset_id
1398 assert_response :success, "Couldn't read back changeset."
1399 assert_select "osm>changeset[min_lon=1.0]", 1
1400 assert_select "osm>changeset[max_lon=1.0]", 1
1401 assert_select "osm>changeset[min_lat=2.0]", 1
1402 assert_select "osm>changeset[max_lat=2.0]", 1
1404 # add another node to it
1405 with_controller(NodeController.new) do
1406 content "<osm><node lon='2' lat='1' changeset='#{changeset_id}'/></osm>"
1408 assert_response :success, "Couldn't create second node."
1411 # get the bounding box back from the changeset
1412 get :read, :id => changeset_id
1413 assert_response :success, "Couldn't read back changeset for the second time."
1414 assert_select "osm>changeset[min_lon=1.0]", 1
1415 assert_select "osm>changeset[max_lon=2.0]", 1
1416 assert_select "osm>changeset[min_lat=1.0]", 1
1417 assert_select "osm>changeset[max_lat=2.0]", 1
1419 # add (delete) a way to it, which contains a point at (3,3)
1420 with_controller(WayController.new) do
1421 content update_changeset(current_ways(:visible_way).to_xml,
1423 put :delete, :id => current_ways(:visible_way).id
1424 assert_response :success, "Couldn't delete a way."
1427 # get the bounding box back from the changeset
1428 get :read, :id => changeset_id
1429 assert_response :success, "Couldn't read back changeset for the third time."
1430 # note that the 3.1 here is because of the bbox overexpansion
1431 assert_select "osm>changeset[min_lon=1.0]", 1
1432 assert_select "osm>changeset[max_lon=3.1]", 1
1433 assert_select "osm>changeset[min_lat=1.0]", 1
1434 assert_select "osm>changeset[max_lat=3.1]", 1
1438 # test that the changeset :include method works as it should
1439 def test_changeset_include
1440 basic_authorization users(:public_user).display_name, "test"
1442 # create a new changeset
1443 content "<osm><changeset/></osm>"
1445 assert_response :success, "Creating of changeset failed."
1446 changeset_id = @response.body.to_i
1448 # NOTE: the include method doesn't over-expand, like inserting
1449 # a real method does. this is because we expect the client to
1450 # know what it is doing!
1451 check_after_include(changeset_id, 1, 1, [ 1, 1, 1, 1])
1452 check_after_include(changeset_id, 3, 3, [ 1, 1, 3, 3])
1453 check_after_include(changeset_id, 4, 2, [ 1, 1, 4, 3])
1454 check_after_include(changeset_id, 2, 2, [ 1, 1, 4, 3])
1455 check_after_include(changeset_id, -1, -1, [-1, -1, 4, 3])
1456 check_after_include(changeset_id, -2, 5, [-2, -1, 4, 5])
1460 # test that a not found, wrong method with the expand bbox works as expected
1461 def test_changeset_expand_bbox_error
1462 basic_authorization users(:public_user).display_name, "test"
1464 # create a new changeset
1465 content "<osm><changeset/></osm>"
1467 assert_response :success, "Creating of changeset failed."
1468 changeset_id = @response.body.to_i
1474 content "<osm><node lon='#{lon}' lat='#{lat}'/></osm>"
1475 put :expand_bbox, :id => changeset_id
1476 assert_response :method_not_allowed, "shouldn't be able to put a bbox expand"
1478 # Try to get the update
1479 content "<osm><node lon='#{lon}' lat='#{lat}'/></osm>"
1480 get :expand_bbox, :id => changeset_id
1481 assert_response :method_not_allowed, "shouldn't be able to get a bbox expand"
1483 # Try to use a hopefully missing changeset
1484 content "<osm><node lon='#{lon}' lat='#{lat}'/></osm>"
1485 post :expand_bbox, :id => changeset_id+13245
1486 assert_response :not_found, "shouldn't be able to do a bbox expand on a nonexistant changeset"
1491 # test the query functionality of changesets
1493 get :query, :bbox => "-10,-10, 10, 10"
1494 assert_response :success, "can't get changesets in bbox"
1495 assert_changesets [1,4,6]
1497 get :query, :bbox => "4.5,4.5,4.6,4.6"
1498 assert_response :success, "can't get changesets in bbox"
1499 assert_changesets [1]
1501 # not found when looking for changesets of non-existing users
1502 get :query, :user => User.maximum(:id) + 1
1503 assert_response :not_found
1504 get :query, :display_name => " "
1505 assert_response :not_found
1507 # can't get changesets of user 1 without authenticating
1508 get :query, :user => users(:normal_user).id
1509 assert_response :not_found, "shouldn't be able to get changesets by non-public user (ID)"
1510 get :query, :display_name => users(:normal_user).display_name
1511 assert_response :not_found, "shouldn't be able to get changesets by non-public user (name)"
1513 # but this should work
1514 basic_authorization "test@openstreetmap.org", "test"
1515 get :query, :user => users(:normal_user).id
1516 assert_response :success, "can't get changesets by user ID"
1517 assert_changesets [1,3,6]
1519 get :query, :display_name => users(:normal_user).display_name
1520 assert_response :success, "can't get changesets by user name"
1521 assert_changesets [1,3,6]
1523 # check that the correct error is given when we provide both UID and name
1524 get :query, :user => users(:normal_user).id, :display_name => users(:normal_user).display_name
1525 assert_response :bad_request, "should be a bad request to have both ID and name specified"
1527 get :query, :user => users(:normal_user).id, :open => true
1528 assert_response :success, "can't get changesets by user and open"
1529 assert_changesets [1]
1531 get :query, :time => '2007-12-31'
1532 assert_response :success, "can't get changesets by time-since"
1533 assert_changesets [1,2,4,5,6]
1535 get :query, :time => '2008-01-01T12:34Z'
1536 assert_response :success, "can't get changesets by time-since with hour"
1537 assert_changesets [1,2,4,5,6]
1539 get :query, :time => '2007-12-31T23:59Z,2008-01-01T00:01Z'
1540 assert_response :success, "can't get changesets by time-range"
1541 assert_changesets [1,5,6]
1543 get :query, :open => 'true'
1544 assert_response :success, "can't get changesets by open-ness"
1545 assert_changesets [1,2,4]
1547 get :query, :closed => 'true'
1548 assert_response :success, "can't get changesets by closed-ness"
1549 assert_changesets [3,5,6,7]
1551 get :query, :closed => 'true', :user => users(:normal_user).id
1552 assert_response :success, "can't get changesets by closed-ness and user"
1553 assert_changesets [3,6]
1555 get :query, :closed => 'true', :user => users(:public_user).id
1556 assert_response :success, "can't get changesets by closed-ness and user"
1557 assert_changesets [7]
1561 # check that errors are returned if garbage is inserted
1562 # into query strings
1563 def test_query_invalid
1566 ";drop table users;"
1568 get :query, :bbox => bbox
1569 assert_response :bad_request, "'#{bbox}' isn't a bbox"
1574 ";drop table users;",
1578 get :query, :time => time
1579 assert_response :bad_request, "'#{time}' isn't a valid time range"
1587 get :query, :user => uid
1588 assert_response :bad_request, "'#{uid}' isn't a valid user ID"
1593 # check updating tags on a changeset
1594 def test_changeset_update
1595 ## First try with the non-public user
1596 changeset = changesets(:normal_user_first_change)
1597 new_changeset = changeset.to_xml
1598 new_tag = XML::Node.new "tag"
1599 new_tag['k'] = "tagtesting"
1600 new_tag['v'] = "valuetesting"
1601 new_changeset.find("//osm/changeset").first << new_tag
1602 content new_changeset
1604 # try without any authorization
1605 put :update, :id => changeset.id
1606 assert_response :unauthorized
1608 # try with the wrong authorization
1609 basic_authorization users(:public_user).email, "test"
1610 put :update, :id => changeset.id
1611 assert_response :conflict
1613 # now this should get an unauthorized
1614 basic_authorization users(:normal_user).email, "test"
1615 put :update, :id => changeset.id
1616 assert_require_public_data "user with their data non-public, shouldn't be able to edit their changeset"
1619 ## Now try with the public user
1620 changeset = changesets(:public_user_first_change)
1621 new_changeset = changeset.to_xml
1622 new_tag = XML::Node.new "tag"
1623 new_tag['k'] = "tagtesting"
1624 new_tag['v'] = "valuetesting"
1625 new_changeset.find("//osm/changeset").first << new_tag
1626 content new_changeset
1628 # try without any authorization
1629 @request.env["HTTP_AUTHORIZATION"] = nil
1630 put :update, :id => changeset.id
1631 assert_response :unauthorized
1633 # try with the wrong authorization
1634 basic_authorization users(:second_public_user).email, "test"
1635 put :update, :id => changeset.id
1636 assert_response :conflict
1638 # now this should work...
1639 basic_authorization users(:public_user).email, "test"
1640 put :update, :id => changeset.id
1641 assert_response :success
1643 assert_select "osm>changeset[id=#{changeset.id}]", 1
1644 assert_select "osm>changeset>tag", 2
1645 assert_select "osm>changeset>tag[k=tagtesting][v=valuetesting]", 1
1649 # check that a user different from the one who opened the changeset
1651 def test_changeset_update_invalid
1652 basic_authorization users(:public_user).email, "test"
1654 changeset = changesets(:normal_user_first_change)
1655 new_changeset = changeset.to_xml
1656 new_tag = XML::Node.new "tag"
1657 new_tag['k'] = "testing"
1658 new_tag['v'] = "testing"
1659 new_changeset.find("//osm/changeset").first << new_tag
1661 content new_changeset
1662 put :update, :id => changeset.id
1663 assert_response :conflict
1667 # check that a changeset can contain a certain max number of changes.
1668 ## FIXME should be changed to an integration test due to the with_controller
1669 def test_changeset_limits
1670 basic_authorization users(:public_user).email, "test"
1672 # open a new changeset
1673 content "<osm><changeset/></osm>"
1675 assert_response :success, "can't create a new changeset"
1676 cs_id = @response.body.to_i
1678 # start the counter just short of where the changeset should finish.
1680 # alter the database to set the counter on the changeset directly,
1681 # otherwise it takes about 6 minutes to fill all of them.
1682 changeset = Changeset.find(cs_id)
1683 changeset.num_changes = Changeset::MAX_ELEMENTS - offset
1686 with_controller(NodeController.new) do
1688 content "<osm><node changeset='#{cs_id}' lat='0.0' lon='0.0'/></osm>"
1690 assert_response :success, "can't create a new node"
1691 node_id = @response.body.to_i
1693 get :read, :id => node_id
1694 assert_response :success, "can't read back new node"
1695 node_doc = XML::Parser.string(@response.body).parse
1696 node_xml = node_doc.find("//osm/node").first
1698 # loop until we fill the changeset with nodes
1700 node_xml['lat'] = rand.to_s
1701 node_xml['lon'] = rand.to_s
1702 node_xml['version'] = (i+1).to_s
1705 put :update, :id => node_id
1706 assert_response :success, "attempt #{i} should have succeeded"
1709 # trying again should fail
1710 node_xml['lat'] = rand.to_s
1711 node_xml['lon'] = rand.to_s
1712 node_xml['version'] = offset.to_s
1715 put :update, :id => node_id
1716 assert_response :conflict, "final attempt should have failed"
1719 changeset = Changeset.find(cs_id)
1720 assert_equal Changeset::MAX_ELEMENTS + 1, changeset.num_changes
1722 # check that the changeset is now closed as well
1723 assert(!changeset.is_open?,
1724 "changeset should have been auto-closed by exceeding " +
1729 # This should display the last 20 changesets closed.
1731 changesets = Changeset.find(:all, :order => "created_at DESC", :conditions => ['num_changes > 0'], :limit=> 20)
1732 assert changesets.size <= 20
1733 get :list, {:format => "html"}
1734 assert_response :success
1735 assert_template "list"
1736 # Now check that all 20 (or however many were returned) changesets are in the html
1737 assert_select "h1", :text => "Changesets", :count => 1
1738 assert_select "table[id='changeset_list'] tr", :count => changesets.size
1739 changesets.each do |changeset|
1740 # FIXME this test needs rewriting - test for table contents
1745 # Checks the display of the user changesets listing
1747 user = users(:public_user)
1748 get :list, {:format => "html", :display_name => user.display_name}
1749 assert_response :success
1750 assert_template "changeset/_user"
1751 ## FIXME need to add more checks to see which if edits are actually shown if your data is public
1755 # Check the not found of the list user changesets
1756 def test_list_user_not_found
1757 get :list, {:format => "html", :display_name => "Some random user"}
1758 assert_response :not_found
1759 assert_template 'user/no_such_user'
1763 # This should display the last 20 changesets closed.
1765 changesets = Changeset.find(:all, :order => "created_at DESC", :conditions => ['num_changes > 0'], :limit=> 20)
1766 assert changesets.size <= 20
1767 get :feed, {:format => "atom"}
1768 assert_response :success
1769 assert_template "list"
1770 # Now check that all 20 (or however many were returned) changesets are in the html
1771 assert_select "feed", :count => 1
1772 assert_select "entry", :count => changesets.size
1773 changesets.each do |changeset|
1774 # FIXME this test needs rewriting - test for feed contents
1779 # Checks the display of the user changesets feed
1781 user = users(:public_user)
1782 get :feed, {:format => "atom", :display_name => user.display_name}
1783 assert_response :success
1784 assert_template "changeset/_user"
1785 ## FIXME need to add more checks to see which if edits are actually shown if your data is public
1789 # Check the not found of the user changesets feed
1790 def test_feed_user_not_found
1791 get :feed, {:format => "atom", :display_name => "Some random user"}
1792 assert_response :not_found
1796 # check that the changeset download for a changeset with a redacted
1797 # element in it doesn't contain that element.
1798 def test_diff_download_redacted
1799 changeset_id = changesets(:public_user_first_change).id
1801 get :download, :id => changeset_id
1802 assert_response :success
1804 assert_select "osmChange", 1
1805 # this changeset contains node 17 in versions 1 & 2, but 1 should
1807 assert_select "osmChange node[id=17]", 1
1808 assert_select "osmChange node[id=17][version=1]", 0
1811 #------------------------------------------------------------
1813 #------------------------------------------------------------
1816 # boilerplate for checking that certain changesets exist in the
1818 def assert_changesets(ids)
1819 assert_select "osm>changeset", ids.size
1821 assert_select "osm>changeset[id=#{id}]", 1
1826 # call the include method and assert properties of the bbox
1827 def check_after_include(changeset_id, lon, lat, bbox)
1828 content "<osm><node lon='#{lon}' lat='#{lat}'/></osm>"
1829 post :expand_bbox, :id => changeset_id
1830 assert_response :success, "Setting include of changeset failed: #{@response.body}"
1832 # check exactly one changeset
1833 assert_select "osm>changeset", 1
1834 assert_select "osm>changeset[id=#{changeset_id}]", 1
1837 doc = XML::Parser.string(@response.body).parse
1838 changeset = doc.find("//osm/changeset").first
1839 assert_equal bbox[0], changeset['min_lon'].to_f, "min lon"
1840 assert_equal bbox[1], changeset['min_lat'].to_f, "min lat"
1841 assert_equal bbox[2], changeset['max_lon'].to_f, "max lon"
1842 assert_equal bbox[3], changeset['max_lat'].to_f, "max lat"
1846 # update the changeset_id of a way element
1847 def update_changeset(xml, changeset_id)
1848 xml_attr_rewrite(xml, 'changeset', changeset_id)
1852 # update an attribute in a way element
1853 def xml_attr_rewrite(xml, name, value)
1854 xml.find("//osm/way").first[name] = value.to_s