1 # frozen_string_literal: true
 
   5 class NodeVersionsTest < ActionDispatch::IntegrationTest
 
   7   # test the version call by submitting several revisions of a new node
 
   8   # to the API and ensuring that later calls to version return the
 
   9   # matching versions of the object.
 
  11     private_user = create(:user, :data_public => false)
 
  12     private_node = create(:node, :with_history, :version => 4, :lat => 0, :lon => 0, :changeset => create(:changeset, :user => private_user))
 
  14     node = create(:node, :with_history, :version => 4, :lat => 0, :lon => 0, :changeset => create(:changeset, :user => user))
 
  15     create_list(:node_tag, 2, :node => node)
 
  16     # Ensure that the current tags are propagated to the history too
 
  17     propagate_tags(node, node.old_nodes.last)
 
  19     ## First try this with a non-public user
 
  20     auth_header = request_headers private_user
 
  22     # setup a simple XML node
 
  23     xml_doc = xml_for_node(private_node)
 
  24     xml_node = xml_doc.find("//osm/node").first
 
  25     node_id = private_node.id
 
  27     # keep a hash of the versions => string, as we'll need something
 
  28     # to test against later
 
  31     # save a version for later checking
 
  32     versions[xml_node["version"]] = xml_doc.to_s
 
  34     # randomly move the node about
 
  36       # move the node somewhere else
 
  37       xml_node["lat"] = precision(rand - 0.5).to_s
 
  38       xml_node["lon"] = precision(rand - 0.5).to_s
 
  39       with_controller(NodesController.new) do
 
  40         put api_node_path(node_id), :params => xml_doc.to_s, :headers => auth_header
 
  41         assert_response :forbidden, "Should have rejected node update"
 
  42         xml_node["version"] = @response.body.to_s
 
  44       # save a version for later checking
 
  45       versions[xml_node["version"]] = xml_doc.to_s
 
  48     # add a bunch of random tags
 
  50       xml_tag = XML::Node.new("tag")
 
  51       xml_tag["k"] = random_string
 
  52       xml_tag["v"] = random_string
 
  54       with_controller(NodesController.new) do
 
  55         put api_node_path(node_id), :params => xml_doc.to_s, :headers => auth_header
 
  56         assert_response :forbidden,
 
  57                         "should have rejected node #{node_id} (#{@response.body}) with forbidden"
 
  58         xml_node["version"] = @response.body.to_s
 
  60       # save a version for later checking
 
  61       versions[xml_node["version"]] = xml_doc.to_s
 
  64     # probably should check that they didn't get written to the database
 
  66     ## Now do it with the public user
 
  67     auth_header = request_headers user
 
  69     # setup a simple XML node
 
  71     xml_doc = xml_for_node(node)
 
  72     xml_node = xml_doc.find("//osm/node").first
 
  75     # keep a hash of the versions => string, as we'll need something
 
  76     # to test against later
 
  79     # save a version for later checking
 
  80     versions[xml_node["version"]] = xml_doc.to_s
 
  82     # randomly move the node about
 
  84       # move the node somewhere else
 
  85       xml_node["lat"] = precision(rand - 0.5).to_s
 
  86       xml_node["lon"] = precision(rand - 0.5).to_s
 
  87       with_controller(NodesController.new) do
 
  88         put api_node_path(node_id), :params => xml_doc.to_s, :headers => auth_header
 
  89         assert_response :success
 
  90         xml_node["version"] = @response.body.to_s
 
  92       # save a version for later checking
 
  93       versions[xml_node["version"]] = xml_doc.to_s
 
  96     # add a bunch of random tags
 
  98       xml_tag = XML::Node.new("tag")
 
  99       xml_tag["k"] = random_string
 
 100       xml_tag["v"] = random_string
 
 102       with_controller(NodesController.new) do
 
 103         put api_node_path(node_id), :params => xml_doc.to_s, :headers => auth_header
 
 104         assert_response :success,
 
 105                         "couldn't update node #{node_id} (#{@response.body})"
 
 106         xml_node["version"] = @response.body.to_s
 
 108       # save a version for later checking
 
 109       versions[xml_node["version"]] = xml_doc.to_s
 
 112     # check all the versions
 
 113     versions.each_key do |key|
 
 114       get api_node_version_path(node_id, key.to_i)
 
 116       assert_response :success,
 
 117                       "couldn't get version #{key.to_i} of node #{node_id}"
 
 119       check_node = Node.from_xml(versions[key])
 
 120       api_node = Node.from_xml(@response.body.to_s)
 
 122       assert_nodes_are_equal check_node, api_node
 
 127   # Test that getting the current version is identical to picking
 
 128   # that version with the version URI call.
 
 129   def test_current_version
 
 130     node = create(:node, :with_history)
 
 131     used_node = create(:node, :with_history)
 
 132     create(:way_node, :node => used_node)
 
 133     node_used_by_relationship = create(:node, :with_history)
 
 134     create(:relation_member, :member => node_used_by_relationship)
 
 135     node_with_versions = create(:node, :with_history, :version => 4)
 
 137     create(:node_tag, :node => node)
 
 138     create(:node_tag, :node => used_node)
 
 139     create(:node_tag, :node => node_used_by_relationship)
 
 140     create(:node_tag, :node => node_with_versions)
 
 141     propagate_tags(node, node.old_nodes.last)
 
 142     propagate_tags(used_node, used_node.old_nodes.last)
 
 143     propagate_tags(node_used_by_relationship, node_used_by_relationship.old_nodes.last)
 
 144     propagate_tags(node_with_versions, node_with_versions.old_nodes.last)
 
 146     check_current_version(node)
 
 147     check_current_version(used_node)
 
 148     check_current_version(node_used_by_relationship)
 
 149     check_current_version(node_with_versions)
 
 154   def check_current_version(node_id)
 
 155     # get the current version of the node
 
 156     current_node = with_controller(NodesController.new) do
 
 157       get api_node_path(node_id)
 
 158       assert_response :success, "cant get current node #{node_id}"
 
 159       Node.from_xml(@response.body)
 
 161     assert_not_nil current_node, "getting node #{node_id} returned nil"
 
 163     # get the "old" version of the node from the old_node interface
 
 164     get api_node_version_path(node_id, current_node.version)
 
 165     assert_response :success, "cant get old node #{node_id}, v#{current_node.version}"
 
 166     old_node = Node.from_xml(@response.body)
 
 168     # check the nodes are the same
 
 169     assert_nodes_are_equal current_node, old_node
 
 173   # returns a 16 character long string with some nasty characters in it.
 
 174   # this ought to stress-test the tag handling as well as the versioning.
 
 176     letters = [["!", '"', "$", "&", ";", "@"],
 
 179                ("0".."9").to_a].flatten
 
 180     (1..16).map { letters[rand(letters.length)] }.join
 
 184   # truncate a floating point number to the scale that it is stored in
 
 185   # the database. otherwise rounding errors can produce failing unit
 
 186   # tests when they shouldn't.
 
 188     (f * GeoRecord::SCALE).round.to_f / GeoRecord::SCALE
 
 191   def propagate_tags(node, old_node)
 
 192     node.tags.each do |k, v|
 
 193       create(:old_node_tag, :old_node => old_node, :k => k, :v => v)
 
 197   def request_headers(user)
 
 198     bearer_authorization_header(user).merge("Content-Type" => "application/xml")