1 require File.dirname(__FILE__) + '/../test_helper'
2 require 'way_controller'
4 class WayControllerTest < ActionController::TestCase
7 def basic_authorization(user, pass)
8 @request.env["HTTP_AUTHORIZATION"] = "Basic %s" % Base64.encode64("#{user}:#{pass}")
12 @request.env["RAW_POST_DATA"] = c.to_s
15 # -------------------------------------
17 # -------------------------------------
20 # check that a visible way is returned properly
21 get :read, :id => current_ways(:visible_way).id
22 assert_response :success
24 # check that an invisible way is not returned
25 get :read, :id => current_ways(:invisible_way).id
28 # check chat a non-existent way is not returned
30 assert_response :not_found
34 # check the "full" mode
36 get :full, :id => current_ways(:visible_way).id
37 assert_response :success
38 # FIXME check whether this contains the stuff we want!
40 # Check the way is correctly returned
41 way = current_ways(:visible_way)
42 assert_select "osm way[id=#{way.id}][version=#{way.version}][visible=#{way.visible}]", 1
43 assert_select "osm way nd[ref=#{way.way_nodes[0].node_id}]", 1
44 # Check that the node is correctly returned
45 nd = current_ways(:visible_way).nodes
46 assert_equal 1, nd.count
48 assert_select "osm node[id=#{nda.id}][version=#{nda.version}][lat=#{nda.lat}][lon=#{nda.lon}]", 1
51 # -------------------------------------
52 # Test simple way creation.
53 # -------------------------------------
56 nid1 = current_nodes(:used_node_1).id
57 nid2 = current_nodes(:used_node_2).id
58 basic_authorization "test@openstreetmap.org", "test"
60 # use the first user's open changeset
61 changeset_id = changesets(:normal_user_first_change).id
63 # create a way with pre-existing nodes
64 content "<osm><way changeset='#{changeset_id}'>" +
65 "<nd ref='#{nid1}'/><nd ref='#{nid2}'/>" +
66 "<tag k='test' v='yes' /></way></osm>"
69 assert_response :success,
70 "way upload did not return success status"
71 # read id of created way and search for it
72 wayid = @response.body
73 checkway = Way.find(wayid)
74 assert_not_nil checkway,
75 "uploaded way not found in data base after upload"
77 assert_equal checkway.nds.length, 2,
78 "saved way does not contain exactly one node"
79 assert_equal checkway.nds[0], nid1,
80 "saved way does not contain the right node on pos 0"
81 assert_equal checkway.nds[1], nid2,
82 "saved way does not contain the right node on pos 1"
83 assert_equal checkway.changeset_id, changeset_id,
84 "saved way does not belong to the correct changeset"
85 assert_equal users(:normal_user).id, checkway.changeset.user_id,
86 "saved way does not belong to user that created it"
87 assert_equal true, checkway.visible,
88 "saved way is not visible"
91 # -------------------------------------
92 # Test creating some invalid ways.
93 # -------------------------------------
95 def test_create_invalid
96 basic_authorization "test@openstreetmap.org", "test"
98 # use the first user's open changeset
99 open_changeset_id = changesets(:normal_user_first_change).id
100 closed_changeset_id = changesets(:normal_user_closed_change).id
101 nid1 = current_nodes(:used_node_1).id
103 # create a way with non-existing node
104 content "<osm><way changeset='#{open_changeset_id}'>" +
105 "<nd ref='0'/><tag k='test' v='yes' /></way></osm>"
108 assert_response :precondition_failed,
109 "way upload with invalid node did not return 'precondition failed'"
111 # create a way with no nodes
112 content "<osm><way changeset='#{open_changeset_id}'>" +
113 "<tag k='test' v='yes' /></way></osm>"
116 assert_response :precondition_failed,
117 "way upload with no node did not return 'precondition failed'"
119 # create a way inside a closed changeset
120 content "<osm><way changeset='#{closed_changeset_id}'>" +
121 "<nd ref='#{nid1}'/></way></osm>"
124 assert_response :conflict,
125 "way upload to closed changeset did not return 'conflict'"
128 # -------------------------------------
129 # Test deleting ways.
130 # -------------------------------------
133 # first try to delete way without auth
134 delete :delete, :id => current_ways(:visible_way).id
135 assert_response :unauthorized
138 basic_authorization("test@openstreetmap.org", "test");
140 # this shouldn't work as with the 0.6 api we need pay load to delete
141 delete :delete, :id => current_ways(:visible_way).id
142 assert_response :bad_request
144 # Now try without having a changeset
145 content "<osm><way id='#{current_ways(:visible_way).id}'></osm>"
146 delete :delete, :id => current_ways(:visible_way).id
147 assert_response :bad_request
149 # try to delete with an invalid (closed) changeset
150 content update_changeset(current_ways(:visible_way).to_xml,
151 changesets(:normal_user_closed_change).id)
152 delete :delete, :id => current_ways(:visible_way).id
153 assert_response :conflict
155 # try to delete with an invalid (non-existent) changeset
156 content update_changeset(current_ways(:visible_way).to_xml,0)
157 delete :delete, :id => current_ways(:visible_way).id
158 assert_response :conflict
160 # Now try with a valid changeset
161 content current_ways(:visible_way).to_xml
162 delete :delete, :id => current_ways(:visible_way).id
163 assert_response :success
165 # check the returned value - should be the new version number
166 # valid delete should return the new version number, which should
167 # be greater than the old version number
168 assert @response.body.to_i > current_ways(:visible_way).version,
169 "delete request should return a new version number for way"
171 # this won't work since the way is already deleted
172 content current_ways(:invisible_way).to_xml
173 delete :delete, :id => current_ways(:invisible_way).id
174 assert_response :gone
176 # this shouldn't work as the way is used in a relation
177 content current_ways(:used_way).to_xml
178 delete :delete, :id => current_ways(:used_way).id
179 assert_response :precondition_failed,
180 "shouldn't be able to delete a way used in a relation (#{@response.body})"
182 # this won't work since the way never existed
183 delete :delete, :id => 0
184 assert_response :not_found
187 # ------------------------------------------------------------
189 # ------------------------------------------------------------
192 # Try adding a duplicate of an existing tag to a way
193 def test_add_duplicate_tags
195 basic_authorization(users(:normal_user).email, "test")
197 # add an identical tag to the way
198 tag_xml = XML::Node.new("tag")
199 tag_xml['k'] = current_way_tags(:t1).k
200 tag_xml['v'] = current_way_tags(:t1).v
202 # add the tag into the existing xml
203 way_xml = current_ways(:visible_way).to_xml
204 way_xml.find("//osm/way").first << tag_xml
208 put :update, :id => current_ways(:visible_way).id
209 assert_response :bad_request,
210 "adding a duplicate tag to a way should fail with 'bad request'"
214 # Try adding a new duplicate tags to a way
215 def test_new_duplicate_tags
217 basic_authorization(users(:normal_user).email, "test")
219 # create duplicate tag
220 tag_xml = XML::Node.new("tag")
221 tag_xml['k'] = "i_am_a_duplicate"
222 tag_xml['v'] = "foobar"
224 # add the tag into the existing xml
225 way_xml = current_ways(:visible_way).to_xml
227 # add two copies of the tag
228 way_xml.find("//osm/way").first << tag_xml.copy(true) << tag_xml
232 put :update, :id => current_ways(:visible_way).id
233 assert_response :bad_request,
234 "adding new duplicate tags to a way should fail with 'bad request'"
238 # Try adding a new duplicate tags to a way.
239 # But be a bit subtle - use unicode decoding ambiguities to use different
240 # binary strings which have the same decoding.
242 # NOTE: I'm not sure this test is working correctly, as a lot of the tag
243 # keys seem to come out as "addr��housenumber". It might be something to
244 # do with Ruby's unicode handling...?
245 def test_invalid_duplicate_tags
247 basic_authorization(users(:normal_user).email, "test")
249 # add the tag into the existing xml
250 way_str = "<osm><way changeset='1'>"
251 way_str << "<tag k='addr:housenumber' v='1'/>"
253 # all of these keys have the same unicode decoding, but are binary
254 # not equal. libxml should make these identical as it decodes the
256 [ "addr\xc0\xbahousenumber",
257 "addr\xe0\x80\xbahousenumber",
258 "addr\xf0\x80\x80\xbahousenumber" ].each do |key|
259 # copy the XML doc to add the tags
260 way_str_copy = way_str.clone
262 # add all new tags to the way
263 way_str_copy << "<tag k='" << key << "' v='1'/>"
264 way_str_copy << "</way></osm>";
269 assert_response :bad_request,
270 "adding new duplicate tags to a way should fail with 'bad request'"
275 # test that a call to ways_for_node returns all ways that contain the node
276 # and none that don't.
277 def test_ways_for_node
278 # in current fixtures ways 1 and 3 all use node 3. ways 2 and 4
279 # *used* to use it but doesn't.
280 get :ways_for_node, :id => current_nodes(:used_node_1).id
281 assert_response :success
282 ways_xml = XML::Parser.string(@response.body).parse
283 assert_not_nil ways_xml, "failed to parse ways_for_node response"
285 # check that the set of IDs match expectations
286 expected_way_ids = [ current_ways(:visible_way).id,
287 current_ways(:used_way).id
289 found_way_ids = ways_xml.find("//osm/way").collect { |w| w["id"].to_i }
290 assert_equal expected_way_ids, found_way_ids,
291 "expected ways for node #{current_nodes(:used_node_1).id} did not match found"
293 # check the full ways to ensure we're not missing anything
294 expected_way_ids.each do |id|
295 way_xml = ways_xml.find("//osm/way[@id=#{id}]").first
296 assert_ways_are_equal(Way.find(id),
297 Way.from_xml_node(way_xml))
302 # update the changeset_id of a node element
303 def update_changeset(xml, changeset_id)
304 xml_attr_rewrite(xml, 'changeset', changeset_id)
308 # update an attribute in the node element
309 def xml_attr_rewrite(xml, name, value)
310 xml.find("//osm/way").first[name] = value.to_s