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