Added test for relations_for_node where the relation had been deleted.
[rails.git] / test / functional / relation_controller_test.rb
1 require File.dirname(__FILE__) + '/../test_helper'
2 require 'relation_controller'
3
4 # Re-raise errors caught by the controller.
5 class RelationController; def rescue_action(e) raise e end; end
6
7 class RelationControllerTest < Test::Unit::TestCase
8   api_fixtures
9
10   def setup
11     @controller = RelationController.new
12     @request    = ActionController::TestRequest.new
13     @response   = ActionController::TestResponse.new
14   end
15
16   def basic_authorization(user, pass)
17     @request.env["HTTP_AUTHORIZATION"] = "Basic %s" % Base64.encode64("#{user}:#{pass}")
18   end
19
20   def content(c)
21     @request.env["RAW_POST_DATA"] = c.to_s
22   end
23
24   # -------------------------------------
25   # Test reading relations.
26   # -------------------------------------
27
28   def test_read
29     # check that a visible relation is returned properly
30     get :read, :id => current_relations(:visible_relation).id
31     assert_response :success
32
33     # check that an invisible relation is not returned
34     get :read, :id => current_relations(:invisible_relation).id
35     assert_response :gone
36
37     # check chat a non-existent relation is not returned
38     get :read, :id => 0
39     assert_response :not_found
40   end
41
42   ##
43   # check that all relations containing a particular node, and no extra
44   # relations, are returned from the relations_for_node call.
45   def test_relations_for_node
46     node_id = current_nodes(:node_used_by_relationship).id
47     
48     # fetch all the relations which contain that node
49     get :relations_for_node, :id => node_id
50     assert_response :success
51
52     # count one osm element
53     assert_select "osm[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
54
55     # we should have only two relations
56     assert_select "osm>relation", 2
57
58     # and each of them should contain the node we originally searched for
59     [ :visible_relation, 
60       :used_relation ].each do |r|
61       relation_id = current_relations(r).id
62       assert_select "osm>relation#?", relation_id
63       assert_select "osm>relation#?>member[type=\"node\"][ref=#{node_id}]", relation_id
64     end
65   end
66
67   def test_relations_for_way
68     # check the "relations for way" mode
69     get :relations_for_way, :id => current_ways(:used_way).id
70     assert_response :success
71     # FIXME check whether this contains the stuff we want!
72     if $VERBOSE
73         print @response.body
74     end
75   end
76
77   def test_relations_for_relation
78     # check the "relations for relation" mode
79     get :relations_for_relation, :id => current_relations(:used_relation).id
80     assert_response :success
81     # FIXME check whether this contains the stuff we want!
82     if $VERBOSE
83         print @response.body
84     end
85   end
86
87   def test_full
88     # check the "full" mode
89     get :full, :id => current_relations(:visible_relation).id
90     assert_response :success
91     # FIXME check whether this contains the stuff we want!
92     if $VERBOSE
93         print @response.body
94     end
95   end
96
97   # -------------------------------------
98   # Test simple relation creation.
99   # -------------------------------------
100
101   def test_create
102     basic_authorization "test@openstreetmap.org", "test"
103     
104     # put the relation in a dummy fixture changset
105     changeset_id = changesets(:normal_user_first_change).id
106
107     # create an relation without members
108     content "<osm><relation changeset='#{changeset_id}'><tag k='test' v='yes' /></relation></osm>"
109     put :create
110     # hope for success
111     assert_response :success, 
112         "relation upload did not return success status"
113     # read id of created relation and search for it
114     relationid = @response.body
115     checkrelation = Relation.find(relationid)
116     assert_not_nil checkrelation, 
117         "uploaded relation not found in data base after upload"
118     # compare values
119     assert_equal checkrelation.members.length, 0, 
120         "saved relation contains members but should not"
121     assert_equal checkrelation.tags.length, 1, 
122         "saved relation does not contain exactly one tag"
123     assert_equal changeset_id, checkrelation.changeset.id,
124         "saved relation does not belong in the changeset it was assigned to"
125     assert_equal users(:normal_user).id, checkrelation.changeset.user_id, 
126         "saved relation does not belong to user that created it"
127     assert_equal true, checkrelation.visible, 
128         "saved relation is not visible"
129     # ok the relation is there but can we also retrieve it?
130     get :read, :id => relationid
131     assert_response :success
132
133
134     # create an relation with a node as member
135     nid = current_nodes(:used_node_1).id
136     content "<osm><relation changeset='#{changeset_id}'>" +
137       "<member type='node' ref='#{nid}' role='some'/>" +
138       "<tag k='test' v='yes' /></relation></osm>"
139     put :create
140     # hope for success
141     assert_response :success, 
142         "relation upload did not return success status"
143     # read id of created relation and search for it
144     relationid = @response.body
145     checkrelation = Relation.find(relationid)
146     assert_not_nil checkrelation, 
147         "uploaded relation not found in data base after upload"
148     # compare values
149     assert_equal checkrelation.members.length, 1, 
150         "saved relation does not contain exactly one member"
151     assert_equal checkrelation.tags.length, 1, 
152         "saved relation does not contain exactly one tag"
153     assert_equal changeset_id, checkrelation.changeset.id,
154         "saved relation does not belong in the changeset it was assigned to"
155     assert_equal users(:normal_user).id, checkrelation.changeset.user_id, 
156         "saved relation does not belong to user that created it"
157     assert_equal true, checkrelation.visible, 
158         "saved relation is not visible"
159     # ok the relation is there but can we also retrieve it?
160     
161     get :read, :id => relationid
162     assert_response :success
163
164     # create an relation with a way and a node as members
165     nid = current_nodes(:used_node_1).id
166     wid = current_ways(:used_way).id
167     content "<osm><relation changeset='#{changeset_id}'>" +
168       "<member type='node' ref='#{nid}' role='some'/>" +
169       "<member type='way' ref='#{wid}' role='other'/>" +
170       "<tag k='test' v='yes' /></relation></osm>"
171     put :create
172     # hope for success
173     assert_response :success, 
174         "relation upload did not return success status"
175     # read id of created relation and search for it
176     relationid = @response.body
177     checkrelation = Relation.find(relationid)
178     assert_not_nil checkrelation, 
179         "uploaded relation not found in data base after upload"
180     # compare values
181     assert_equal checkrelation.members.length, 2, 
182         "saved relation does not have exactly two members"
183     assert_equal checkrelation.tags.length, 1, 
184         "saved relation does not contain exactly one tag"
185     assert_equal changeset_id, checkrelation.changeset.id,
186         "saved relation does not belong in the changeset it was assigned to"
187     assert_equal users(:normal_user).id, checkrelation.changeset.user_id, 
188         "saved relation does not belong to user that created it"
189     assert_equal true, checkrelation.visible, 
190         "saved relation is not visible"
191     # ok the relation is there but can we also retrieve it?
192     get :read, :id => relationid
193     assert_response :success
194
195   end
196
197   # -------------------------------------
198   # Test creating some invalid relations.
199   # -------------------------------------
200
201   def test_create_invalid
202     basic_authorization "test@openstreetmap.org", "test"
203
204     # put the relation in a dummy fixture changset
205     changeset_id = changesets(:normal_user_first_change).id
206
207     # create a relation with non-existing node as member
208     content "<osm><relation changeset='#{changeset_id}'>" +
209       "<member type='node' ref='0'/><tag k='test' v='yes' />" +
210       "</relation></osm>"
211     put :create
212     # expect failure
213     assert_response :precondition_failed, 
214         "relation upload with invalid node did not return 'precondition failed'"
215   end
216
217   # -------------------------------------
218   # Test deleting relations.
219   # -------------------------------------
220   
221   def test_delete
222     # first try to delete relation without auth
223     delete :delete, :id => current_relations(:visible_relation).id
224     assert_response :unauthorized
225
226     # now set auth
227     basic_authorization("test@openstreetmap.org", "test");  
228
229     # this shouldn't work, as we should need the payload...
230     delete :delete, :id => current_relations(:visible_relation).id
231     assert_response :bad_request
232
233     # try to delete without specifying a changeset
234     content "<osm><relation id='#{current_relations(:visible_relation).id}'/></osm>"
235     delete :delete, :id => current_relations(:visible_relation).id
236     assert_response :conflict
237
238     # try to delete with an invalid (closed) changeset
239     content update_changeset(current_relations(:visible_relation).to_xml,
240                              changesets(:normal_user_closed_change).id)
241     delete :delete, :id => current_relations(:visible_relation).id
242     assert_response :conflict
243
244     # try to delete with an invalid (non-existent) changeset
245     content update_changeset(current_relations(:visible_relation).to_xml,0)
246     delete :delete, :id => current_relations(:visible_relation).id
247     assert_response :conflict
248
249     # this won't work because the relation is in-use by another relation
250     content(relations(:used_relation).to_xml)
251     delete :delete, :id => current_relations(:used_relation).id
252     assert_response :precondition_failed, 
253        "shouldn't be able to delete a relation used in a relation (#{@response.body})"
254
255     # this should work when we provide the appropriate payload...
256     content(relations(:visible_relation).to_xml)
257     delete :delete, :id => current_relations(:visible_relation).id
258     assert_response :success
259
260     # valid delete should return the new version number, which should
261     # be greater than the old version number
262     assert @response.body.to_i > current_relations(:visible_relation).version,
263        "delete request should return a new version number for relation"
264
265     # this won't work since the relation is already deleted
266     content(relations(:invisible_relation).to_xml)
267     delete :delete, :id => current_relations(:invisible_relation).id
268     assert_response :gone
269
270     # this works now because the relation which was using this one 
271     # has been deleted.
272     content(relations(:used_relation).to_xml)
273     delete :delete, :id => current_relations(:used_relation).id
274     assert_response :success, 
275        "should be able to delete a relation used in an old relation (#{@response.body})"
276
277     # this won't work since the relation never existed
278     delete :delete, :id => 0
279     assert_response :not_found
280   end
281
282   ##
283   # update the changeset_id of a node element
284   def update_changeset(xml, changeset_id)
285     xml_attr_rewrite(xml, 'changeset', changeset_id)
286   end
287
288   ##
289   # update an attribute in the node element
290   def xml_attr_rewrite(xml, name, value)
291     xml.find("//osm/relation").first[name] = value.to_s
292     return xml
293   end
294
295   ##
296   # parse some xml
297   def xml_parse(xml)
298     parser = XML::Parser.new
299     parser.string = xml
300     parser.parse
301   end
302 end