]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/5637'
authorTom Hughes <tom@compton.nu>
Tue, 11 Feb 2025 17:53:00 +0000 (17:53 +0000)
committerTom Hughes <tom@compton.nu>
Tue, 11 Feb 2025 17:53:00 +0000 (17:53 +0000)
53 files changed:
Gemfile.lock
app/abilities/api_ability.rb
app/assets/javascripts/application.js
app/assets/javascripts/index/contextmenu.js
app/assets/javascripts/index/layers/data.js
app/assets/javascripts/index/query.js
app/assets/javascripts/leaflet.locate.js
app/assets/javascripts/osm.js.erb
app/controllers/api/nodes/relations_controller.rb
app/controllers/api/nodes/ways_controller.rb
app/controllers/api/old_elements_controller.rb
app/controllers/api/old_nodes_controller.rb
app/controllers/api/old_relations_controller.rb
app/controllers/api/old_ways_controller.rb
app/controllers/api/relations/relations_controller.rb
app/controllers/api/ways/relations_controller.rb
app/controllers/application_controller.rb
app/controllers/site_controller.rb
app/views/api/old_nodes/index.json.jbuilder [moved from app/views/api/old_nodes/history.json.jbuilder with 100% similarity]
app/views/api/old_nodes/index.xml.builder [moved from app/views/api/old_nodes/history.xml.builder with 100% similarity]
app/views/api/old_relations/index.json.jbuilder [moved from app/views/api/old_relations/history.json.jbuilder with 100% similarity]
app/views/api/old_relations/index.xml.builder [moved from app/views/api/old_relations/history.xml.builder with 100% similarity]
app/views/api/old_ways/index.json.jbuilder [moved from app/views/api/old_ways/history.json.jbuilder with 100% similarity]
app/views/api/old_ways/index.xml.builder [moved from app/views/api/old_ways/history.xml.builder with 100% similarity]
app/views/layouts/_offline_flash.erb [new file with mode: 0644]
app/views/old_elements/_actions.html.erb
app/views/old_elements/index.html.erb
app/views/site/_not_public_flash.erb [new file with mode: 0644]
app/views/site/edit.html.erb
config/eslint.js
config/locales/de.yml
config/locales/el.yml
config/locales/en.yml
config/locales/gd.yml
config/locales/gl.yml
config/locales/it.yml
config/locales/lb.yml
config/locales/ru.yml
config/locales/skr-arab.yml
config/locales/sr.yml
config/routes.rb
config/settings.yml
lib/tasks/eslint.rake
test/controllers/api/old_nodes_controller_test.rb
test/controllers/api/old_relations_controller_test.rb
test/controllers/api/old_ways_controller_test.rb
test/controllers/api/relations_controller_test.rb
test/controllers/old_nodes_controller_test.rb
test/controllers/old_relations_controller_test.rb
test/controllers/old_ways_controller_test.rb
test/integration/node_versions_test.rb [new file with mode: 0644]
test/integration/way_versions_test.rb [new file with mode: 0644]
yarn.lock

index 0fd4dc5ea1662aa9055b3f31df547b9020149eb4..9475cb663e83f8b3cab7894c249e2fafdf9a78cc 100644 (file)
@@ -85,23 +85,24 @@ GEM
     annotate (3.2.0)
       activerecord (>= 3.2, < 8.0)
       rake (>= 10.4, < 14.0)
-    argon2 (2.3.0)
+    argon2 (2.3.2)
       ffi (~> 1.15)
       ffi-compiler (~> 1.0)
     ast (2.4.2)
     autoprefixer-rails (10.4.19.0)
       execjs (~> 2)
     aws-eventstream (1.3.0)
-    aws-partitions (1.1044.0)
-    aws-sdk-core (3.217.1)
+    aws-partitions (1.1049.0)
+    aws-sdk-core (3.218.1)
       aws-eventstream (~> 1, >= 1.3.0)
       aws-partitions (~> 1, >= 1.992.0)
       aws-sigv4 (~> 1.9)
+      base64
       jmespath (~> 1, >= 1.6.1)
-    aws-sdk-kms (1.97.0)
+    aws-sdk-kms (1.98.0)
       aws-sdk-core (~> 3, >= 3.216.0)
       aws-sigv4 (~> 1.5)
-    aws-sdk-s3 (1.179.0)
+    aws-sdk-s3 (1.180.0)
       aws-sdk-core (~> 3, >= 3.216.0)
       aws-sdk-kms (~> 1)
       aws-sigv4 (~> 1.5)
@@ -211,9 +212,10 @@ GEM
       railties (>= 5)
     doorkeeper-i18n (5.2.7)
       doorkeeper (>= 5.2)
-    doorkeeper-openid_connect (1.8.10)
+    doorkeeper-openid_connect (1.8.11)
       doorkeeper (>= 5.5, < 5.9)
       jwt (>= 2.5)
+      ostruct (>= 0.5)
     drb (2.2.1)
     dry-configurable (1.3.0)
       dry-core (~> 1.1)
@@ -321,8 +323,8 @@ GEM
       image_optim (~> 0.24)
       railties
       sprockets
-    image_processing (1.13.0)
-      mini_magick (>= 4.9.5, < 5)
+    image_processing (1.14.0)
+      mini_magick (>= 4.9.5, < 6)
       ruby-vips (>= 2.0.17, < 3)
     image_size (3.4.0)
     in_threads (1.6.0)
@@ -340,7 +342,7 @@ GEM
       rails-dom-testing (>= 1, < 3)
       railties (>= 4.2.0)
       thor (>= 0.14, < 2.0)
-    json (2.9.1)
+    json (2.10.1)
     jwt (2.10.1)
       base64
     kgio (2.11.4)
@@ -369,7 +371,9 @@ GEM
     marcel (1.0.4)
     matrix (0.4.2)
     maxminddb (0.1.22)
-    mini_magick (4.13.2)
+    mini_magick (5.1.2)
+      benchmark
+      logger
     mini_mime (1.1.5)
     mini_portile2 (2.8.8)
     mini_racer (0.9.0)
@@ -377,21 +381,21 @@ GEM
     minitest (5.25.4)
     minitest-focus (1.4.0)
       minitest (>= 4, < 6)
-    msgpack (1.7.5)
+    msgpack (1.8.0)
     multi_json (1.15.0)
     multi_xml (0.7.1)
       bigdecimal (~> 3.1)
     nap (1.1.0)
     net-http (0.6.0)
       uri
-    net-imap (0.5.5)
+    net-imap (0.5.6)
       date
       net-protocol
     net-pop (0.1.2)
       net-protocol
     net-protocol (0.2.2)
       timeout
-    net-smtp (0.5.0)
+    net-smtp (0.5.1)
       net-protocol
     nio4r (2.7.4)
     nokogiri (1.18.2)
@@ -456,7 +460,7 @@ GEM
       iniparse (~> 1.4)
       rexml (>= 3.3.9)
     parallel (1.26.3)
-    parser (3.3.7.0)
+    parser (3.3.7.1)
       ast (~> 2.4.1)
       racc
     pg (1.5.9)
@@ -536,7 +540,7 @@ GEM
     rb-inotify (0.11.1)
       ffi (~> 1.0)
     rchardet (1.9.0)
-    rdoc (6.11.0)
+    rdoc (6.12.0)
       psych (>= 4.0.0)
     regexp_parser (2.10.0)
     reline (0.6.0)
@@ -549,7 +553,7 @@ GEM
     rouge (4.5.1)
     rtlcss (0.2.1)
       mini_racer (>= 0.6.3)
-    rubocop (1.71.1)
+    rubocop (1.71.2)
       json (~> 2.3)
       language_server-protocol (>= 3.17.0)
       parallel (~> 1.10)
@@ -580,7 +584,7 @@ GEM
       rubocop (~> 1.0)
     ruby-openid (2.9.2)
     ruby-progressbar (1.13.0)
-    ruby-vips (2.2.2)
+    ruby-vips (2.2.3)
       ffi (~> 1.12)
       logger
     rubyzip (2.4.1)
@@ -649,7 +653,7 @@ GEM
       simpleidn
     vendorer (0.2.0)
     version_gem (1.1.4)
-    webmock (3.24.0)
+    webmock (3.25.0)
       addressable (>= 2.8.0)
       crack (>= 0.3.2)
       hashdiff (>= 0.4.0, < 2.0.0)
index 55476ab53f72440f5871b8df3a6419c3fd83c82b..e774f6820df3f364c3d766f1c2bd25129f12a0dc 100644 (file)
@@ -15,8 +15,7 @@ class ApiAbility
       can [:read, :download], Changeset
       can :read, Tracepoint
       can :read, User
-      can :read, [Node, Way, Relation]
-      can [:history, :read], [OldNode, OldWay, OldRelation]
+      can :read, [Node, Way, Relation, OldNode, OldWay, OldRelation]
       can :read, UserBlock
 
       if user&.active?
index 86a0a0789962abcc08c9de91aaf853d3991b8cbf..2e13f69671bec7253adbe5c98887a33c105d7725 100644 (file)
@@ -113,13 +113,13 @@ $(document).ready(function () {
    */
   setTimeout(function () {
     $("header").children(":visible").each(function (i, e) {
-      headerWidth = headerWidth + $(e).outerWidth();
+      headerWidth += $(e).outerWidth();
     });
 
     $("body").addClass("compact-nav");
 
     $("header").children(":visible").each(function (i, e) {
-      compactWidth = compactWidth + $(e).outerWidth();
+      compactWidth += $(e).outerWidth();
     });
 
     $("body").removeClass("compact-nav");
index fea7e73145415ecf36bca270b53f19feab5683f3..d7e6b427da6ce585a03b8e0581ddfd793e9d9a24 100644 (file)
@@ -65,9 +65,8 @@ OSM.initializeContextMenu = function (map) {
   function getDirectionsEndpointCoordinatesFromInput(input) {
     if (input.attr("data-lat") && input.attr("data-lon")) {
       return input.attr("data-lat") + "," + input.attr("data-lon");
-    } else {
-      return $(input).val();
     }
+    return $(input).val();
   }
 
   var updateMenu = function updateMenu() {
index dc522af418d809f6e16c90ccf5b91a67bf211494..e6a7cc66684be0323361d21758156a9ee816ffb8 100644 (file)
@@ -121,7 +121,7 @@ OSM.initializeDataLayer = function (map) {
       },
       error: function (XMLHttpRequest, textStatus) {
         dataLoader = null;
-        if (textStatus === "abort") { return; }
+        if (textStatus === "abort") return;
 
         function closeError() {
           $("#browse_status").empty();
index 5c8ee88760ceb549adb01ed81efdfb2797bae47d..54d5e080fb0f5675a968bcd720f9a0373ae5e23c 100644 (file)
@@ -115,17 +115,16 @@ OSM.Query = function (map) {
       }
     }
 
-    if (tags.name) {
-      return tags.name;
-    } else if (tags.ref) {
-      return tags.ref;
-    } else if (tags["addr:housename"]) {
-      return tags["addr:housename"];
-    } else if (tags["addr:housenumber"] && tags["addr:street"]) {
+    for (const key of ["name", "ref", "addr:housename"]) {
+      if (tags[key]) {
+        return tags[key];
+      }
+    }
+
+    if (tags["addr:housenumber"] && tags["addr:street"]) {
       return tags["addr:housenumber"] + " " + tags["addr:street"];
-    } else {
-      return "#" + feature.id;
     }
+    return "#" + feature.id;
   }
 
   function featureGeometry(feature) {
@@ -285,10 +284,11 @@ OSM.Query = function (map) {
       .hide();
 
     if (marker) map.removeLayer(marker);
-    marker = L.circle(latlng, Object.assign({
+    marker = L.circle(latlng, {
       radius: radius,
-      className: "query-marker"
-    }, featureStyle)).addTo(map);
+      className: "query-marker",
+      ...featureStyle
+    }).addTo(map);
 
     runQuery(latlng, radius, nearby, $("#query-nearby"), false);
     runQuery(latlng, radius, isin, $("#query-isin"), true, compareSize);
index d43a5e458fe4e1615f445509bb32bf9c230d8839..d199292083d93bbbded0586326f6f5e09a0056dc 100644 (file)
@@ -1,5 +1,5 @@
 L.OSM.locate = function (options) {
-  var control = L.control.locate(Object.assign({
+  var control = L.control.locate({
     icon: "icon geolocate",
     iconLoading: "icon geolocate",
     strings: {
@@ -7,8 +7,9 @@ L.OSM.locate = function (options) {
       popup: function (options) {
         return I18n.t("javascripts.map.locate." + options.unit + "Popup", { count: options.distance });
       }
-    }
-  }, options));
+    },
+    ...options
+  });
 
   control.onAdd = function (map) {
     var container = Object.getPrototypeOf(this).onAdd.apply(this, [map]);
index 030c51a08e6901b0e1ce524f851e2c6430ce6466..062d537ffe8347195e8a70d588400ae725674a5a 100644 (file)
@@ -62,7 +62,8 @@ OSM = {
   },
 
   mapParams: function (search) {
-    var params = OSM.params(search), mapParams = {};
+    var params = OSM.params(search),
+        mapParams = {};
 
     if (params.mlon && params.mlat) {
       mapParams.marker = true;
index 0f0409e1927a735213acac2dd1f1841365d9b0c4..c6b33eab81242767bfd6eb6a0f9df849a4bfd623 100644 (file)
@@ -6,13 +6,12 @@ module Api
       before_action :set_request_formats
 
       def index
-        relation_ids = RelationMember.where(:member_type => "Node", :member_id => params[:node_id]).collect(&:relation_id).uniq
-
-        @relations = []
-
-        Relation.find(relation_ids).each do |relation|
-          @relations << relation if relation.visible
-        end
+        @relations = Relation
+                     .visible
+                     .where(:id => RelationMember.where(
+                       :member_type => "Node",
+                       :member_id => params[:node_id]
+                     ).select(:relation_id))
 
         # Render the result
         respond_to do |format|
index 2a71f1903956e001d893487c8d635c7c47152e66..cdbdc07d0becd36fdd0311b00d6fdb832efa8ccc 100644 (file)
@@ -10,9 +10,11 @@ module Api
       # :node_id parameter. note that this used to return deleted ways as well, but
       # this seemed not to be the expected behaviour, so it was removed.
       def index
-        way_ids = WayNode.where(:node_id => params[:node_id]).collect { |ws| ws.id[0] }.uniq
-
-        @ways = Way.where(:id => way_ids, :visible => true)
+        @ways = Way
+                .visible
+                .where(:id => WayNode.where(
+                  :node_id => params[:node_id]
+                ).select(:way_id))
 
         # Render the result
         respond_to do |format|
index 73e57c1f82355415baeef6a4ee044e3a741b942c..bdbc5e392e21dd00409b5f93dc3494e00f7de334 100644 (file)
@@ -4,17 +4,17 @@
 module Api
   class OldElementsController < ApiController
     before_action :check_api_writable, :only => [:redact]
-    before_action :setup_user_auth, :only => [:history, :show]
+    before_action :setup_user_auth, :only => [:index, :show]
     before_action :authorize, :only => [:redact]
 
     authorize_resource
 
-    before_action :lookup_old_element, :except => [:history]
-    before_action :lookup_old_element_versions, :only => [:history]
+    before_action :lookup_old_element, :except => [:index]
+    before_action :lookup_old_element_versions, :only => [:index]
 
     before_action :set_request_formats, :except => [:redact]
 
-    def history
+    def index
       # the .where() method used in the lookup_old_element_versions
       # call won't throw an error if no records are found, so we have
       # to do that ourselves.
index c2831c48ba558e34b0b937f0a423d1818d571591..b63761af9cfb96353cbb4dfd56d39735ab46052e 100644 (file)
@@ -3,11 +3,11 @@ module Api
     private
 
     def lookup_old_element
-      @old_element = OldNode.find([params[:id], params[:version]])
+      @old_element = OldNode.find([params[:node_id], params[:version]])
     end
 
     def lookup_old_element_versions
-      @elements = OldNode.where(:node_id => params[:id]).order(:version)
+      @elements = OldNode.where(:node_id => params[:node_id]).order(:version)
     end
   end
 end
index 4679384dd3877084ad9378a8e17b6aa75e9c606d..c065c657d1a787a4eb8b14a075b226164dcfbc74 100644 (file)
@@ -3,11 +3,11 @@ module Api
     private
 
     def lookup_old_element
-      @old_element = OldRelation.find([params[:id], params[:version]])
+      @old_element = OldRelation.find([params[:relation_id], params[:version]])
     end
 
     def lookup_old_element_versions
-      @elements = OldRelation.where(:relation_id => params[:id]).order(:version)
+      @elements = OldRelation.where(:relation_id => params[:relation_id]).order(:version)
     end
   end
 end
index 0afa3059ccfce9a9ff1b350e7fbe1f5c3f41b82d..654100767f06e833c46f4ce3c400caa9f8cd3487 100644 (file)
@@ -3,11 +3,11 @@ module Api
     private
 
     def lookup_old_element
-      @old_element = OldWay.find([params[:id], params[:version]])
+      @old_element = OldWay.find([params[:way_id], params[:version]])
     end
 
     def lookup_old_element_versions
-      @elements = OldWay.where(:way_id => params[:id]).order(:version)
+      @elements = OldWay.where(:way_id => params[:way_id]).order(:version)
     end
   end
 end
index 1769e1396ace5bda28da782864c0bf0acec6f261..9b829252645aa26a9528270e1726dcd3f31f14da 100644 (file)
@@ -6,13 +6,12 @@ module Api
       before_action :set_request_formats
 
       def index
-        relation_ids = RelationMember.where(:member_type => "Relation", :member_id => params[:relation_id]).collect(&:relation_id).uniq
-
-        @relations = []
-
-        Relation.find(relation_ids).each do |relation|
-          @relations << relation if relation.visible
-        end
+        @relations = Relation
+                     .visible
+                     .where(:id => RelationMember.where(
+                       :member_type => "Relation",
+                       :member_id => params[:relation_id]
+                     ).select(:relation_id))
 
         # Render the result
         respond_to do |format|
index fcd8b40dd03ab714257c4bc93b22762069026cd2..4188dfe4eceb637d9107cd7a73ee12372424e098 100644 (file)
@@ -6,13 +6,12 @@ module Api
       before_action :set_request_formats
 
       def index
-        relation_ids = RelationMember.where(:member_type => "Way", :member_id => params[:way_id]).collect(&:relation_id).uniq
-
-        @relations = []
-
-        Relation.find(relation_ids).each do |relation|
-          @relations << relation if relation.visible
-        end
+        @relations = Relation
+                     .visible
+                     .where(:id => RelationMember.where(
+                       :member_type => "Way",
+                       :member_id => params[:way_id]
+                     ).select(:relation_id))
 
         # Render the result
         respond_to do |format|
index 176fd8c2e060213d8264c1ccd1dd8cddca281df6..a7235241c14f95f46661073c7fe01e7165d6d246 100644 (file)
@@ -259,12 +259,7 @@ class ApplicationController < ActionController::Base
 
     request.content_security_policy = policy
 
-    case Settings.status
-    when "database_offline", "api_offline"
-      flash.now[:warning] = t("layouts.osm_offline")
-    when "database_readonly", "api_readonly"
-      flash.now[:warning] = t("layouts.osm_read_only")
-    end
+    flash.now[:warning] = { :partial => "layouts/offline_flash" } unless api_status == "online"
 
     request.xhr? ? "xhr" : "map"
   end
index 9adbaa1953fd9fe774bf9bb90eb130da53aed90e..5110be0197ab21face71e30427ac5b29c04b7092 100644 (file)
@@ -107,6 +107,14 @@ class SiteController < ApplicationController
     rescue ActiveRecord::RecordNotFound
       # don't try and derive a location from a missing/deleted object
     end
+
+    if api_status != "online"
+      flash.now[:warning] = { :partial => "layouts/offline_flash" }
+    elsif current_user && !current_user.data_public?
+      flash.now[:warning] = { :partial => "not_public_flash" }
+    else
+      @enable_editor = true
+    end
   end
 
   def copyright
@@ -129,11 +137,7 @@ class SiteController < ApplicationController
   def export; end
 
   def offline
-    flash.now[:warning] = if Settings.status == "database_offline"
-                            t("layouts.osm_offline")
-                          else
-                            t("layouts.osm_read_only")
-                          end
+    flash.now[:warning] = { :partial => "layouts/offline_flash" }
     render :html => nil, :layout => true
   end
 
diff --git a/app/views/layouts/_offline_flash.erb b/app/views/layouts/_offline_flash.erb
new file mode 100644 (file)
index 0000000..364788d
--- /dev/null
@@ -0,0 +1,26 @@
+<div class="d-flex flex-column gap-2">
+  <% if %w[database_offline api_offline].include? Settings.status %>
+    <p class="mb-0">
+      <%= t(".osm_offline") %>
+    </p>
+  <% elsif %w[database_readonly api_readonly].include? Settings.status %>
+    <p class="mb-0">
+      <%= t(".osm_read_only") %>
+    </p>
+  <% end %>
+
+  <% if Settings.status_expected_restore_date %>
+    <% expected_restore_time = Time.parse(Settings.status_expected_restore_date).utc %>
+    <% if expected_restore_time > Time.now.utc %>
+      <p class="mb-0">
+        <%= t ".expected_restore_html", :time => friendly_date(expected_restore_time) %>
+      </p>
+    <% end %>
+  <% end %>
+
+  <% if Settings.status_announcement_url %>
+    <p class="mb-0">
+      <%= link_to t(".announcement"), Settings.status_announcement_url %>
+    </p>
+  <% end %>
+</div>
index 36a16abb4543ffb74c3a00276c5e34e9d877b932..b4d28123ce4f38be33d3e263d8a40efbce9fbd71 100644 (file)
@@ -2,7 +2,7 @@
   <%= link_to t("browse.view_details"), :controller => @type.pluralize, :action => :show %>
   <% if !@feature.redacted? %>
     &middot;
-    <%= link_to t("browse.download_xml"), :controller => "api/old_#{@type.pluralize}", :action => :show %>
+    <%= link_to t("browse.download_xml"), send(:"api_#{@type}_version_path", *@feature.id) %>
   <% elsif current_user&.moderator? %>
     &middot;
     <% if !params[:show_redactions] %>
index d4ecbfa60480c618041bb7902bd601abd91ec644..eaf7787fa8d2c6f92e7399ee70e9ecb2d25d0a63 100644 (file)
@@ -5,7 +5,7 @@
 <%= render :partial => "browse/#{@type}", :collection => @feature.send(:"old_#{@type}s").reverse %>
 
 <div class='secondary-actions'>
-  <%= link_to t("browse.download_xml"), :controller => "api/old_#{@type.pluralize}", :action => "history" %>
+  <%= link_to t("browse.download_xml"), send(:"api_#{@type}_versions_path", @feature.id) %>
   &middot;
   <%= link_to t("browse.view_details"), :controller => @type.pluralize, :action => :show %>
   <% if params[:show_redactions] %>
diff --git a/app/views/site/_not_public_flash.erb b/app/views/site/_not_public_flash.erb
new file mode 100644 (file)
index 0000000..bcd010f
--- /dev/null
@@ -0,0 +1,3 @@
+<p><%= t ".not_public" %></p>
+<p><%= t ".not_public_description_html", :user_page => (link_to t(".user_page_link"), edit_account_path(:anchor => "public")) %></p>
+<p><%= t ".anon_edits_html", :link => link_to(t(".anon_edits_link_text"), t(".anon_edits_link")) %></p>
index 1eb73382279b638866d08af61e302681e5cff858..6d463df7848dbd52138ebad1c12640d2671d61af 100644 (file)
@@ -1,17 +1,5 @@
 <% content_for :content do %>
-  <% if Settings.status == "database_offline" or Settings.status == "api_offline" %>
-    <div class="alert alert-warning text-center">
-        <p class="my-2"><%= t "layouts.osm_offline" %></p>
-    </div>
-  <% elsif Settings.status == "database_readonly" or Settings.status == "api_readonly" %>
-    <div class="alert alert-warning text-center">
-        <p class="my-2"><%= t "layouts.osm_read_only" %></p>
-    </div>
-  <% elsif !current_user.data_public? %>
-    <p><%= t ".not_public" %></p>
-    <p><%= t ".not_public_description_html", :user_page => (link_to t(".user_page_link"), edit_account_path(:anchor => "public")) %></p>
-    <p><%= t ".anon_edits_html", :link => link_to(t(".anon_edits_link_text"), t(".anon_edits_link")) %></p>
-  <% else %>
+  <% if @enable_editor %>
     <%= render :partial => preferred_editor %>
   <% end %>
 <% end %>
index 90040f7bfae41cdaf6e7deb55f79d4bc29d86e4f..c968d9e9a568efabe1539ac70af6a5e63901bdd0 100644 (file)
@@ -1,3 +1,5 @@
+/* eslint sort-keys: ["error", "asc", {minKeys: 5}] */
+
 const globals = require("globals");
 const js = require("@eslint/js");
 const erb = require("eslint-plugin-erb");
@@ -6,6 +8,14 @@ const stylisticJs = require("@stylistic/eslint-plugin-js");
 module.exports = [
   js.configs.recommended,
   erb.configs.recommended,
+  {
+    ignores: [
+      "app/assets/javascripts/i18n/",
+      "coverage/assets/",
+      "public/assets/",
+      "vendor/"
+    ]
+  },
   {
     plugins: {
       "@stylistic": stylisticJs
@@ -19,8 +29,8 @@ module.exports = [
         Cookies: "readonly",
         I18n: "readonly",
         L: "readonly",
-        OSM: "writable",
         Matomo: "readonly",
+        OSM: "writable",
         Turbo: "readonly",
         updateLinks: "readonly"
       }
@@ -47,23 +57,25 @@ module.exports = [
       "@stylistic/eol-last": "error",
       "@stylistic/func-call-spacing": "error",
       "@stylistic/indent": ["error", 2, {
-        SwitchCase: 1,
-        VariableDeclarator: "first",
+        CallExpression: { arguments: "first" },
         FunctionDeclaration: { parameters: "first" },
         FunctionExpression: { parameters: "first" },
-        CallExpression: { arguments: "first" }
+        SwitchCase: 1,
+        VariableDeclarator: "first"
       }],
       "@stylistic/key-spacing": "error",
       "@stylistic/keyword-spacing": "error",
+      "@stylistic/max-statements-per-line": "error",
       "@stylistic/no-floating-decimal": "error",
       "@stylistic/no-mixed-operators": "error",
-      "@stylistic/no-multiple-empty-lines": "error",
       "@stylistic/no-multi-spaces": "error",
+      "@stylistic/no-multiple-empty-lines": "error",
       "@stylistic/no-trailing-spaces": "error",
       "@stylistic/no-whitespace-before-property": "error",
       "@stylistic/object-curly-newline": ["error", { consistent: true }],
       "@stylistic/object-curly-spacing": ["error", "always"],
       "@stylistic/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
+      "@stylistic/one-var-declaration-per-line": "error",
       "@stylistic/operator-linebreak": ["error", "after"],
       "@stylistic/padded-blocks": ["error", "never"],
       "@stylistic/quote-props": ["error", "consistent-as-needed", { keywords: true, numbers: true }],
@@ -91,6 +103,7 @@ module.exports = [
       "no-caller": "error",
       "no-console": "warn",
       "no-div-regex": "error",
+      "no-else-return": ["error", { allowElseIf: false }],
       "no-eq-null": "error",
       "no-eval": "error",
       "no-extend-native": "error",
@@ -101,8 +114,8 @@ module.exports = [
       "no-implied-eval": "error",
       "no-invalid-this": "error",
       "no-iterator": "error",
-      "no-labels": "error",
       "no-label-var": "error",
+      "no-labels": "error",
       "no-lone-blocks": "error",
       "no-lonely-if": "error",
       "no-loop-func": "error",
@@ -126,12 +139,14 @@ module.exports = [
       "no-unneeded-ternary": "error",
       "no-unused-expressions": "off",
       "no-unused-vars": ["error", { caughtErrors: "none" }],
+      "no-use-before-define": ["error", { functions: false }],
       "no-useless-call": "error",
       "no-useless-concat": "error",
       "no-useless-return": "error",
-      "no-use-before-define": ["error", { functions: false }],
       "no-void": "error",
       "no-warning-comments": "warn",
+      "operator-assignment": "error",
+      "prefer-object-spread": "error",
       "radix": ["error", "always"],
       "yoda": "error"
     }
index 59a66354839eb0fb7d941cafdc421db3f5a30022..2333bf08f69d3ebf34629a1a184c3d90304967a1 100644 (file)
@@ -1683,6 +1683,7 @@ de:
       reports: Meldungen
       last_updated: Zuletzt aktualisiert
       last_updated_time_ago_user_html: '%{time_ago} von %{user}'
+      reporting_users: Benutzer melden
       reports_count:
         one: Eine Meldung
         other: '%{count} Meldungen'
@@ -1721,6 +1722,8 @@ de:
       reopened: Der Problemstatus wurde auf „Offen“ geändert
     comments:
       comment_from_html: Kommentar von %{user_link} erstellt am %{comment_created_at}
+      reassign_to_moderators: Weise das Problem den Moderatoren zu
+      reassign_to_administrators: Weise das Problem den Administratoren zu
     reports:
       reported_by_html: Gemeldet als %{category} von %{user} bei %{updated_at}
     helper:
@@ -3318,6 +3321,7 @@ de:
       open_title: Ungelöster Hinweis Nr. %{note_name}
       closed_title: Erledigter Hinweis Nr. %{note_name}
       hidden_title: Versteckter Hinweis Nr. %{note_name}
+      description_when_author_is_deleted: gelöscht
       event_opened_by_html: Erstellt von %{user} %{time_ago}
       event_opened_by_anonymous_html: Erstellt von anonym %{time_ago}
       event_commented_by_html: Kommentar von %{user} %{time_ago}
index 7c48cafcb753606687f253f53fa88a0bb835ce18..d343d978539e7c6c3292b461e93d0a8ecc25a1c0 100644 (file)
@@ -1609,6 +1609,7 @@ el:
       reports: Αναφορές
       last_updated: Τελευταία ενημέρωση
       last_updated_time_ago_user_html: '%{time_ago} από %{user}'
+      reporting_users: Αναφερόμενοι Χρήστες
       reports_count:
         one: '%{count} Αναφορά'
         other: '%{count} Αναφορές'
@@ -1648,6 +1649,8 @@ el:
       reopened: Η κατάσταση του ζητήματος έχει οριστεί σε 'Ανοιχτό'
     comments:
       comment_from_html: Σχόλιο από %{user_link} γραμμένο στις %{comment_created_at}
+      reassign_to_moderators: Ανάθεση ζητήματος σε Συντονιστές
+      reassign_to_administrators: Ανάθεση ζητήματος σε Διαχειριστές
     reports:
       reported_by_html: Αναφέρθηκε ως %{category} από %{user} στις %{updated_at}
     helper:
@@ -3233,6 +3236,7 @@ el:
       open_title: 'Ανοικτή σημείωση #%{note_name}'
       closed_title: 'Επιλυμένη σημείωση #%{note_name}'
       hidden_title: 'Κρυφή σημείωση #%{note_name}'
+      description_when_author_is_deleted: διαγράφηκε
       event_opened_by_html: Δημιουργήθηκε από %{user} %{time_ago}
       event_opened_by_anonymous_html: Δημιουργήθηκε από ανώνυμο %{time_ago}
       event_commented_by_html: Σχολιάστηκε από %{user} %{time_ago}
index 7b2be6a0cb63180d6a2a1376550d2688d2d7fc40..cb7e24ee0d580b302a79be9aeeaa4271763e8f31 100644 (file)
@@ -1624,8 +1624,6 @@ en:
     partners_corpmembers: "OSMF corporate members"
     partners_partners: "partners"
     tou: "Terms of Use"
-    osm_offline: "The OpenStreetMap database is currently offline while essential database maintenance work is carried out."
-    osm_read_only: "The OpenStreetMap database is currently in read-only mode while essential database maintenance work is carried out."
     nothing_to_preview: "Nothing to preview."
     help: Help
     about: About
@@ -1633,6 +1631,11 @@ en:
     communities: Communities
     learn_more: "Learn More"
     more: More
+    offline_flash:
+      osm_offline: "The OpenStreetMap database is currently offline while essential maintenance work is carried out."
+      osm_read_only: "The OpenStreetMap database is currently in read-only mode while essential maintenance work is carried out."
+      expected_restore_html: "Services are expected to be restored in %{time}."
+      announcement: "You can read the announcement here."
   user_mailer:
     diary_comment_notification:
       description: "OpenStreetMap Diary Entry #%{id}"
@@ -2249,13 +2252,14 @@ en:
         license_url: "https://openstreetmap.org/copyright"
         project_url: "https://openstreetmap.org"
       remote_failed: "Editing failed - make sure JOSM or Merkaartor is loaded and the remote control option is enabled"
-    edit:
+    not_public_flash:
       not_public: "You have not set your edits to be public."
       not_public_description_html: "You can no longer edit the map unless you do so. You can set your edits as public from your %{user_page}."
       user_page_link: user page
       anon_edits_html: "(%{link})"
       anon_edits_link: "https://wiki.openstreetmap.org/wiki/Disabling_anonymous_edits"
       anon_edits_link_text: "Find out why this is the case."
+    edit:
       id_not_configured: "iD has not been configured"
     export:
       title: "Export"
index 083612acc7d2a358666a679e9bdffef541c5951c..02d9047e6e9ac79aa95c81d502a8d7ebf3830333 100644 (file)
@@ -49,6 +49,7 @@ gd:
       message: Teachdaireachd
       node: Nòd
       node_tag: Taga nòid
+      note: Nòta
       old_node: Seann nòd
       old_node_tag: Taga seann nòid
       old_relation: Seann dàimh
@@ -76,6 +77,8 @@ gd:
         name: Ainm (Riatanach)
         callback_url: URL ais-ghairm
         support_url: URL taice
+        allow_read_prefs: na roghainnean a' chleachdaiche aca a leughadh
+        allow_write_prefs: na roghainnean a' chleachdaiche aca atharrachadh
         allow_write_api: am mapa atharrachadh
         allow_read_gpx: na lorgaidhean GPS prìobhaideach aca a leughadh
         allow_write_gpx: lorgaidhean GPS a luchdadh suas
@@ -91,6 +94,7 @@ gd:
         language_code: Cànan
       doorkeeper/application:
         name: Ainm
+        scopes: Ceadan
       friend:
         user: Cleachdaiche
         friend: Caraid
@@ -103,7 +107,7 @@ gd:
         longitude: Domhan-fhad
         public: Poblach
         description: Tuairisgeul
-        gpx_file: Luchdaich suas faidhle GPX
+        gpx_file: Tagh faidhle lorgadh GPS
         visibility: Faicsinneachd
         tagstring: Tagaichean
       message:
@@ -114,12 +118,14 @@ gd:
       redaction:
         title: Tiotal
         description: Tuairisgeul
+      report:
+        category: Tagh adhbhar dhan aithris agad
       user:
         email: Post-d
         new_email: An seòladh puist-d ùr
         active: Gnìomhach
         display_name: Ainm seallaidh
-        description: Tuairisgeul
+        description: Tuairisgeul Pròifile
         home_lat: Domhan-leud
         home_lon: Domhan-fhad
         languages: Cànain
@@ -206,6 +212,9 @@ gd:
   auth:
     providers:
       google: Google
+      facebook: Facebook
+      github: GitHub
+      wikipedia: Uicipeid
   api:
     notes:
       comment:
@@ -238,7 +247,7 @@ gd:
       openid:
         link text: dè th`ann?
       contributor terms:
-        heading: 'Teirmichean a'' chom-pàirtiche:'
+        heading: Teirmichean a' chom-pàirtiche
         agreed: Dh'aontaich thu ri teirmichean ùra a' chom-pàirtiche.
         not yet agreed: Cha do dh'aontaich thu ri teirmichean ùra a' chom-pàirtiche
           fhathast.
@@ -261,11 +270,13 @@ gd:
         cancel: Sguir dheth
     terms:
       show:
-        title: Teirmichean a' chom-pàirtiche
-        heading: Teirmichean a' chom-pàirtiche
+        title: Teirmichean
+        heading: Teirmichean
+        heading_ct: Teirmichean a' chom-pàirtiche
         consider_pd: A bharrachd air an aonta gu h-àrd, aontaichidh mi gun dèid na
           bheir mi dhuibh 'nam cho-thabhartaiche a chur sa Public Domain
         consider_pd_why: Dè th`ann?
+        cancel: Sguir dheth
         you need to accept or decline: Feuch an leugh thu teirmichean ùra a' chom-pàirtiche
           agus an uairsin aontaich no nach gabh riutha mus lean thu air adhart.
         legale_select: 'Dùthaich còmhnaidh:'
@@ -404,8 +415,11 @@ gd:
     show:
       title: 'Seata atharraichean: %{id}'
       created: 'Air a chruthachadh: %{when}'
+      closed: 'Air a dhùnadh: %{when}'
       created_ago_html: Air a chruthachadh %{time_ago}
+      closed_ago_html: Air a dhùnadh %{time_ago}
       created_ago_by_html: Air a chruthachadh %{time_ago} le %{user}
+      closed_ago_by_html: Air a dhùnadh %{time_ago} le %{user}
       discussion: Deasbaireachd
       join_discussion: Clàraich a-steach gus pàirt a ghabhail san deasbaireachd
       subscribe: Fo-sgrìobh
@@ -440,6 +454,7 @@ gd:
       nearby users: Cleachdaichean am fagas eile
       no nearby users: Chan eil cleachdaiche sam bith eile ann a dh'innis gu bheil
         iad ris an obair-mhapa am fagas.
+      followed_changesets: seataichean atharraichean
       nearby_changesets: seata atharraichean nan cleachdaichean am fagas
       nearby_diaries: clàran leabhair-latha am fagas
   diary_entries:
@@ -517,12 +532,13 @@ gd:
           station: Stèisean trama-adhair
         aeroway:
           aerodrome: Raon-adhair
-          apron: Aparan
-          gate: Geata
+          apron: Aparan puirt-adhair
+          gate: Geata puirt-adhair
+          hangar: Hangar
           helipad: Port-heileacoptair
           runway: Raon-laighe
           taxiway: Raon-cuairteachaidh
-          terminal: Tèirmineal
+          terminal: Tèirmineal puirt-adhair
         amenity:
           animal_shelter: Fasgadh bheathaichean
           arts_centre: Ionad ealain
@@ -562,13 +578,15 @@ gd:
           fire_station: Stèisean-smàlaidh
           food_court: Talla bìdh
           fountain: Fuaran
-          fuel: Connadh
+          fuel: Stèisean-peatrail
           gambling: Cearrachas
           grave_yard: Cladh
           hospital: Ospadal
           hunting_stand: Stannd seilge
           ice_cream: Reòiteagan
+          internet_cafe: Cafaidh eadar-lìn
           kindergarten: Sgoil-àraich
+          language_school: Sgoil cànain
           library: Leabhar-lann
           marketplace: Ionad-margaidh
           monastery: Manachainn
@@ -607,6 +625,7 @@ gd:
           waste_basket: Bogsa-sgudail
           waste_disposal: Ionad-sgudail
         boundary:
+          aboriginal_lands: Tìrean Tùsanaich
           administrative: Crìoch rianachd
           census: Crìoch cunntas-sluaigh
           national_park: Pàirc nàiseanta
@@ -618,9 +637,12 @@ gd:
           viaduct: Drochaid-rathaid
           "yes": Drochaid
         building:
+          chapel: Seipeal
           garage: Garaids
           garages: Garaidsean
+          hangar: Hangar
           house: Taigh
+          roof: Mullach
           shed: Seada
           static_caravan: Carabhan
           "yes": Togalach
@@ -633,6 +655,7 @@ gd:
           photographer: Neach-dhealbh
           plumber: Plumair
           shoemaker: Greusaiche
+          stonemason: Clachair
           tailor: Tàillear
           "yes": Bùth cheàrd
         emergency:
@@ -646,6 +669,7 @@ gd:
           bus_guideway: Lonaig bus-stiùirichte
           bus_stop: Stad-bus
           construction: Mòr-rathad 'ga thogail
+          corridor: Trannsa
           cycleway: Slighe baidhseagail
           elevator: Àrdaichear
           emergency_access_point: Puing-inntrigidh èiginn
@@ -706,6 +730,8 @@ gd:
           wayside_cross: Cros ri taobh an rathaid
           wayside_shrine: Naomh-chiste ri taobh an rathaid
           wreck: Long bhriste
+        information:
+          map: Mapa
         junction:
           "yes": Gobhal
         landuse:
@@ -766,7 +792,10 @@ gd:
           track: Cuairt-ruith
           water_park: Pàirc-uisge
           "yes": Cur-seachad
+        lock:
+          "yes": Tuil-dhoras
         man_made:
+          bridge: Drochaid
           cairn: Càrn
           lighthouse: Taigh-solais
           pier: Cidhe
@@ -814,6 +843,7 @@ gd:
           sand: Gainmheach
           scree: Sgàirneach
           scrub: Fiodhach
+          shingle: Mol
           spring: Fuaran
           stone: Clach
           strait: Caolas
@@ -902,7 +932,9 @@ gd:
           carpet: Bùth bhratan
           charity: Bùth carthannais
           chemist: Bùth-chungaidhean
+          chocolate: Seòclaid
           clothes: Bùth aodach
+          coffee: Bùth cofaidh
           computer: Bùth choimpiutairean
           confectionery: Bùth mìlseanachd
           convenience: Bùth goireasach
@@ -928,9 +960,10 @@ gd:
           grocery: Gròsair
           hairdresser: Gruagaire
           hardware: Bùth leasachadh dachaigh
-          hifi: HiFi
+          hifi: Bùth HiFi
           jewelry: Bùth usgaran
           kiosk: Cìtheasg
+          kitchen: Bùth cidsin
           laundry: Taigh-nigheachain
           mall: Ionad-seopadaireachd
           mobile_phone: Bùth fhònaichean-làmhe
@@ -942,6 +975,7 @@ gd:
           outdoor: Bùth acainnean blàir
           pet: Bùth pheatachan
           photo: Bùth dhealbhan
+          seafood: Biadh na mara
           second_hand: Bùth rudan ath-làimhe
           shoes: Bùth bhrògan
           sports: Bùth spòrs
@@ -977,6 +1011,11 @@ gd:
         tunnel:
           culvert: Cùlbhart
           "yes": Tunail
+        water:
+          lake: Loch
+          pond: Lod
+          reservoir: Stòr-amar
+          lock: Tuil-dhoras
         waterway:
           artificial: Slighe-uisge fhuadain
           boatyard: Bàta-lann
@@ -1012,6 +1051,9 @@ gd:
       search: Lorg
       states:
         open: Fosgailte
+    page:
+      states:
+        open: Fosgailte
     show:
       reports:
         one: '%{count} aithris'
@@ -1023,6 +1065,15 @@ gd:
     helper:
       reportable_title:
         note: 'Nòta #%{note_id}'
+  reports:
+    new:
+      categories:
+        diary_comment:
+          other_label: Eile
+        user:
+          other_label: Eile
+        note:
+          other_label: Eile
   layouts:
     logo:
       alt_text: Suaicheantas OpenStreetMap
@@ -1040,6 +1091,7 @@ gd:
     intro_header: Fàilte gu OpenStreetMap!
     intro_text: '''S e mapa an t-saoghail a tha san OpenStreetMap a chaidh a chruthachadh
       le daoine mar thu fhèin ''s a tha saor fo cheadachas fhosgailte.'
+    partners_fastly: Fastly
     partners_partners: com-pàirtichean eile
     osm_offline: Tha an stòr-dàta aig OpenStreetMap far loidhńe an-dràsta on a tha
       sinn a' dèanamh obair-charaidh riatanach air.
@@ -1069,6 +1121,9 @@ gd:
       hi: Shin thu, %{to_user},
       see_their_profile: '''S urrainn dhut a'' phròifil aig an neach ud a shealltainn
         air %{userurl}.'
+    gpx_details:
+      description: Tuairisgeul
+      tags: Tagaichean
     gpx_failure:
       hi: Shin thu, %{to_user},
       failed_to_import: 'ion-phortachadh. Seo a'' mhearachd:'
@@ -1250,8 +1305,17 @@ gd:
         an URL?
     update:
       flash changed: Chaidh am facal-faire agad atharrachadh.
+  preferences:
+    show:
+      site_color_schemes:
+        light: Soilleir
+        dark: Dorcha
+      map_color_schemes:
+        light: Soilleir
+        dark: Dorcha
   profiles:
     edit:
+      cancel: Sguir dheth
       image: Dealbh
       gravatar:
         gravatar: Cleachd Gravatar
@@ -1286,6 +1350,9 @@ gd:
     richtext_field:
       edit: Deasaich
     pagination:
+      changeset_comments:
+        older: Beachdan nas sine
+        newer: Beachdan nas ùire
       diary_comments:
         older: Beachdan nas sine
         newer: Beachdan nas ùire
@@ -1823,6 +1890,7 @@ gd:
       description: Tuairisgeul
       created_at: Air a chruthachadh
       last_changed: An t-atharrachadh mu dheireadh
+      closed: Dùinte
     show:
       title: 'Nòta: %{id}'
       description: Tuairisgeul
index aa761d9f66f9db8369dbb51909284add968a3590..ad5d747b6d31b61a4416cdd9446de382a5bd9109 100644 (file)
@@ -1580,6 +1580,7 @@ gl:
       reports: Denuncias
       last_updated: Última actualización
       last_updated_time_ago_user_html: '%{time_ago} por %{user}'
+      reporting_users: Usuarios denunciantes
       reports_count:
         one: '%{count} denuncia'
         other: '%{count} denuncias'
@@ -1618,6 +1619,8 @@ gl:
       reopened: O estado da incidencia mudou a "Aberta"
     comments:
       comment_from_html: Comentario de %{user_link} no %{comment_created_at}
+      reassign_to_moderators: Reasignar a incidencia aos moderadores
+      reassign_to_administrators: Reasignar a incidencia aos administradores
     reports:
       reported_by_html: Denunciado coma %{category} por %{user} o %{updated_at}
     helper:
@@ -3183,6 +3186,7 @@ gl:
       open_title: Nota sen resolver n.º %{note_name}
       closed_title: Nota resolta n.º %{note_name}
       hidden_title: Nota agochada n.º %{note_name}
+      description_when_author_is_deleted: eliminado
       event_opened_by_html: Creado por %{user} %{time_ago}
       event_opened_by_anonymous_html: Creado por un usuario anónimo %{time_ago}
       event_commented_by_html: Comentario de %{user} %{time_ago}
index c147303be73b814caad24f8f3bfd9b11c3e2649f..271d8272a14cce039a08a90cdf9ce23956a096c9 100644 (file)
@@ -3216,6 +3216,7 @@ it:
       open_title: 'Nota irrisolta #%{note_name}'
       closed_title: 'Nota risolta #%{note_name}'
       hidden_title: 'Nota nascosta #%{note_name}'
+      description_when_author_is_deleted: cancellato
       event_opened_by_html: Creata da %{user} %{time_ago}
       event_opened_by_anonymous_html: Creata da anonimo %{time_ago}
       event_commented_by_html: Commento da %{user} %{time_ago}
index ead60fb80b99d1bb5cf4afad6b36eaaa476540f5..b950cc39076a1ff3d157cfc12dfdaf1eaed8b9e8 100644 (file)
@@ -1453,6 +1453,7 @@ lb:
       reports: Rapporten
       last_updated: Lescht Aktualiséierung
       last_updated_time_ago_user_html: '%{time_ago} vum %{user}'
+      reporting_users: Benotzer mellen
       reports_count:
         one: '%{count} Bericht'
         other: '%{count} Berichter'
@@ -2492,6 +2493,7 @@ lb:
       open_title: 'Ongeléisten Hiweis #%{note_name}'
       closed_title: 'Geléisten Hiweis #%{note_name}'
       hidden_title: Verstoppt Notiz N° %{note_name}
+      description_when_author_is_deleted: geläscht
       report: Dësen Hiweis mellen
       discussion: Diskussioun
       subscribe: Abonéieren
index 04f1d259fe42cc4ca24f71b6d230ce46cdbbad74..d7fd37996c4b69145d832a2d0ae2cea494bfdd7a 100644 (file)
@@ -18,6 +18,7 @@
 # Author: BushmanK
 # Author: Butko
 # Author: CM3X
+# Author: Cabadeck
 # Author: Calibrator
 # Author: Chilin
 # Author: Cjaushe4ka
@@ -1712,6 +1713,7 @@ ru:
       reopened: Статус проблемы был установлен в "Открыто"
     comments:
       comment_from_html: Комментарий участника %{user_link}, созданный %{comment_created_at}
+      reassign_to_administrators: Перенаправить проблему Администраторам
     reports:
       reported_by_html: Указано как %{category} пользователем %{user} %{updated_at}
     helper:
index 08fc951a5c27dc1ed37a0795f35867ef9f5d8199..3f1d4dad3451789f4f0a138e1573db8d5e2e94b7 100644 (file)
@@ -1367,6 +1367,7 @@ skr-arab:
     show:
       title: نوٹ:%{id}
       description: تفصیل
+      description_when_author_is_deleted: مٹا ݙتے
       discussion: بحث مباحثہ
       subscribe: سبسکرائب کرو
       unsubscribe: اݨ سبسکرائب کرو
index 82e9c870d83fcdaa2ac080755ab9c431d6dcc89a..af42dc29cbc6bb9b7be5a13b75f7acaad221cd33 100644 (file)
@@ -2334,6 +2334,7 @@ sr:
       open_title: Нерешена белешка бр. %{note_name}
       closed_title: Решена белешка бр. %{note_name}
       hidden_title: Скривена белешка бр. %{note_name}
+      description_when_author_is_deleted: обрисано
       event_opened_by_html: Направио %{user} %{time_ago}
       report: пријави ову белешку
       anonymous_warning: Ова белешка садржи коментаре анонимних корисника које би
index 2b86326986dae9e1c07c2df8ac060aa82769e24d..54bf037cf293984488572a901710283a02d9222b 100644 (file)
@@ -30,17 +30,11 @@ OpenStreetMap::Application.routes.draw do
     post "changeset/comment/:id/hide" => "changeset_comments#destroy", :as => :changeset_comment_hide, :id => /\d+/
     post "changeset/comment/:id/unhide" => "changeset_comments#restore", :as => :changeset_comment_unhide, :id => /\d+/
 
-    get "node/:id/history" => "old_nodes#history", :as => :api_node_history, :id => /\d+/
-    post "node/:id/:version/redact" => "old_nodes#redact", :as => :node_version_redact, :version => /\d+/, :id => /\d+/
-    get "node/:id/:version" => "old_nodes#show", :as => :api_old_node, :id => /\d+/, :version => /\d+/
+    post "node/:node_id/:version/redact" => "old_nodes#redact", :as => :node_version_redact, :version => /\d+/, :node_id => /\d+/
 
-    get "way/:id/history" => "old_ways#history", :as => :api_way_history, :id => /\d+/
-    post "way/:id/:version/redact" => "old_ways#redact", :as => :way_version_redact, :version => /\d+/, :id => /\d+/
-    get "way/:id/:version" => "old_ways#show", :as => :api_old_way, :id => /\d+/, :version => /\d+/
+    post "way/:way_id/:version/redact" => "old_ways#redact", :as => :way_version_redact, :version => /\d+/, :id => /\d+/
 
-    get "relation/:id/history" => "old_relations#history", :as => :api_relation_history, :id => /\d+/
-    post "relation/:id/:version/redact" => "old_relations#redact", :as => :relation_version_redact, :version => /\d+/, :id => /\d+/
-    get "relation/:id/:version" => "old_relations#show", :as => :api_old_relation, :id => /\d+/, :version => /\d+/
+    post "relation/:relation_id/:version/redact" => "old_relations#redact", :as => :relation_version_redact, :version => /\d+/, :id => /\d+/
   end
 
   namespace :api, :path => "api/0.6" do
@@ -50,6 +44,8 @@ OpenStreetMap::Application.routes.draw do
         resources :ways, :only => :index
         resources :relations, :only => :index
       end
+      resources :versions, :path => "history", :controller => :old_nodes, :only => :index
+      resources :versions, :path => "", :version => /\d+/, :param => :version, :controller => :old_nodes, :only => :show
     end
     put "node/create" => "nodes#create", :as => nil
 
@@ -61,6 +57,8 @@ OpenStreetMap::Application.routes.draw do
       scope :module => :ways do
         resources :relations, :only => :index
       end
+      resources :versions, :path => "history", :controller => :old_ways, :only => :index
+      resources :versions, :path => "", :version => /\d+/, :param => :version, :controller => :old_ways, :only => :show
     end
     put "way/create" => "ways#create", :as => nil
 
@@ -72,6 +70,8 @@ OpenStreetMap::Application.routes.draw do
       scope :module => :relations do
         resources :relations, :only => :index
       end
+      resources :versions, :path => "history", :controller => :old_relations, :only => :index
+      resources :versions, :path => "", :version => /\d+/, :param => :version, :controller => :old_relations, :only => :show
     end
     put "relation/create" => "relations#create", :as => nil
 
index c79199145163359dd3a7efbc6dcb6e539c4037e1..2e0346f0031c891d226deeddaa284adb2801cc31 100644 (file)
@@ -23,6 +23,10 @@ api_version: "0.6"
 #   database_offline - database offline with site in emergency mode
 #   gpx_offline - gpx storage offline
 status: "online"
+# Expected services restoration date added to offline flash messages
+#status_expected_restore_date: "2024-12-18 12:00:00Z"
+# Application status announcement url added to offline flash messages
+#status_announcement_url: "https://en.osm.town/@osm_tech"
 # The maximum area you're allowed to request, in square degrees
 max_request_area: 0.25
 # Number of GPS trace/trackpoints returned per-page
index 27b550e40bd1f00ff0be62f75c43d5c67f4d08a2..17f28a4e9cb4ef134a4ac205690159499ff3b9ad 100644 (file)
@@ -8,18 +8,12 @@ def config_file
   Rails.root.join("config/eslint.js").to_s
 end
 
-def js_files
-  Rails.application.assets.each_file.select do |file|
-    (file.ends_with?(".js") || file.ends_with?(".js.erb")) && !file.match?(%r{/(gems|vendor|i18n|node_modules)/})
-  end
-end
-
 namespace "eslint" do
   task :check => :environment do
-    system(yarn_path, "run", "eslint", "-c", config_file, *js_files) || abort
+    system(yarn_path, "run", "eslint", "-c", config_file, "--no-warn-ignored", Rails.root.to_s) || abort
   end
 
   task :fix => :environment do
-    system(yarn_path, "run", "eslint", "-c", config_file, "--fix", *js_files) || abort
+    system(yarn_path, "run", "eslint", "-c", config_file, "--no-warn-ignored", "--fix", Rails.root.to_s) || abort
   end
 end
index 8ce19f3ea2f5f80669801e34fc3d9115d5f0181c..75123f9e0f68472ce49a2e39c48f69d49a3f2d92 100644 (file)
@@ -2,159 +2,105 @@ require "test_helper"
 
 module Api
   class OldNodesControllerTest < ActionDispatch::IntegrationTest
-    #
-    # TODO: test history
-    #
-
     ##
     # test all routes which lead to this controller
     def test_routes
       assert_routing(
         { :path => "/api/0.6/node/1/history", :method => :get },
-        { :controller => "api/old_nodes", :action => "history", :id => "1" }
+        { :controller => "api/old_nodes", :action => "index", :node_id => "1" }
       )
       assert_routing(
-        { :path => "/api/0.6/node/1/2", :method => :get },
-        { :controller => "api/old_nodes", :action => "show", :id => "1", :version => "2" }
+        { :path => "/api/0.6/node/1/history.json", :method => :get },
+        { :controller => "api/old_nodes", :action => "index", :node_id => "1", :format => "json" }
       )
       assert_routing(
-        { :path => "/api/0.6/node/1/history.json", :method => :get },
-        { :controller => "api/old_nodes", :action => "history", :id => "1", :format => "json" }
+        { :path => "/api/0.6/node/1/2", :method => :get },
+        { :controller => "api/old_nodes", :action => "show", :node_id => "1", :version => "2" }
       )
       assert_routing(
         { :path => "/api/0.6/node/1/2.json", :method => :get },
-        { :controller => "api/old_nodes", :action => "show", :id => "1", :version => "2", :format => "json" }
+        { :controller => "api/old_nodes", :action => "show", :node_id => "1", :version => "2", :format => "json" }
       )
       assert_routing(
         { :path => "/api/0.6/node/1/2/redact", :method => :post },
-        { :controller => "api/old_nodes", :action => "redact", :id => "1", :version => "2" }
+        { :controller => "api/old_nodes", :action => "redact", :node_id => "1", :version => "2" }
       )
     end
 
-    ##
-    # test the version call by submitting several revisions of a new node
-    # to the API and ensuring that later calls to version return the
-    # matching versions of the object.
-    #
-    ##
-    # FIXME: Move this test to being an integration test since it spans multiple controllers
-    def test_version
-      private_user = create(:user, :data_public => false)
-      private_node = create(:node, :with_history, :version => 4, :lat => 0, :lon => 0, :changeset => create(:changeset, :user => private_user))
-      user = create(:user)
-      node = create(:node, :with_history, :version => 4, :lat => 0, :lon => 0, :changeset => create(:changeset, :user => user))
-      create_list(:node_tag, 2, :node => node)
-      # Ensure that the current tags are propagated to the history too
-      propagate_tags(node, node.old_nodes.last)
-
-      ## First try this with a non-public user
-      auth_header = bearer_authorization_header private_user
-
-      # setup a simple XML node
-      xml_doc = xml_for_node(private_node)
-      xml_node = xml_doc.find("//osm/node").first
-      nodeid = private_node.id
-
-      # keep a hash of the versions => string, as we'll need something
-      # to test against later
-      versions = {}
-
-      # save a version for later checking
-      versions[xml_node["version"]] = xml_doc.to_s
-
-      # randomly move the node about
-      3.times do
-        # move the node somewhere else
-        xml_node["lat"] = precision(rand - 0.5).to_s
-        xml_node["lon"] = precision(rand - 0.5).to_s
-        with_controller(NodesController.new) do
-          put api_node_path(nodeid), :params => xml_doc.to_s, :headers => auth_header
-          assert_response :forbidden, "Should have rejected node update"
-          xml_node["version"] = @response.body.to_s
-        end
-        # save a version for later checking
-        versions[xml_node["version"]] = xml_doc.to_s
-      end
-
-      # add a bunch of random tags
-      3.times do
-        xml_tag = XML::Node.new("tag")
-        xml_tag["k"] = random_string
-        xml_tag["v"] = random_string
-        xml_node << xml_tag
-        with_controller(NodesController.new) do
-          put api_node_path(nodeid), :params => xml_doc.to_s, :headers => auth_header
-          assert_response :forbidden,
-                          "should have rejected node #{nodeid} (#{@response.body}) with forbidden"
-          xml_node["version"] = @response.body.to_s
+    def test_index
+      node = create(:node, :version => 2)
+      create(:old_node, :node_id => node.id, :version => 1, :latitude => 60 * OldNode::SCALE, :longitude => 30 * OldNode::SCALE)
+      create(:old_node, :node_id => node.id, :version => 2, :latitude => 61 * OldNode::SCALE, :longitude => 31 * OldNode::SCALE)
+
+      get api_node_versions_path(node)
+
+      assert_response :success
+      assert_dom "osm:root", 1 do
+        assert_dom "> node", 2 do |dom_nodes|
+          assert_dom dom_nodes[0], "> @id", node.id.to_s
+          assert_dom dom_nodes[0], "> @version", "1"
+          assert_dom dom_nodes[0], "> @lat", "60.0000000"
+          assert_dom dom_nodes[0], "> @lon", "30.0000000"
+
+          assert_dom dom_nodes[1], "> @id", node.id.to_s
+          assert_dom dom_nodes[1], "> @version", "2"
+          assert_dom dom_nodes[1], "> @lat", "61.0000000"
+          assert_dom dom_nodes[1], "> @lon", "31.0000000"
         end
-        # save a version for later checking
-        versions[xml_node["version"]] = xml_doc.to_s
       end
+    end
 
-      # probably should check that they didn't get written to the database
-
-      ## Now do it with the public user
-      auth_header = bearer_authorization_header user
-
-      # setup a simple XML node
+    ##
+    # test that redacted nodes aren't visible in the history
+    def test_index_redacted
+      node = create(:node, :with_history, :version => 2)
+      node_v1 = node.old_nodes.find_by(:version => 1)
+      node_v1.redact!(create(:redaction))
 
-      xml_doc = xml_for_node(node)
-      xml_node = xml_doc.find("//osm/node").first
-      nodeid = node.id
+      get api_node_versions_path(node)
+      assert_response :success, "Redaction shouldn't have stopped history working."
+      assert_select "osm node[id='#{node_v1.node_id}'][version='#{node_v1.version}']", 0,
+                    "redacted node #{node_v1.node_id} version #{node_v1.version} shouldn't be present in the history."
 
-      # keep a hash of the versions => string, as we'll need something
-      # to test against later
-      versions = {}
+      # not even to a logged-in user
+      auth_header = bearer_authorization_header
+      get api_node_versions_path(node), :headers => auth_header
+      assert_response :success, "Redaction shouldn't have stopped history working."
+      assert_select "osm node[id='#{node_v1.node_id}'][version='#{node_v1.version}']", 0,
+                    "redacted node #{node_v1.node_id} version #{node_v1.version} shouldn't be present in the history, even when logged in."
+    end
 
-      # save a version for later checking
-      versions[xml_node["version"]] = xml_doc.to_s
+    def test_show
+      node = create(:node, :version => 2)
+      create(:old_node, :node_id => node.id, :version => 1, :latitude => 60 * OldNode::SCALE, :longitude => 30 * OldNode::SCALE)
+      create(:old_node, :node_id => node.id, :version => 2, :latitude => 61 * OldNode::SCALE, :longitude => 31 * OldNode::SCALE)
 
-      # randomly move the node about
-      3.times do
-        # move the node somewhere else
-        xml_node["lat"] = precision(rand - 0.5).to_s
-        xml_node["lon"] = precision(rand - 0.5).to_s
-        with_controller(NodesController.new) do
-          put api_node_path(nodeid), :params => xml_doc.to_s, :headers => auth_header
-          assert_response :success
-          xml_node["version"] = @response.body.to_s
-        end
-        # save a version for later checking
-        versions[xml_node["version"]] = xml_doc.to_s
-      end
+      get api_node_version_path(node, 1)
 
-      # add a bunch of random tags
-      3.times do
-        xml_tag = XML::Node.new("tag")
-        xml_tag["k"] = random_string
-        xml_tag["v"] = random_string
-        xml_node << xml_tag
-        with_controller(NodesController.new) do
-          put api_node_path(nodeid), :params => xml_doc.to_s, :headers => auth_header
-          assert_response :success,
-                          "couldn't update node #{nodeid} (#{@response.body})"
-          xml_node["version"] = @response.body.to_s
+      assert_response :success
+      assert_dom "osm:root", 1 do
+        assert_dom "> node", 1 do
+          assert_dom "> @id", node.id.to_s
+          assert_dom "> @version", "1"
+          assert_dom "> @lat", "60.0000000"
+          assert_dom "> @lon", "30.0000000"
         end
-        # save a version for later checking
-        versions[xml_node["version"]] = xml_doc.to_s
       end
 
-      # check all the versions
-      versions.each_key do |key|
-        get api_old_node_path(nodeid, key.to_i)
-
-        assert_response :success,
-                        "couldn't get version #{key.to_i} of node #{nodeid}"
+      get api_node_version_path(node, 2)
 
-        check_node = Node.from_xml(versions[key])
-        api_node = Node.from_xml(@response.body.to_s)
-
-        assert_nodes_are_equal check_node, api_node
+      assert_response :success
+      assert_dom "osm:root", 1 do
+        assert_dom "> node", 1 do
+          assert_dom "> @id", node.id.to_s
+          assert_dom "> @version", "2"
+          assert_dom "> @lat", "61.0000000"
+          assert_dom "> @lon", "31.0000000"
+        end
       end
     end
 
-    def test_not_found_version
+    def test_show_not_found
       check_not_found_id_version(70000, 312344)
       check_not_found_id_version(-1, -13)
       check_not_found_id_version(create(:node).id, 24354)
@@ -162,36 +108,27 @@ module Api
     end
 
     ##
-    # Test that getting the current version is identical to picking
-    # that version with the version URI call.
-    def test_current_version
-      node = create(:node, :with_history)
-      used_node = create(:node, :with_history)
-      create(:way_node, :node => used_node)
-      node_used_by_relationship = create(:node, :with_history)
-      create(:relation_member, :member => node_used_by_relationship)
-      node_with_versions = create(:node, :with_history, :version => 4)
-
-      create(:node_tag, :node => node)
-      create(:node_tag, :node => used_node)
-      create(:node_tag, :node => node_used_by_relationship)
-      create(:node_tag, :node => node_with_versions)
-      propagate_tags(node, node.old_nodes.last)
-      propagate_tags(used_node, used_node.old_nodes.last)
-      propagate_tags(node_used_by_relationship, node_used_by_relationship.old_nodes.last)
-      propagate_tags(node_with_versions, node_with_versions.old_nodes.last)
-
-      check_current_version(node)
-      check_current_version(used_node)
-      check_current_version(node_used_by_relationship)
-      check_current_version(node_with_versions)
+    # test that redacted nodes aren't visible, regardless of
+    # authorisation except as moderator...
+    def test_show_redacted
+      node = create(:node, :with_history, :version => 2)
+      node_v1 = node.old_nodes.find_by(:version => 1)
+      node_v1.redact!(create(:redaction))
+
+      get api_node_version_path(node_v1.node_id, node_v1.version)
+      assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
+
+      # not even to a logged-in user
+      auth_header = bearer_authorization_header
+      get api_node_version_path(node_v1.node_id, node_v1.version), :headers => auth_header
+      assert_response :forbidden, "Redacted node shouldn't be visible via the version API, even when logged in."
     end
 
     # Ensure the lat/lon is formatted as a decimal e.g. not 4.0e-05
     def test_lat_lon_xml_format
       old_node = create(:old_node, :latitude => (0.00004 * OldNode::SCALE).to_i, :longitude => (0.00008 * OldNode::SCALE).to_i)
 
-      get api_node_history_path(old_node.node_id)
+      get api_node_versions_path(old_node.node_id)
       assert_match(/lat="0.0000400"/, response.body)
       assert_match(/lon="0.0000800"/, response.body)
     end
@@ -262,43 +199,6 @@ module Api
       assert_response :success, "should be OK to redact old version as moderator with write_redactions scope."
     end
 
-    ##
-    # test that redacted nodes aren't visible, regardless of
-    # authorisation except as moderator...
-    def test_version_redacted
-      node = create(:node, :with_history, :version => 2)
-      node_v1 = node.old_nodes.find_by(:version => 1)
-      node_v1.redact!(create(:redaction))
-
-      get api_old_node_path(node_v1.node_id, node_v1.version)
-      assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
-
-      # not even to a logged-in user
-      auth_header = bearer_authorization_header
-      get api_old_node_path(node_v1.node_id, node_v1.version), :headers => auth_header
-      assert_response :forbidden, "Redacted node shouldn't be visible via the version API, even when logged in."
-    end
-
-    ##
-    # test that redacted nodes aren't visible in the history
-    def test_history_redacted
-      node = create(:node, :with_history, :version => 2)
-      node_v1 = node.old_nodes.find_by(:version => 1)
-      node_v1.redact!(create(:redaction))
-
-      get api_node_history_path(node)
-      assert_response :success, "Redaction shouldn't have stopped history working."
-      assert_select "osm node[id='#{node_v1.node_id}'][version='#{node_v1.version}']", 0,
-                    "redacted node #{node_v1.node_id} version #{node_v1.version} shouldn't be present in the history."
-
-      # not even to a logged-in user
-      auth_header = bearer_authorization_header
-      get api_node_history_path(node), :headers => auth_header
-      assert_response :success, "Redaction shouldn't have stopped history working."
-      assert_select "osm node[id='#{node_v1.node_id}'][version='#{node_v1.version}']", 0,
-                    "redacted node #{node_v1.node_id} version #{node_v1.version} shouldn't be present in the history, even when logged in."
-    end
-
     ##
     # test the redaction of an old version of a node, while being
     # authorised as a moderator.
@@ -312,17 +212,17 @@ module Api
 
       # check moderator can still see the redacted data, when passing
       # the appropriate flag
-      get api_old_node_path(node_v3.node_id, node_v3.version), :headers => auth_header
+      get api_node_version_path(node_v3.node_id, node_v3.version), :headers => auth_header
       assert_response :forbidden, "After redaction, node should be gone for moderator, when flag not passed."
-      get api_old_node_path(node_v3.node_id, node_v3.version, :show_redactions => "true"), :headers => auth_header
+      get api_node_version_path(node_v3.node_id, node_v3.version, :show_redactions => "true"), :headers => auth_header
       assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
 
       # and when accessed via history
-      get api_node_history_path(node)
+      get api_node_versions_path(node)
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm node[id='#{node_v3.node_id}'][version='#{node_v3.version}']", 0,
                     "node #{node_v3.node_id} version #{node_v3.version} should not be present in the history for moderators when not passing flag."
-      get api_node_history_path(node, :show_redactions => "true"), :headers => auth_header
+      get api_node_versions_path(node, :show_redactions => "true"), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm node[id='#{node_v3.node_id}'][version='#{node_v3.version}']", 1,
                     "node #{node_v3.node_id} version #{node_v3.version} should still be present in the history for moderators when passing flag."
@@ -342,11 +242,11 @@ module Api
       auth_header = bearer_authorization_header
 
       # check can't see the redacted data
-      get api_old_node_path(node_v3.node_id, node_v3.version), :headers => auth_header
+      get api_node_version_path(node_v3.node_id, node_v3.version), :headers => auth_header
       assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
 
       # and when accessed via history
-      get api_node_history_path(node), :headers => auth_header
+      get api_node_versions_path(node), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm node[id='#{node_v3.node_id}'][version='#{node_v3.version}']", 0,
                     "redacted node #{node_v3.node_id} version #{node_v3.version} shouldn't be present in the history."
@@ -395,11 +295,11 @@ module Api
 
       # check moderator can now see the redacted data, when not
       # passing the aspecial flag
-      get api_old_node_path(node_v1.node_id, node_v1.version), :headers => auth_header
+      get api_node_version_path(node_v1.node_id, node_v1.version), :headers => auth_header
       assert_response :success, "After unredaction, node should not be gone for moderator."
 
       # and when accessed via history
-      get api_node_history_path(node)
+      get api_node_versions_path(node)
       assert_response :success, "Unredaction shouldn't have stopped history working."
       assert_select "osm node[id='#{node_v1.node_id}'][version='#{node_v1.version}']", 1,
                     "node #{node_v1.node_id} version #{node_v1.version} should now be present in the history for moderators without passing flag."
@@ -407,11 +307,11 @@ module Api
       auth_header = bearer_authorization_header
 
       # check normal user can now see the redacted data
-      get api_old_node_path(node_v1.node_id, node_v1.version), :headers => auth_header
+      get api_node_version_path(node_v1.node_id, node_v1.version), :headers => auth_header
       assert_response :success, "After unredaction, node should be visible to normal users."
 
       # and when accessed via history
-      get api_node_history_path(node)
+      get api_node_versions_path(node)
       assert_response :success, "Unredaction shouldn't have stopped history working."
       assert_select "osm node[id='#{node_v1.node_id}'][version='#{node_v1.version}']", 1,
                     "node #{node_v1.node_id} version #{node_v1.version} should now be present in the history for normal users without passing flag."
@@ -426,61 +326,18 @@ module Api
     end
 
     def do_redact_node(node, redaction, headers = {})
-      get api_old_node_path(node.node_id, node.version), :headers => headers
+      get api_node_version_path(node.node_id, node.version), :headers => headers
       assert_response :success, "should be able to get version #{node.version} of node #{node.node_id}."
 
       # now redact it
       post node_version_redact_path(node.node_id, node.version), :params => { :redaction => redaction.id }, :headers => headers
     end
 
-    def check_current_version(node_id)
-      # get the current version of the node
-      current_node = with_controller(NodesController.new) do
-        get api_node_path(node_id)
-        assert_response :success, "cant get current node #{node_id}"
-        Node.from_xml(@response.body)
-      end
-      assert_not_nil current_node, "getting node #{node_id} returned nil"
-
-      # get the "old" version of the node from the old_node interface
-      get api_old_node_path(node_id, current_node.version)
-      assert_response :success, "cant get old node #{node_id}, v#{current_node.version}"
-      old_node = Node.from_xml(@response.body)
-
-      # check the nodes are the same
-      assert_nodes_are_equal current_node, old_node
-    end
-
     def check_not_found_id_version(id, version)
-      get api_old_node_path(id, version)
+      get api_node_version_path(id, version)
       assert_response :not_found
     rescue ActionController::UrlGenerationError => e
       assert_match(/No route matches/, e.to_s)
     end
-
-    ##
-    # returns a 16 character long string with some nasty characters in it.
-    # this ought to stress-test the tag handling as well as the versioning.
-    def random_string
-      letters = [["!", '"', "$", "&", ";", "@"],
-                 ("a".."z").to_a,
-                 ("A".."Z").to_a,
-                 ("0".."9").to_a].flatten
-      (1..16).map { letters[rand(letters.length)] }.join
-    end
-
-    ##
-    # truncate a floating point number to the scale that it is stored in
-    # the database. otherwise rounding errors can produce failing unit
-    # tests when they shouldn't.
-    def precision(f)
-      (f * GeoRecord::SCALE).round.to_f / GeoRecord::SCALE
-    end
-
-    def propagate_tags(node, old_node)
-      node.tags.each do |k, v|
-        create(:old_node_tag, :old_node => old_node, :k => k, :v => v)
-      end
-    end
   end
 end
index 880c340115d13e98c04e2c57aca1ebb919757b1b..96e4c99e40d59d9e0bd881a9bc96fcebf6b9d180 100644 (file)
@@ -7,39 +7,123 @@ module Api
     def test_routes
       assert_routing(
         { :path => "/api/0.6/relation/1/history", :method => :get },
-        { :controller => "api/old_relations", :action => "history", :id => "1" }
+        { :controller => "api/old_relations", :action => "index", :relation_id => "1" }
       )
       assert_routing(
-        { :path => "/api/0.6/relation/1/2", :method => :get },
-        { :controller => "api/old_relations", :action => "show", :id => "1", :version => "2" }
+        { :path => "/api/0.6/relation/1/history.json", :method => :get },
+        { :controller => "api/old_relations", :action => "index", :relation_id => "1", :format => "json" }
       )
       assert_routing(
-        { :path => "/api/0.6/relation/1/history.json", :method => :get },
-        { :controller => "api/old_relations", :action => "history", :id => "1", :format => "json" }
+        { :path => "/api/0.6/relation/1/2", :method => :get },
+        { :controller => "api/old_relations", :action => "show", :relation_id => "1", :version => "2" }
       )
       assert_routing(
         { :path => "/api/0.6/relation/1/2.json", :method => :get },
-        { :controller => "api/old_relations", :action => "show", :id => "1", :version => "2", :format => "json" }
+        { :controller => "api/old_relations", :action => "show", :relation_id => "1", :version => "2", :format => "json" }
       )
       assert_routing(
         { :path => "/api/0.6/relation/1/2/redact", :method => :post },
-        { :controller => "api/old_relations", :action => "redact", :id => "1", :version => "2" }
+        { :controller => "api/old_relations", :action => "redact", :relation_id => "1", :version => "2" }
       )
     end
 
-    # -------------------------------------
-    # Test reading old relations.
-    # -------------------------------------
-    def test_history
-      # check that a visible relations is returned properly
-      get api_relation_history_path(create(:relation, :with_history))
+    ##
+    # check that a visible relations is returned properly
+    def test_index
+      relation = create(:relation, :with_history, :version => 2)
+
+      get api_relation_versions_path(relation)
+
       assert_response :success
+      assert_dom "osm:root", 1 do
+        assert_dom "> relation", 2 do |dom_relations|
+          assert_dom dom_relations[0], "> @id", relation.id.to_s
+          assert_dom dom_relations[0], "> @version", "1"
+
+          assert_dom dom_relations[1], "> @id", relation.id.to_s
+          assert_dom dom_relations[1], "> @version", "2"
+        end
+      end
+    end
 
-      # check chat a non-existent relations is not returned
-      get api_relation_history_path(0)
+    ##
+    # check that a non-existent relations is not returned
+    def test_index_invalid
+      get api_relation_versions_path(0)
       assert_response :not_found
     end
 
+    ##
+    # test that redacted relations aren't visible in the history
+    def test_index_redacted
+      relation = create(:relation, :with_history, :version => 2)
+      relation_v1 = relation.old_relations.find_by(:version => 1)
+      relation_v1.redact!(create(:redaction))
+
+      get api_relation_versions_path(relation)
+      assert_response :success, "Redaction shouldn't have stopped history working."
+      assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 0,
+                    "redacted relation #{relation_v1.relation_id} version #{relation_v1.version} shouldn't be present in the history."
+
+      # not even to a logged-in user
+      auth_header = bearer_authorization_header
+      get api_relation_versions_path(relation), :headers => auth_header
+      assert_response :success, "Redaction shouldn't have stopped history working."
+      assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 0,
+                    "redacted relation #{relation_v1.relation_id} version #{relation_v1.version} shouldn't be present in the history, even when logged in."
+    end
+
+    def test_show
+      relation = create(:relation, :with_history, :version => 2)
+      create(:old_relation_tag, :old_relation => relation.old_relations[0], :k => "k1", :v => "v1")
+      create(:old_relation_tag, :old_relation => relation.old_relations[1], :k => "k2", :v => "v2")
+
+      get api_relation_version_path(relation, 1)
+
+      assert_response :success
+      assert_dom "osm:root", 1 do
+        assert_dom "> relation", 1 do
+          assert_dom "> @id", relation.id.to_s
+          assert_dom "> @version", "1"
+          assert_dom "> tag", 1 do
+            assert_dom "> @k", "k1"
+            assert_dom "> @v", "v1"
+          end
+        end
+      end
+
+      get api_relation_version_path(relation, 2)
+
+      assert_response :success
+      assert_dom "osm:root", 1 do
+        assert_dom "> relation", 1 do
+          assert_dom "> @id", relation.id.to_s
+          assert_dom "> @version", "2"
+          assert_dom "> tag", 1 do
+            assert_dom "> @k", "k2"
+            assert_dom "> @v", "v2"
+          end
+        end
+      end
+    end
+
+    ##
+    # test that redacted relations aren't visible, regardless of
+    # authorisation except as moderator...
+    def test_show_redacted
+      relation = create(:relation, :with_history, :version => 2)
+      relation_v1 = relation.old_relations.find_by(:version => 1)
+      relation_v1.redact!(create(:redaction))
+
+      get api_relation_version_path(relation_v1.relation_id, relation_v1.version)
+      assert_response :forbidden, "Redacted relation shouldn't be visible via the version API."
+
+      # not even to a logged-in user
+      auth_header = bearer_authorization_header
+      get api_relation_version_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
+      assert_response :forbidden, "Redacted relation shouldn't be visible via the version API, even when logged in."
+    end
+
     ##
     # test the redaction of an old version of a relation, while not being
     # authorised.
@@ -101,44 +185,6 @@ module Api
       assert_response :success, "should be OK to redact old version as moderator with write_redactions scope."
     end
 
-    ##
-    # test that redacted relations aren't visible, regardless of
-    # authorisation except as moderator...
-    def test_version_redacted
-      relation = create(:relation, :with_history, :version => 2)
-      relation_v1 = relation.old_relations.find_by(:version => 1)
-      relation_v1.redact!(create(:redaction))
-
-      get api_old_relation_path(relation_v1.relation_id, relation_v1.version)
-      assert_response :forbidden, "Redacted relation shouldn't be visible via the version API."
-
-      # not even to a logged-in user
-      auth_header = bearer_authorization_header
-      get api_old_relation_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
-      assert_response :forbidden, "Redacted relation shouldn't be visible via the version API, even when logged in."
-    end
-
-    ##
-    # test that redacted relations aren't visible in the history
-    def test_history_redacted
-      relation = create(:relation, :with_history, :version => 2)
-      relation_v1 = relation.old_relations.find_by(:version => 1)
-      relation_v1.redact!(create(:redaction))
-
-      get api_relation_history_path(relation)
-      assert_response :success, "Redaction shouldn't have stopped history working."
-      assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 0,
-                    "redacted relation #{relation_v1.relation_id} version #{relation_v1.version} shouldn't be present in the history."
-
-      # not even to a logged-in user
-      auth_header = bearer_authorization_header
-      get api_old_relation_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
-      get api_relation_history_path(relation), :headers => auth_header
-      assert_response :success, "Redaction shouldn't have stopped history working."
-      assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 0,
-                    "redacted relation #{relation_v1.relation_id} version #{relation_v1.version} shouldn't be present in the history, even when logged in."
-    end
-
     ##
     # test the redaction of an old version of a relation, while being
     # authorised as a moderator.
@@ -153,17 +199,17 @@ module Api
 
       # check moderator can still see the redacted data, when passing
       # the appropriate flag
-      get api_old_relation_path(relation_v3.relation_id, relation_v3.version), :headers => auth_header
+      get api_relation_version_path(relation_v3.relation_id, relation_v3.version), :headers => auth_header
       assert_response :forbidden, "After redaction, relation should be gone for moderator, when flag not passed."
-      get api_old_relation_path(relation_v3.relation_id, relation_v3.version, :show_redactions => "true"), :headers => auth_header
+      get api_relation_version_path(relation_v3.relation_id, relation_v3.version, :show_redactions => "true"), :headers => auth_header
       assert_response :success, "After redaction, relation should not be gone for moderator, when flag passed."
 
       # and when accessed via history
-      get api_relation_history_path(relation), :headers => auth_header
+      get api_relation_versions_path(relation), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm relation[id='#{relation_v3.relation_id}'][version='#{relation_v3.version}']", 0,
                     "relation #{relation_v3.relation_id} version #{relation_v3.version} should not be present in the history for moderators when not passing flag."
-      get api_relation_history_path(relation, :show_redactions => "true"), :headers => auth_header
+      get api_relation_versions_path(relation, :show_redactions => "true"), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm relation[id='#{relation_v3.relation_id}'][version='#{relation_v3.version}']", 1,
                     "relation #{relation_v3.relation_id} version #{relation_v3.version} should still be present in the history for moderators when passing flag."
@@ -184,11 +230,11 @@ module Api
       auth_header = bearer_authorization_header
 
       # check can't see the redacted data
-      get api_old_relation_path(relation_v3.relation_id, relation_v3.version), :headers => auth_header
+      get api_relation_version_path(relation_v3.relation_id, relation_v3.version), :headers => auth_header
       assert_response :forbidden, "Redacted relation shouldn't be visible via the version API."
 
       # and when accessed via history
-      get api_relation_history_path(relation), :headers => auth_header
+      get api_relation_versions_path(relation), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm relation[id='#{relation_v3.relation_id}'][version='#{relation_v3.version}']", 0,
                     "redacted relation #{relation_v3.relation_id} version #{relation_v3.version} shouldn't be present in the history."
@@ -235,11 +281,11 @@ module Api
 
       # check moderator can still see the redacted data, without passing
       # the appropriate flag
-      get api_old_relation_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
+      get api_relation_version_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
       assert_response :success, "After unredaction, relation should not be gone for moderator."
 
       # and when accessed via history
-      get api_relation_history_path(relation), :headers => auth_header
+      get api_relation_versions_path(relation), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 1,
                     "relation #{relation_v1.relation_id} version #{relation_v1.version} should still be present in the history for moderators."
@@ -247,11 +293,11 @@ module Api
       auth_header = bearer_authorization_header
 
       # check normal user can now see the redacted data
-      get api_old_relation_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
+      get api_relation_version_path(relation_v1.relation_id, relation_v1.version), :headers => auth_header
       assert_response :success, "After redaction, node should not be gone for normal user."
 
       # and when accessed via history
-      get api_relation_history_path(relation), :headers => auth_header
+      get api_relation_versions_path(relation), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm relation[id='#{relation_v1.relation_id}'][version='#{relation_v1.version}']", 1,
                     "relation #{relation_v1.relation_id} version #{relation_v1.version} should still be present in the history for normal users."
@@ -259,49 +305,6 @@ module Api
 
     private
 
-    ##
-    # check that the current version of a relation is equivalent to the
-    # version which we're getting from the versions call.
-    def check_current_version(relation_id)
-      # get the current version
-      current_relation = with_controller(RelationsController.new) do
-        get :show, :params => { :id => relation_id }
-        assert_response :success, "can't get current relation #{relation_id}"
-        Relation.from_xml(@response.body)
-      end
-      assert_not_nil current_relation, "getting relation #{relation_id} returned nil"
-
-      # get the "old" version of the relation from the version method
-      get :version, :params => { :id => relation_id, :version => current_relation.version }
-      assert_response :success, "can't get old relation #{relation_id}, v#{current_relation.version}"
-      old_relation = Relation.from_xml(@response.body)
-
-      # check that the relations are identical
-      assert_relations_are_equal current_relation, old_relation
-    end
-
-    ##
-    # look at all the versions of the relation in the history and get each version from
-    # the versions call. check that they're the same.
-    def check_history_equals_versions(relation_id)
-      get :history, :params => { :id => relation_id }
-      assert_response :success, "can't get relation #{relation_id} from API"
-      history_doc = XML::Parser.string(@response.body).parse
-      assert_not_nil history_doc, "parsing relation #{relation_id} history failed"
-
-      history_doc.find("//osm/relation").each do |relation_doc|
-        history_relation = Relation.from_xml_node(relation_doc)
-        assert_not_nil history_relation, "parsing relation #{relation_id} version failed"
-
-        get :version, :params => { :id => relation_id, :version => history_relation.version }
-        assert_response :success, "couldn't get relation #{relation_id}, v#{history_relation.version}"
-        version_relation = Relation.from_xml(@response.body)
-        assert_not_nil version_relation, "failed to parse #{relation_id}, v#{history_relation.version}"
-
-        assert_relations_are_equal history_relation, version_relation
-      end
-    end
-
     def do_redact_redactable_relation(headers = {})
       relation = create(:relation, :with_history, :version => 4)
       relation_v3 = relation.old_relations.find_by(:version => 3)
@@ -309,7 +312,7 @@ module Api
     end
 
     def do_redact_relation(relation, redaction, headers = {})
-      get api_old_relation_path(relation.relation_id, relation.version)
+      get api_relation_version_path(relation.relation_id, relation.version)
       assert_response :success, "should be able to get version #{relation.version} of relation #{relation.relation_id}."
 
       # now redact it
index cc9eaf312375b322ba94f27ff38099125450fddf..a00dd84cf127a0bbbd90a917b1cdab3a38677e4c 100644 (file)
@@ -7,66 +7,118 @@ module Api
     def test_routes
       assert_routing(
         { :path => "/api/0.6/way/1/history", :method => :get },
-        { :controller => "api/old_ways", :action => "history", :id => "1" }
+        { :controller => "api/old_ways", :action => "index", :way_id => "1" }
       )
       assert_routing(
-        { :path => "/api/0.6/way/1/2", :method => :get },
-        { :controller => "api/old_ways", :action => "show", :id => "1", :version => "2" }
+        { :path => "/api/0.6/way/1/history.json", :method => :get },
+        { :controller => "api/old_ways", :action => "index", :way_id => "1", :format => "json" }
       )
       assert_routing(
-        { :path => "/api/0.6/way/1/history.json", :method => :get },
-        { :controller => "api/old_ways", :action => "history", :id => "1", :format => "json" }
+        { :path => "/api/0.6/way/1/2", :method => :get },
+        { :controller => "api/old_ways", :action => "show", :way_id => "1", :version => "2" }
       )
       assert_routing(
         { :path => "/api/0.6/way/1/2.json", :method => :get },
-        { :controller => "api/old_ways", :action => "show", :id => "1", :version => "2", :format => "json" }
+        { :controller => "api/old_ways", :action => "show", :way_id => "1", :version => "2", :format => "json" }
       )
       assert_routing(
         { :path => "/api/0.6/way/1/2/redact", :method => :post },
-        { :controller => "api/old_ways", :action => "redact", :id => "1", :version => "2" }
+        { :controller => "api/old_ways", :action => "redact", :way_id => "1", :version => "2" }
       )
     end
 
-    # -------------------------------------
-    # Test reading old ways.
-    # -------------------------------------
+    ##
+    # check that a visible way is returned properly
+    def test_index
+      way = create(:way, :with_history, :version => 2)
+
+      get api_way_versions_path(way)
 
-    def test_history_visible
-      # check that a visible way is returned properly
-      get api_way_history_path(create(:way, :with_history))
       assert_response :success
+      assert_dom "osm:root", 1 do
+        assert_dom "> way", 2 do |dom_ways|
+          assert_dom dom_ways[0], "> @id", way.id.to_s
+          assert_dom dom_ways[0], "> @version", "1"
+
+          assert_dom dom_ways[1], "> @id", way.id.to_s
+          assert_dom dom_ways[1], "> @version", "2"
+        end
+      end
     end
 
-    def test_history_invisible
-      # check that an invisible way's history is returned properly
-      get api_way_history_path(create(:way, :with_history, :deleted))
+    ##
+    # check that an invisible way's history is returned properly
+    def test_index_invisible
+      get api_way_versions_path(create(:way, :with_history, :deleted))
       assert_response :success
     end
 
-    def test_history_invalid
-      # check chat a non-existent way is not returned
-      get api_way_history_path(0)
+    ##
+    # check chat a non-existent way is not returned
+    def test_index_invalid
+      get api_way_versions_path(0)
       assert_response :not_found
     end
 
     ##
-    # check that we can retrieve versions of a way
-    def test_version
-      way = create(:way, :with_history)
-      used_way = create(:way, :with_history)
-      create(:relation_member, :member => used_way)
-      way_with_versions = create(:way, :with_history, :version => 4)
+    # test that redacted ways aren't visible in the history
+    def test_index_redacted
+      way = create(:way, :with_history, :version => 2)
+      way_v1 = way.old_ways.find_by(:version => 1)
+      way_v1.redact!(create(:redaction))
+
+      get api_way_versions_path(way)
+      assert_response :success, "Redaction shouldn't have stopped history working."
+      assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 0,
+                    "redacted way #{way_v1.way_id} version #{way_v1.version} shouldn't be present in the history."
+
+      # not even to a logged-in user
+      auth_header = bearer_authorization_header
+      get api_way_versions_path(way), :headers => auth_header
+      assert_response :success, "Redaction shouldn't have stopped history working."
+      assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 0,
+                    "redacted node #{way_v1.way_id} version #{way_v1.version} shouldn't be present in the history, even when logged in."
+    end
+
+    def test_show
+      way = create(:way, :with_history, :version => 2)
+
+      get api_way_version_path(way, 1)
+
+      assert_response :success
+      assert_dom "osm:root", 1 do
+        assert_dom "> way", 1 do
+          assert_dom "> @id", way.id.to_s
+          assert_dom "> @version", "1"
+        end
+      end
 
-      create(:way_tag, :way => way)
-      create(:way_tag, :way => used_way)
-      create(:way_tag, :way => way_with_versions)
-      propagate_tags(way, way.old_ways.last)
-      propagate_tags(used_way, used_way.old_ways.last)
-      propagate_tags(way_with_versions, way_with_versions.old_ways.last)
+      get api_way_version_path(way, 2)
 
-      check_current_version(way.id)
-      check_current_version(used_way.id)
-      check_current_version(way_with_versions.id)
+      assert_response :success
+      assert_dom "osm:root", 1 do
+        assert_dom "> way", 1 do
+          assert_dom "> @id", way.id.to_s
+          assert_dom "> @version", "2"
+        end
+      end
+    end
+
+    ##
+    # test that redacted ways aren't visible, regardless of
+    # authorisation except as moderator...
+    def test_show_redacted
+      way = create(:way, :with_history, :version => 2)
+      way_v1 = way.old_ways.find_by(:version => 1)
+      way_v1.redact!(create(:redaction))
+
+      get api_way_version_path(way_v1.way_id, way_v1.version)
+      assert_response :forbidden, "Redacted way shouldn't be visible via the version API."
+
+      # not even to a logged-in user
+      auth_header = bearer_authorization_header
+      get api_way_version_path(way_v1.way_id, way_v1.version), :headers => auth_header
+      assert_response :forbidden, "Redacted way shouldn't be visible via the version API, even when logged in."
     end
 
     ##
@@ -142,43 +194,6 @@ module Api
       assert_response :success, "should be OK to redact old version as moderator with write_redactions scope."
     end
 
-    ##
-    # test that redacted ways aren't visible, regardless of
-    # authorisation except as moderator...
-    def test_version_redacted
-      way = create(:way, :with_history, :version => 2)
-      way_v1 = way.old_ways.find_by(:version => 1)
-      way_v1.redact!(create(:redaction))
-
-      get api_old_way_path(way_v1.way_id, way_v1.version)
-      assert_response :forbidden, "Redacted way shouldn't be visible via the version API."
-
-      # not even to a logged-in user
-      auth_header = bearer_authorization_header
-      get api_old_way_path(way_v1.way_id, way_v1.version), :headers => auth_header
-      assert_response :forbidden, "Redacted way shouldn't be visible via the version API, even when logged in."
-    end
-
-    ##
-    # test that redacted ways aren't visible in the history
-    def test_history_redacted
-      way = create(:way, :with_history, :version => 2)
-      way_v1 = way.old_ways.find_by(:version => 1)
-      way_v1.redact!(create(:redaction))
-
-      get api_way_history_path(way)
-      assert_response :success, "Redaction shouldn't have stopped history working."
-      assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 0,
-                    "redacted way #{way_v1.way_id} version #{way_v1.version} shouldn't be present in the history."
-
-      # not even to a logged-in user
-      auth_header = bearer_authorization_header
-      get api_way_history_path(way), :headers => auth_header
-      assert_response :success, "Redaction shouldn't have stopped history working."
-      assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 0,
-                    "redacted node #{way_v1.way_id} version #{way_v1.version} shouldn't be present in the history, even when logged in."
-    end
-
     ##
     # test the redaction of an old version of a way, while being
     # authorised as a moderator.
@@ -192,17 +207,17 @@ module Api
 
       # check moderator can still see the redacted data, when passing
       # the appropriate flag
-      get api_old_way_path(way_v3.way_id, way_v3.version), :headers => auth_header
+      get api_way_version_path(way_v3.way_id, way_v3.version), :headers => auth_header
       assert_response :forbidden, "After redaction, node should be gone for moderator, when flag not passed."
-      get api_old_way_path(way_v3.way_id, way_v3.version, :show_redactions => "true"), :headers => auth_header
+      get api_way_version_path(way_v3.way_id, way_v3.version, :show_redactions => "true"), :headers => auth_header
       assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
 
       # and when accessed via history
-      get api_way_history_path(way), :headers => auth_header
+      get api_way_versions_path(way), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm way[id='#{way_v3.way_id}'][version='#{way_v3.version}']", 0,
                     "way #{way_v3.way_id} version #{way_v3.version} should not be present in the history for moderators when not passing flag."
-      get api_way_history_path(way, :show_redactions => "true"), :headers => auth_header
+      get api_way_versions_path(way, :show_redactions => "true"), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm way[id='#{way_v3.way_id}'][version='#{way_v3.version}']", 1,
                     "way #{way_v3.way_id} version #{way_v3.version} should still be present in the history for moderators when passing flag."
@@ -222,11 +237,11 @@ module Api
       auth_header = bearer_authorization_header
 
       # check can't see the redacted data
-      get api_old_way_path(way_v3.way_id, way_v3.version), :headers => auth_header
+      get api_way_version_path(way_v3.way_id, way_v3.version), :headers => auth_header
       assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
 
       # and when accessed via history
-      get api_way_history_path(way), :headers => auth_header
+      get api_way_versions_path(way), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm way[id='#{way_v3.way_id}'][version='#{way_v3.version}']", 0,
                     "redacted way #{way_v3.way_id} version #{way_v3.version} shouldn't be present in the history."
@@ -274,11 +289,11 @@ module Api
 
       # check moderator can still see the unredacted data, without passing
       # the appropriate flag
-      get api_old_way_path(way_v1.way_id, way_v1.version), :headers => auth_header
+      get api_way_version_path(way_v1.way_id, way_v1.version), :headers => auth_header
       assert_response :success, "After unredaction, node should not be gone for moderator."
 
       # and when accessed via history
-      get api_way_history_path(way), :headers => auth_header
+      get api_way_versions_path(way), :headers => auth_header
       assert_response :success, "Unredaction shouldn't have stopped history working."
       assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 1,
                     "way #{way_v1.way_id} version #{way_v1.version} should still be present in the history for moderators."
@@ -286,11 +301,11 @@ module Api
       auth_header = bearer_authorization_header
 
       # check normal user can now see the unredacted data
-      get api_old_way_path(way_v1.way_id, way_v1.version), :headers => auth_header
+      get api_way_version_path(way_v1.way_id, way_v1.version), :headers => auth_header
       assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
 
       # and when accessed via history
-      get api_way_history_path(way), :headers => auth_header
+      get api_way_versions_path(way), :headers => auth_header
       assert_response :success, "Redaction shouldn't have stopped history working."
       assert_select "osm way[id='#{way_v1.way_id}'][version='#{way_v1.version}']", 1,
                     "way #{way_v1.way_id} version #{way_v1.version} should still be present in the history for normal users."
@@ -298,32 +313,11 @@ module Api
 
     private
 
-    ##
-    # check that the current version of a way is equivalent to the
-    # version which we're getting from the versions call.
-    def check_current_version(way_id)
-      # get the current version
-      current_way = with_controller(WaysController.new) do
-        get api_way_path(way_id)
-        assert_response :success, "can't get current way #{way_id}"
-        Way.from_xml(@response.body)
-      end
-      assert_not_nil current_way, "getting way #{way_id} returned nil"
-
-      # get the "old" version of the way from the version method
-      get api_old_way_path(way_id, current_way.version)
-      assert_response :success, "can't get old way #{way_id}, v#{current_way.version}"
-      old_way = Way.from_xml(@response.body)
-
-      # check that the ways are identical
-      assert_ways_are_equal current_way, old_way
-    end
-
     ##
     # look at all the versions of the way in the history and get each version from
     # the versions call. check that they're the same.
     def check_history_equals_versions(way_id)
-      get api_way_history_path(way_id)
+      get api_way_versions_path(way_id)
       assert_response :success, "can't get way #{way_id} from API"
       history_doc = XML::Parser.string(@response.body).parse
       assert_not_nil history_doc, "parsing way #{way_id} history failed"
@@ -332,7 +326,7 @@ module Api
         history_way = Way.from_xml_node(way_doc)
         assert_not_nil history_way, "parsing way #{way_id} version failed"
 
-        get api_old_way_path(way_id, history_way.version)
+        get api_way_version_path(way_id, history_way.version)
         assert_response :success, "couldn't get way #{way_id}, v#{history_way.version}"
         version_way = Way.from_xml(@response.body)
         assert_not_nil version_way, "failed to parse #{way_id}, v#{history_way.version}"
@@ -348,17 +342,11 @@ module Api
     end
 
     def do_redact_way(way, redaction, headers = {})
-      get api_old_way_path(way.way_id, way.version)
+      get api_way_version_path(way.way_id, way.version)
       assert_response :success, "should be able to get version #{way.version} of way #{way.way_id}."
 
       # now redact it
       post way_version_redact_path(way.way_id, way.version), :params => { :redaction => redaction.id }, :headers => headers
     end
-
-    def propagate_tags(way, old_way)
-      way.tags.each do |k, v|
-        create(:old_way_tag, :old_way => old_way, :k => k, :v => v)
-      end
-    end
   end
 end
index 5e480b69c0b1d02584554a2ba43b9578f444f8c2..9e2972495756de8b987d642b5f90ab4d4ee7667a 100644 (file)
@@ -782,7 +782,7 @@ module Api
 
       # check the ordering in the history tables:
       with_controller(OldRelationsController.new) do
-        get api_old_relation_path(relation_id, 2)
+        get api_relation_version_path(relation_id, 2)
         assert_response :success, "can't read back version 2 of the relation #{relation_id}"
         check_ordering(doc, @response.body)
       end
@@ -862,7 +862,7 @@ module Api
 
       # check the ordering in the history tables:
       with_controller(OldRelationsController.new) do
-        get api_old_relation_path(relation_id, 1)
+        get api_relation_version_path(relation_id, 1)
         assert_response :success, "can't read back version 1 of the relation: #{@response.body}"
         check_ordering(doc, @response.body)
       end
@@ -1084,7 +1084,7 @@ module Api
         get api_relation_path(id)
       else
         with_controller(OldRelationsController.new) do
-          get api_old_relation_path(id, ver)
+          get api_relation_version_path(id, ver)
         end
       end
       assert_response :success
index 8e3a14ab6c8717a5860dbb7a1d8ed2284ce9bad2..aba69b03aa4135985daa3683f1bdb3ea6ecc9e8f 100644 (file)
@@ -114,7 +114,7 @@ class OldNodesControllerTest < ActionDispatch::IntegrationTest
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_node_path node, 1}']", :count => 0
     end
-    assert_select ".secondary-actions a[href='#{api_old_node_path node, 1}']", :count => 1
+    assert_select ".secondary-actions a[href='#{api_node_version_path node, 1}']", :count => 1
     assert_select ".secondary-actions a[href='#{node_path node}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_node_path node, 1, :params => { :show_redactions => true }}']", :count => 0
     assert_select ".secondary-actions a[href='#{node_history_path node}']", :count => 1
@@ -129,7 +129,7 @@ class OldNodesControllerTest < ActionDispatch::IntegrationTest
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_node_path node, 1}']", :count => 0
     end
-    assert_select ".secondary-actions a[href='#{api_old_node_path node, 1}']", :count => 1
+    assert_select ".secondary-actions a[href='#{api_node_version_path node, 1}']", :count => 1
     assert_select ".secondary-actions a[href='#{node_path node}']", :count => 1
     assert_select ".secondary-actions a[href='#{node_history_path node}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_node_path node, 2}']", :count => 1
@@ -141,7 +141,7 @@ class OldNodesControllerTest < ActionDispatch::IntegrationTest
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_node_path node, 2}']", :count => 0
     end
-    assert_select ".secondary-actions a[href='#{api_old_node_path node, 2}']", :count => 1
+    assert_select ".secondary-actions a[href='#{api_node_version_path node, 2}']", :count => 1
     assert_select ".secondary-actions a[href='#{node_path node}']", :count => 1
     assert_select ".secondary-actions a[href='#{node_history_path node}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_node_path node, 1}']", :count => 1
@@ -157,7 +157,7 @@ class OldNodesControllerTest < ActionDispatch::IntegrationTest
     assert_select ".secondary-actions a[href='#{node_path node}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_node_path node, 1, :params => { :show_redactions => true }}']", :count => 0
     assert_select ".secondary-actions a[href='#{old_node_path node, 1}']", :count => 0
-    assert_select ".secondary-actions a[href='#{api_old_node_path node, 1}']", :count => 0
+    assert_select ".secondary-actions a[href='#{api_node_version_path node, 1}']", :count => 0
   end
 
   test "show unrevealed redacted versions to regular users" do
@@ -171,7 +171,7 @@ class OldNodesControllerTest < ActionDispatch::IntegrationTest
     assert_select ".secondary-actions a[href='#{node_path node}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_node_path node, 1, :params => { :show_redactions => true }}']", :count => 0
     assert_select ".secondary-actions a[href='#{old_node_path node, 1}']", :count => 0
-    assert_select ".secondary-actions a[href='#{api_old_node_path node, 1}']", :count => 0
+    assert_select ".secondary-actions a[href='#{api_node_version_path node, 1}']", :count => 0
   end
 
   test "show unrevealed redacted versions to moderators" do
@@ -185,7 +185,7 @@ class OldNodesControllerTest < ActionDispatch::IntegrationTest
     assert_select ".secondary-actions a[href='#{node_path node}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_node_path node, 1, :params => { :show_redactions => true }}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_node_path node, 1}']", :count => 0
-    assert_select ".secondary-actions a[href='#{api_old_node_path node, 1}']", :count => 0
+    assert_select ".secondary-actions a[href='#{api_node_version_path node, 1}']", :count => 0
   end
 
   test "don't reveal redacted versions to anonymous users" do
index 3ede1842b5d35137602c92dde30a3ddf1e83f9b2..cd6737dca32070b651f30dba7a2f9242dabe8d27 100644 (file)
@@ -64,7 +64,7 @@ class OldRelationsControllerTest < ActionDispatch::IntegrationTest
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_relation_path relation, 1}']", :count => 0
     end
-    assert_select ".secondary-actions a[href='#{api_old_relation_path relation, 1}']", :count => 1
+    assert_select ".secondary-actions a[href='#{api_relation_version_path relation, 1}']", :count => 1
     assert_select ".secondary-actions a[href='#{relation_path relation}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 1, :params => { :show_redactions => true }}']", :count => 0
     assert_select ".secondary-actions a[href='#{relation_history_path relation}']", :count => 1
@@ -79,7 +79,7 @@ class OldRelationsControllerTest < ActionDispatch::IntegrationTest
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_relation_path relation, 1}']", :count => 0
     end
-    assert_select ".secondary-actions a[href='#{api_old_relation_path relation, 1}']", :count => 1
+    assert_select ".secondary-actions a[href='#{api_relation_version_path relation, 1}']", :count => 1
     assert_select ".secondary-actions a[href='#{relation_path relation}']", :count => 1
     assert_select ".secondary-actions a[href='#{relation_history_path relation}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 2}']", :count => 1
@@ -91,7 +91,7 @@ class OldRelationsControllerTest < ActionDispatch::IntegrationTest
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_relation_path relation, 2}']", :count => 0
     end
-    assert_select ".secondary-actions a[href='#{api_old_relation_path relation, 2}']", :count => 1
+    assert_select ".secondary-actions a[href='#{api_relation_version_path relation, 2}']", :count => 1
     assert_select ".secondary-actions a[href='#{relation_path relation}']", :count => 1
     assert_select ".secondary-actions a[href='#{relation_history_path relation}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 1}']", :count => 1
@@ -116,7 +116,7 @@ class OldRelationsControllerTest < ActionDispatch::IntegrationTest
     assert_select ".secondary-actions a[href='#{relation_path relation}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 1, :params => { :show_redactions => true }}']", :count => 0
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 1}']", :count => 0
-    assert_select ".secondary-actions a[href='#{api_old_relation_path relation, 1}']", :count => 0
+    assert_select ".secondary-actions a[href='#{api_relation_version_path relation, 1}']", :count => 0
   end
 
   test "show unrevealed redacted versions to regular users" do
@@ -130,7 +130,7 @@ class OldRelationsControllerTest < ActionDispatch::IntegrationTest
     assert_select ".secondary-actions a[href='#{relation_path relation}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 1, :params => { :show_redactions => true }}']", :count => 0
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 1}']", :count => 0
-    assert_select ".secondary-actions a[href='#{api_old_relation_path relation, 1}']", :count => 0
+    assert_select ".secondary-actions a[href='#{api_relation_version_path relation, 1}']", :count => 0
   end
 
   test "show unrevealed redacted versions to moderators" do
@@ -144,7 +144,7 @@ class OldRelationsControllerTest < ActionDispatch::IntegrationTest
     assert_select ".secondary-actions a[href='#{relation_path relation}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 1, :params => { :show_redactions => true }}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 1}']", :count => 0
-    assert_select ".secondary-actions a[href='#{api_old_relation_path relation, 1}']", :count => 0
+    assert_select ".secondary-actions a[href='#{api_relation_version_path relation, 1}']", :count => 0
   end
 
   test "don't reveal redacted versions to anonymous users" do
index c7b383202bb45081f2396b4a916e93108f9ab606..3ac6eaf2f0fd87c5466578627f8487a979ae6386 100644 (file)
@@ -64,7 +64,7 @@ class OldWaysControllerTest < ActionDispatch::IntegrationTest
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_way_path way, 1}']", :count => 0
     end
-    assert_select ".secondary-actions a[href='#{api_old_way_path way, 1}']", :count => 1
+    assert_select ".secondary-actions a[href='#{api_way_version_path way, 1}']", :count => 1
     assert_select ".secondary-actions a[href='#{way_path way}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_way_path way, 1, :params => { :show_redactions => true }}']", :count => 0
     assert_select ".secondary-actions a[href='#{way_history_path way}']", :count => 1
@@ -79,7 +79,7 @@ class OldWaysControllerTest < ActionDispatch::IntegrationTest
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_way_path way, 1}']", :count => 0
     end
-    assert_select ".secondary-actions a[href='#{api_old_way_path way, 1}']", :count => 1
+    assert_select ".secondary-actions a[href='#{api_way_version_path way, 1}']", :count => 1
     assert_select ".secondary-actions a[href='#{way_path way}']", :count => 1
     assert_select ".secondary-actions a[href='#{way_history_path way}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_way_path way, 2}']", :count => 1
@@ -91,7 +91,7 @@ class OldWaysControllerTest < ActionDispatch::IntegrationTest
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_way_path way, 2}']", :count => 0
     end
-    assert_select ".secondary-actions a[href='#{api_old_way_path way, 2}']", :count => 1
+    assert_select ".secondary-actions a[href='#{api_way_version_path way, 2}']", :count => 1
     assert_select ".secondary-actions a[href='#{way_path way}']", :count => 1
     assert_select ".secondary-actions a[href='#{way_history_path way}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_way_path way, 1}']", :count => 1
@@ -121,7 +121,7 @@ class OldWaysControllerTest < ActionDispatch::IntegrationTest
     assert_select ".secondary-actions a[href='#{way_path way}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_way_path way, 1, :params => { :show_redactions => true }}']", :count => 0
     assert_select ".secondary-actions a[href='#{old_way_path way, 1}']", :count => 0
-    assert_select ".secondary-actions a[href='#{api_old_way_path way, 1}']", :count => 0
+    assert_select ".secondary-actions a[href='#{api_way_version_path way, 1}']", :count => 0
   end
 
   test "show unrevealed redacted versions to regular users" do
@@ -135,7 +135,7 @@ class OldWaysControllerTest < ActionDispatch::IntegrationTest
     assert_select ".secondary-actions a[href='#{way_path way}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_way_path way, 1, :params => { :show_redactions => true }}']", :count => 0
     assert_select ".secondary-actions a[href='#{old_way_path way, 1}']", :count => 0
-    assert_select ".secondary-actions a[href='#{api_old_way_path way, 1}']", :count => 0
+    assert_select ".secondary-actions a[href='#{api_way_version_path way, 1}']", :count => 0
   end
 
   test "show unrevealed redacted versions to moderators" do
@@ -149,7 +149,7 @@ class OldWaysControllerTest < ActionDispatch::IntegrationTest
     assert_select ".secondary-actions a[href='#{way_path way}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_way_path way, 1, :params => { :show_redactions => true }}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_way_path way, 1}']", :count => 0
-    assert_select ".secondary-actions a[href='#{api_old_way_path way, 1}']", :count => 0
+    assert_select ".secondary-actions a[href='#{api_way_version_path way, 1}']", :count => 0
   end
 
   test "don't reveal redacted versions to anonymous users" do
diff --git a/test/integration/node_versions_test.rb b/test/integration/node_versions_test.rb
new file mode 100644 (file)
index 0000000..71251aa
--- /dev/null
@@ -0,0 +1,194 @@
+require "test_helper"
+
+class NodeVersionsTest < ActionDispatch::IntegrationTest
+  ##
+  # test the version call by submitting several revisions of a new node
+  # to the API and ensuring that later calls to version return the
+  # matching versions of the object.
+  def test_version
+    private_user = create(:user, :data_public => false)
+    private_node = create(:node, :with_history, :version => 4, :lat => 0, :lon => 0, :changeset => create(:changeset, :user => private_user))
+    user = create(:user)
+    node = create(:node, :with_history, :version => 4, :lat => 0, :lon => 0, :changeset => create(:changeset, :user => user))
+    create_list(:node_tag, 2, :node => node)
+    # Ensure that the current tags are propagated to the history too
+    propagate_tags(node, node.old_nodes.last)
+
+    ## First try this with a non-public user
+    auth_header = bearer_authorization_header private_user
+
+    # setup a simple XML node
+    xml_doc = xml_for_node(private_node)
+    xml_node = xml_doc.find("//osm/node").first
+    node_id = private_node.id
+
+    # keep a hash of the versions => string, as we'll need something
+    # to test against later
+    versions = {}
+
+    # save a version for later checking
+    versions[xml_node["version"]] = xml_doc.to_s
+
+    # randomly move the node about
+    3.times do
+      # move the node somewhere else
+      xml_node["lat"] = precision(rand - 0.5).to_s
+      xml_node["lon"] = precision(rand - 0.5).to_s
+      with_controller(NodesController.new) do
+        put api_node_path(node_id), :params => xml_doc.to_s, :headers => auth_header
+        assert_response :forbidden, "Should have rejected node update"
+        xml_node["version"] = @response.body.to_s
+      end
+      # save a version for later checking
+      versions[xml_node["version"]] = xml_doc.to_s
+    end
+
+    # add a bunch of random tags
+    3.times do
+      xml_tag = XML::Node.new("tag")
+      xml_tag["k"] = random_string
+      xml_tag["v"] = random_string
+      xml_node << xml_tag
+      with_controller(NodesController.new) do
+        put api_node_path(node_id), :params => xml_doc.to_s, :headers => auth_header
+        assert_response :forbidden,
+                        "should have rejected node #{node_id} (#{@response.body}) with forbidden"
+        xml_node["version"] = @response.body.to_s
+      end
+      # save a version for later checking
+      versions[xml_node["version"]] = xml_doc.to_s
+    end
+
+    # probably should check that they didn't get written to the database
+
+    ## Now do it with the public user
+    auth_header = bearer_authorization_header user
+
+    # setup a simple XML node
+
+    xml_doc = xml_for_node(node)
+    xml_node = xml_doc.find("//osm/node").first
+    node_id = node.id
+
+    # keep a hash of the versions => string, as we'll need something
+    # to test against later
+    versions = {}
+
+    # save a version for later checking
+    versions[xml_node["version"]] = xml_doc.to_s
+
+    # randomly move the node about
+    3.times do
+      # move the node somewhere else
+      xml_node["lat"] = precision(rand - 0.5).to_s
+      xml_node["lon"] = precision(rand - 0.5).to_s
+      with_controller(NodesController.new) do
+        put api_node_path(node_id), :params => xml_doc.to_s, :headers => auth_header
+        assert_response :success
+        xml_node["version"] = @response.body.to_s
+      end
+      # save a version for later checking
+      versions[xml_node["version"]] = xml_doc.to_s
+    end
+
+    # add a bunch of random tags
+    3.times do
+      xml_tag = XML::Node.new("tag")
+      xml_tag["k"] = random_string
+      xml_tag["v"] = random_string
+      xml_node << xml_tag
+      with_controller(NodesController.new) do
+        put api_node_path(node_id), :params => xml_doc.to_s, :headers => auth_header
+        assert_response :success,
+                        "couldn't update node #{node_id} (#{@response.body})"
+        xml_node["version"] = @response.body.to_s
+      end
+      # save a version for later checking
+      versions[xml_node["version"]] = xml_doc.to_s
+    end
+
+    # check all the versions
+    versions.each_key do |key|
+      get api_node_version_path(node_id, key.to_i)
+
+      assert_response :success,
+                      "couldn't get version #{key.to_i} of node #{node_id}"
+
+      check_node = Node.from_xml(versions[key])
+      api_node = Node.from_xml(@response.body.to_s)
+
+      assert_nodes_are_equal check_node, api_node
+    end
+  end
+
+  ##
+  # Test that getting the current version is identical to picking
+  # that version with the version URI call.
+  def test_current_version
+    node = create(:node, :with_history)
+    used_node = create(:node, :with_history)
+    create(:way_node, :node => used_node)
+    node_used_by_relationship = create(:node, :with_history)
+    create(:relation_member, :member => node_used_by_relationship)
+    node_with_versions = create(:node, :with_history, :version => 4)
+
+    create(:node_tag, :node => node)
+    create(:node_tag, :node => used_node)
+    create(:node_tag, :node => node_used_by_relationship)
+    create(:node_tag, :node => node_with_versions)
+    propagate_tags(node, node.old_nodes.last)
+    propagate_tags(used_node, used_node.old_nodes.last)
+    propagate_tags(node_used_by_relationship, node_used_by_relationship.old_nodes.last)
+    propagate_tags(node_with_versions, node_with_versions.old_nodes.last)
+
+    check_current_version(node)
+    check_current_version(used_node)
+    check_current_version(node_used_by_relationship)
+    check_current_version(node_with_versions)
+  end
+
+  private
+
+  def check_current_version(node_id)
+    # get the current version of the node
+    current_node = with_controller(NodesController.new) do
+      get api_node_path(node_id)
+      assert_response :success, "cant get current node #{node_id}"
+      Node.from_xml(@response.body)
+    end
+    assert_not_nil current_node, "getting node #{node_id} returned nil"
+
+    # get the "old" version of the node from the old_node interface
+    get api_node_version_path(node_id, current_node.version)
+    assert_response :success, "cant get old node #{node_id}, v#{current_node.version}"
+    old_node = Node.from_xml(@response.body)
+
+    # check the nodes are the same
+    assert_nodes_are_equal current_node, old_node
+  end
+
+  ##
+  # returns a 16 character long string with some nasty characters in it.
+  # this ought to stress-test the tag handling as well as the versioning.
+  def random_string
+    letters = [["!", '"', "$", "&", ";", "@"],
+               ("a".."z").to_a,
+               ("A".."Z").to_a,
+               ("0".."9").to_a].flatten
+    (1..16).map { letters[rand(letters.length)] }.join
+  end
+
+  ##
+  # truncate a floating point number to the scale that it is stored in
+  # the database. otherwise rounding errors can produce failing unit
+  # tests when they shouldn't.
+  def precision(f)
+    (f * GeoRecord::SCALE).round.to_f / GeoRecord::SCALE
+  end
+
+  def propagate_tags(node, old_node)
+    node.tags.each do |k, v|
+      create(:old_node_tag, :old_node => old_node, :k => k, :v => v)
+    end
+  end
+end
diff --git a/test/integration/way_versions_test.rb b/test/integration/way_versions_test.rb
new file mode 100644 (file)
index 0000000..866e485
--- /dev/null
@@ -0,0 +1,52 @@
+require "test_helper"
+
+class WayVersionsTest < ActionDispatch::IntegrationTest
+  ##
+  # check that we can retrieve versions of a way
+  def test_version
+    way = create(:way, :with_history)
+    used_way = create(:way, :with_history)
+    create(:relation_member, :member => used_way)
+    way_with_versions = create(:way, :with_history, :version => 4)
+
+    create(:way_tag, :way => way)
+    create(:way_tag, :way => used_way)
+    create(:way_tag, :way => way_with_versions)
+    propagate_tags(way, way.old_ways.last)
+    propagate_tags(used_way, used_way.old_ways.last)
+    propagate_tags(way_with_versions, way_with_versions.old_ways.last)
+
+    check_current_version(way.id)
+    check_current_version(used_way.id)
+    check_current_version(way_with_versions.id)
+  end
+
+  private
+
+  ##
+  # check that the current version of a way is equivalent to the
+  # version which we're getting from the versions call.
+  def check_current_version(way_id)
+    # get the current version
+    current_way = with_controller(WaysController.new) do
+      get api_way_path(way_id)
+      assert_response :success, "can't get current way #{way_id}"
+      Way.from_xml(@response.body)
+    end
+    assert_not_nil current_way, "getting way #{way_id} returned nil"
+
+    # get the "old" version of the way from the version method
+    get api_way_version_path(way_id, current_way.version)
+    assert_response :success, "can't get old way #{way_id}, v#{current_way.version}"
+    old_way = Way.from_xml(@response.body)
+
+    # check that the ways are identical
+    assert_ways_are_equal current_way, old_way
+  end
+
+  def propagate_tags(way, old_way)
+    way.tags.each do |k, v|
+      create(:old_way_tag, :old_way => old_way, :k => k, :v => v)
+    end
+  end
+end
index 902fdb90605625ba1d8243d016410cbef207b0e7..5d68101b7e3873980fe02086e74be0390891719d 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
   integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==
 
 "@stylistic/eslint-plugin-js@^3.0.0":
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin-js/-/eslint-plugin-js-3.0.1.tgz#15638c55a9adab2c110243a9f0d812264b067aab"
-  integrity sha512-hjp6BKXSUdlY4l20pDb0EjIB5PtQDGihk2EUKCjJ5gaRVfcmMMkaIyVd/yK3oH7OLxWWBxJ8qSSo+zEdkmpnYA==
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin-js/-/eslint-plugin-js-3.1.0.tgz#b36292b09bd810ea1b34e0720512f137335ef745"
+  integrity sha512-lQktsOiCr8S6StG29C5fzXYxLOD6ID1rp4j6TRS+E/qY1xd59Fm7dy5qm9UauJIEoSTlYx6yGsCHYh5UkgXPyg==
   dependencies:
     eslint-visitor-keys "^4.2.0"
     espree "^10.3.0"