1 require File.dirname(__FILE__) + '/../test_helper'
2 require 'way_controller'
4 # Re-raise errors caught by the controller.
5 class WayController; def rescue_action(e) raise e end; end
7 class WayControllerTest < Test::Unit::TestCase
11 @controller = WayController.new
12 @request = ActionController::TestRequest.new
13 @response = ActionController::TestResponse.new
16 def basic_authorization(user, pass)
17 @request.env["HTTP_AUTHORIZATION"] = "Basic %s" % Base64.encode64("#{user}:#{pass}")
21 @request.env["RAW_POST_DATA"] = c.to_s
24 # -------------------------------------
26 # -------------------------------------
29 # check that a visible way is returned properly
30 get :read, :id => current_ways(:visible_way).id
31 assert_response :success
33 # check that an invisible way is not returned
34 get :read, :id => current_ways(:invisible_way).id
37 # check chat a non-existent way is not returned
39 assert_response :not_found
41 # check the "ways for node" mode
42 get :ways_for_node, :id => current_nodes(:used_node_1).id
43 assert_response :success
44 # FIXME check whether this contains the stuff we want!
46 # Needs to be updated when changing fixtures
47 # The generator should probably be defined in the environment.rb file
48 # in the same place as the api version
49 assert_select "osm[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
50 assert_select "osm way", 3
51 assert_select "osm way nd", 3
52 assert_select "osm way tag", 3
54 # check the "full" mode
55 get :full, :id => current_ways(:visible_way).id
56 assert_response :success
57 # FIXME check whether this contains the stuff we want!
59 # Check the way is correctly returned
60 way = current_ways(:visible_way)
61 assert_select "osm way[id=#{way.id}][version=#{way.version}][visible=#{way.visible}]", 1
62 assert_select "osm way nd[ref=#{way.way_nodes[0].node_id}]", 1
63 # Check that the node is correctly returned
64 nd = current_ways(:visible_way).nodes
65 assert_equal 1, nd.count
67 assert_select "osm node[id=#{nda.id}][version=#{nda.version}][lat=#{nda.lat}][lon=#{nda.lon}]", 1
70 # -------------------------------------
71 # Test simple way creation.
72 # -------------------------------------
75 nid1 = current_nodes(:used_node_1).id
76 nid2 = current_nodes(:used_node_2).id
77 basic_authorization "test@openstreetmap.org", "test"
79 # use the first user's open changeset
80 changeset_id = changesets(:normal_user_first_change).id
82 # create a way with pre-existing nodes
83 content "<osm><way changeset='#{changeset_id}'>" +
84 "<nd ref='#{nid1}'/><nd ref='#{nid2}'/>" +
85 "<tag k='test' v='yes' /></way></osm>"
88 assert_response :success,
89 "way upload did not return success status"
90 # read id of created way and search for it
91 wayid = @response.body
92 checkway = Way.find(wayid)
93 assert_not_nil checkway,
94 "uploaded way not found in data base after upload"
96 assert_equal checkway.nds.length, 2,
97 "saved way does not contain exactly one node"
98 assert_equal checkway.nds[0], nid1,
99 "saved way does not contain the right node on pos 0"
100 assert_equal checkway.nds[1], nid2,
101 "saved way does not contain the right node on pos 1"
102 assert_equal checkway.changeset_id, changeset_id,
103 "saved way does not belong to the correct changeset"
104 assert_equal users(:normal_user).id, checkway.changeset.user_id,
105 "saved way does not belong to user that created it"
106 assert_equal true, checkway.visible,
107 "saved way is not visible"
110 # -------------------------------------
111 # Test creating some invalid ways.
112 # -------------------------------------
114 def test_create_invalid
115 basic_authorization "test@openstreetmap.org", "test"
117 # use the first user's open changeset
118 open_changeset_id = changesets(:normal_user_first_change).id
119 closed_changeset_id = changesets(:normal_user_closed_change).id
120 nid1 = current_nodes(:used_node_1).id
122 # create a way with non-existing node
123 content "<osm><way changeset='#{open_changeset_id}'>" +
124 "<nd ref='0'/><tag k='test' v='yes' /></way></osm>"
127 assert_response :precondition_failed,
128 "way upload with invalid node did not return 'precondition failed'"
130 # create a way with no nodes
131 content "<osm><way changeset='#{open_changeset_id}'>" +
132 "<tag k='test' v='yes' /></way></osm>"
135 assert_response :precondition_failed,
136 "way upload with no node did not return 'precondition failed'"
138 # create a way inside a closed changeset
139 content "<osm><way changeset='#{closed_changeset_id}'>" +
140 "<nd ref='#{nid1}'/></way></osm>"
143 assert_response :conflict,
144 "way upload to closed changeset did not return 'conflict'"
147 # -------------------------------------
148 # Test deleting ways.
149 # -------------------------------------
152 # first try to delete way without auth
153 delete :delete, :id => current_ways(:visible_way).id
154 assert_response :unauthorized
157 basic_authorization("test@openstreetmap.org", "test");
159 # this shouldn't work as with the 0.6 api we need pay load to delete
160 delete :delete, :id => current_ways(:visible_way).id
161 assert_response :bad_request
163 # Now try without having a changeset
164 content "<osm><way id='#{current_ways(:visible_way).id}'></osm>"
165 delete :delete, :id => current_ways(:visible_way).id
166 assert_response :bad_request
168 # try to delete with an invalid (closed) changeset
169 content update_changeset(current_ways(:visible_way).to_xml,
170 changesets(:normal_user_closed_change).id)
171 delete :delete, :id => current_ways(:visible_way).id
172 assert_response :conflict
174 # try to delete with an invalid (non-existent) changeset
175 content update_changeset(current_ways(:visible_way).to_xml,0)
176 delete :delete, :id => current_ways(:visible_way).id
177 assert_response :conflict
179 # Now try with a valid changeset
180 content current_ways(:visible_way).to_xml
181 delete :delete, :id => current_ways(:visible_way).id
182 assert_response :success
184 # check the returned value - should be the new version number
185 # valid delete should return the new version number, which should
186 # be greater than the old version number
187 assert @response.body.to_i > current_ways(:visible_way).version,
188 "delete request should return a new version number for way"
190 # this won't work since the way is already deleted
191 content current_ways(:invisible_way).to_xml
192 delete :delete, :id => current_ways(:invisible_way).id
193 assert_response :gone
195 # this shouldn't work as the way is used in a relation
196 content current_ways(:used_way).to_xml
197 delete :delete, :id => current_ways(:used_way).id
198 assert_response :precondition_failed,
199 "shouldn't be able to delete a way used in a relation (#{@response.body})"
201 # this won't work since the way never existed
202 delete :delete, :id => 0
203 assert_response :not_found
206 # ------------------------------------------------------------
208 # ------------------------------------------------------------
211 # Try adding a duplicate of an existing tag to a way
212 def test_add_duplicate_tags
214 basic_authorization(users(:normal_user).email, "test")
216 # add an identical tag to the way
217 tag_xml = XML::Node.new("tag")
218 tag_xml['k'] = current_way_tags(:t1).k
219 tag_xml['v'] = current_way_tags(:t1).v
221 # add the tag into the existing xml
222 way_xml = current_ways(:visible_way).to_xml
223 way_xml.find("//osm/way").first << tag_xml
227 put :update, :id => current_ways(:visible_way).id
228 assert_response :bad_request,
229 "adding a duplicate tag to a way should fail with 'bad request'"
233 # Try adding a new duplicate tags to a way
234 def test_new_duplicate_tags
236 basic_authorization(users(:normal_user).email, "test")
238 # create duplicate tag
239 tag_xml = XML::Node.new("tag")
240 tag_xml['k'] = "i_am_a_duplicate"
241 tag_xml['v'] = "foobar"
243 # add the tag into the existing xml
244 way_xml = current_ways(:visible_way).to_xml
246 # add two copies of the tag
247 way_xml.find("//osm/way").first << tag_xml.copy(true) << tag_xml
251 put :update, :id => current_ways(:visible_way).id
252 assert_response :bad_request,
253 "adding new duplicate tags to a way should fail with 'bad request'"
257 # Try adding a new duplicate tags to a way.
258 # But be a bit subtle - use unicode decoding ambiguities to use different
259 # binary strings which have the same decoding.
260 def test_invalid_duplicate_tags
262 basic_authorization(users(:normal_user).email, "test")
264 # add the tag into the existing xml
265 way_str = "<osm><way changeset='1'>"
267 # all of these keys have the same unicode decoding, but are binary
268 # not equal. libxml should make these identical as it decodes the
270 [ "addr:housenumber",
271 "addr\xc0\xbahousenumber",
272 "addr\xe0\x80\xbahousenumber",
273 "addr\xf0\x80\x80\xbahousenumber" ].each do |key|
274 tag_xml = XML::Node.new("tag")
278 # add all new tags to the way
279 way_str << "<tag k='" + key + "' v='1'/>"
281 way_str << "</way></osm>";
286 assert_response :bad_request,
287 "adding new duplicate tags to a way should fail with 'bad request'"
291 # update the changeset_id of a node element
292 def update_changeset(xml, changeset_id)
293 xml_attr_rewrite(xml, 'changeset', changeset_id)
297 # update an attribute in the node element
298 def xml_attr_rewrite(xml, name, value)
299 xml.find("//osm/way").first[name] = value.to_s