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