3 class RelationVersionsTest < ActionDispatch::IntegrationTest
5 # test that, when tags are updated on a relation, the correct things
6 # happen to the correct tables and the API gives sensible results.
7 # this is to test a case that gregory marler noticed and posted to
9 def test_update_relation_tags
11 changeset = create(:changeset, :user => user)
12 relation = create(:relation)
13 create_list(:relation_tag, 4, :relation => relation)
15 auth_header = bearer_authorization_header user
17 get api_relation_path(relation)
18 assert_response :success
19 rel = xml_parse(@response.body)
20 rel_id = rel.find("//osm/relation").first["id"].to_i
22 # alter one of the tags
23 tag = rel.find("//osm/relation/tag").first
24 tag["v"] = "some changed value"
25 update_changeset(rel, changeset.id)
26 put api_relation_path(rel_id), :params => rel.to_s, :headers => auth_header
27 assert_response :success, "can't update relation: #{@response.body}"
28 new_version = @response.body.to_i
30 # check that the downloaded tags are the same as the uploaded tags...
31 get api_relation_path(rel_id)
32 assert_tags_equal_response rel
34 # check the original one in the current_* table again
35 get api_relation_path(relation)
36 assert_tags_equal_response rel
38 # now check the version in the history
39 get api_relation_version_path(relation, new_version)
40 assert_tags_equal_response rel
44 # test that, when tags are updated on a relation when using the diff
45 # upload function, the correct things happen to the correct tables
46 # and the API gives sensible results. this is to test a case that
47 # gregory marler noticed and posted to josm-dev.
48 def test_update_relation_tags_via_upload
50 changeset = create(:changeset, :user => user)
51 relation = create(:relation)
52 create_list(:relation_tag, 4, :relation => relation)
54 auth_header = bearer_authorization_header user
56 get api_relation_path(relation)
57 assert_response :success
58 rel = xml_parse(@response.body)
59 rel_id = rel.find("//osm/relation").first["id"].to_i
61 # alter one of the tags
62 tag = rel.find("//osm/relation/tag").first
63 tag["v"] = "some changed value"
64 update_changeset(rel, changeset.id)
66 with_controller(Api::ChangesetsController.new) do
67 doc = OSM::API.new.xml_doc
68 change = XML::Node.new "osmChange"
70 modify = XML::Node.new "modify"
72 modify << doc.import(rel.find("//osm/relation").first)
74 post api_changeset_upload_path(changeset), :params => doc.to_s, :headers => auth_header
75 assert_response :success, "can't upload diff relation: #{@response.body}"
76 new_version = xml_parse(@response.body).find("//diffResult/relation").first["new_version"].to_i
79 # check that the downloaded tags are the same as the uploaded tags...
80 get api_relation_path(rel_id)
81 assert_tags_equal_response rel
83 # check the original one in the current_* table again
84 get api_relation_path(relation)
85 assert_tags_equal_response rel
87 # now check the version in the history
88 get api_relation_version_path(relation, new_version)
89 assert_tags_equal_response rel
93 # check that relations are ordered
94 def test_relation_member_ordering
96 changeset = create(:changeset, :user => user)
100 way1 = create(:way_with_nodes, :nodes_count => 2)
101 way2 = create(:way_with_nodes, :nodes_count => 2)
103 auth_header = bearer_authorization_header user
107 <relation changeset='#{changeset.id}'>
108 <member ref='#{node1.id}' type='node' role='first'/>
109 <member ref='#{node2.id}' type='node' role='second'/>
110 <member ref='#{way1.id}' type='way' role='third'/>
111 <member ref='#{way2.id}' type='way' role='fourth'/>
115 doc = XML::Parser.string(doc_str).parse
117 post api_relations_path, :params => doc.to_s, :headers => auth_header
118 assert_response :success, "can't create a relation: #{@response.body}"
119 relation_id = @response.body.to_i
121 # get it back and check the ordering
122 get api_relation_path(relation_id)
123 assert_members_equal_response doc
125 # check the ordering in the history tables:
126 get api_relation_version_path(relation_id, 1)
127 assert_members_equal_response doc, "can't read back version 2 of the relation"
129 # insert a member at the front
130 new_member = XML::Node.new "member"
131 new_member["ref"] = node3.id.to_s
132 new_member["type"] = "node"
133 new_member["role"] = "new first"
134 doc.find("//osm/relation").first.child.prev = new_member
135 # update the version, should be 1?
136 doc.find("//osm/relation").first["id"] = relation_id.to_s
137 doc.find("//osm/relation").first["version"] = 1.to_s
139 # upload the next version of the relation
140 put api_relation_path(relation_id), :params => doc.to_s, :headers => auth_header
141 assert_response :success, "can't update relation: #{@response.body}"
142 assert_equal 2, @response.body.to_i
144 # get it back again and check the ordering again
145 get api_relation_path(relation_id)
146 assert_members_equal_response doc
148 # check the ordering in the history tables:
149 get api_relation_version_path(relation_id, 2)
150 assert_members_equal_response doc, "can't read back version 2 of the relation"
154 # check that relations can contain duplicate members
155 def test_relation_member_duplicates
156 private_user = create(:user, :data_public => false)
158 changeset = create(:changeset, :user => user)
159 node1 = create(:node)
160 node2 = create(:node)
164 <relation changeset='#{changeset.id}'>
165 <member ref='#{node1.id}' type='node' role='forward'/>
166 <member ref='#{node2.id}' type='node' role='forward'/>
167 <member ref='#{node1.id}' type='node' role='forward'/>
168 <member ref='#{node2.id}' type='node' role='forward'/>
172 doc = XML::Parser.string(doc_str).parse
174 ## First try with the private user
175 auth_header = bearer_authorization_header private_user
177 post api_relations_path, :params => doc.to_s, :headers => auth_header
178 assert_response :forbidden
180 ## Now try with the public user
181 auth_header = bearer_authorization_header user
183 post api_relations_path, :params => doc.to_s, :headers => auth_header
184 assert_response :success, "can't create a relation: #{@response.body}"
185 relation_id = @response.body.to_i
187 # get it back and check the ordering
188 get api_relation_path(relation_id)
189 assert_members_equal_response doc
191 # check the ordering in the history tables:
192 get api_relation_version_path(relation_id, 1)
193 assert_members_equal_response doc, "can't read back version 1 of the relation"
197 # test that the ordering of elements in the history is the same as in current.
198 def test_history_ordering
200 changeset = create(:changeset, :user => user)
201 node1 = create(:node)
202 node2 = create(:node)
203 node3 = create(:node)
204 node4 = create(:node)
208 <relation changeset='#{changeset.id}'>
209 <member ref='#{node1.id}' type='node' role='forward'/>
210 <member ref='#{node4.id}' type='node' role='forward'/>
211 <member ref='#{node3.id}' type='node' role='forward'/>
212 <member ref='#{node2.id}' type='node' role='forward'/>
216 doc = XML::Parser.string(doc_str).parse
217 auth_header = bearer_authorization_header user
219 post api_relations_path, :params => doc.to_s, :headers => auth_header
220 assert_response :success, "can't create a relation: #{@response.body}"
221 relation_id = @response.body.to_i
223 # check the ordering in the current tables:
224 get api_relation_path(relation_id)
225 assert_members_equal_response doc
227 # check the ordering in the history tables:
228 get api_relation_version_path(relation_id, 1)
229 assert_members_equal_response doc, "can't read back version 1 of the relation"
235 # assert that tags on relation document +rel+
236 # are equal to tags in response
237 def assert_tags_equal_response(rel)
238 assert_response :success
239 response_xml = xml_parse(@response.body)
241 # turn the XML doc into tags hashes
242 rel_tags = get_tags_as_hash(rel)
243 response_tags = get_tags_as_hash(response_xml)
245 assert_equal rel_tags, response_tags, "Tags should be identical."
249 # checks that the XML document and the response have
250 # members in the same order.
251 def assert_members_equal_response(doc, response_message = "can't read back the relation")
252 assert_response :success, "#{response_message}: #{@response.body}"
253 new_doc = XML::Parser.string(@response.body).parse
255 doc_members = doc.find("//osm/relation/member").collect do |m|
256 [m["ref"].to_i, m["type"].to_sym, m["role"]]
259 new_members = new_doc.find("//osm/relation/member").collect do |m|
260 [m["ref"].to_i, m["type"].to_sym, m["role"]]
263 assert_equal doc_members, new_members, "members are not equal - ordering is wrong? (#{doc}, #{@response.body})"
267 # returns a k->v hash of tags from an xml doc
268 def get_tags_as_hash(a)
269 a.find("//osm/relation/tag").to_h do |tag|
275 # update the changeset_id of a node element
276 def update_changeset(xml, changeset_id)
277 xml_attr_rewrite(xml, "changeset", changeset_id)
281 # update an attribute in the node element
282 def xml_attr_rewrite(xml, name, value)
283 xml.find("//osm/relation").first[name] = value.to_s
290 parser = XML::Parser.string(xml)