]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/5387' live
authorTom Hughes <tom@compton.nu>
Wed, 11 Dec 2024 17:09:07 +0000 (17:09 +0000)
committerTom Hughes <tom@compton.nu>
Wed, 11 Dec 2024 17:09:07 +0000 (17:09 +0000)
22 files changed:
app/abilities/api_ability.rb
app/assets/stylesheets/common.scss
app/assets/stylesheets/parameters.scss
app/assets/stylesheets/screen-auto-ltr.scss [new file with mode: 0644]
app/assets/stylesheets/screen-auto-rtl.rtlcss.scss [new file with mode: 0644]
app/assets/stylesheets/screen-ltr.scss [deleted file]
app/assets/stylesheets/screen-manual-ltr.scss [new file with mode: 0644]
app/assets/stylesheets/screen-manual-rtl.rtlcss.scss [new file with mode: 0644]
app/assets/stylesheets/screen-rtl.rtlcss.scss [deleted file]
app/controllers/api/traces/data_controller.rb [new file with mode: 0644]
app/controllers/api/traces_controller.rb
app/controllers/application_controller.rb
app/controllers/preferences_controller.rb
app/views/layouts/_head.html.erb
app/views/layouts/site.html.erb
app/views/preferences/edit.html.erb
app/views/preferences/show.html.erb
config/locales/en.yml
config/routes.rb
test/controllers/api/traces/data_controller_test.rb [new file with mode: 0644]
test/controllers/api/traces_controller_test.rb
test/controllers/preferences_controller_test.rb

index 96ed9b080fa3b79f4692aab8c52c21aa1c4efe5d..c790da66ab522f1b6fcbed3baee9cfa214b5b4f1 100644 (file)
@@ -22,7 +22,7 @@ class ApiAbility
 
       if user&.active?
         can [:comment, :close, :reopen], Note
-        can [:create, :show, :update, :destroy, :data], Trace
+        can [:create, :show, :update, :destroy], Trace
         can [:details, :gpx_files], User
         can [:index, :show, :update, :update_all, :destroy], UserPreference
 
index c1e71cc2d7e53d892214df5e1bc4f82848ab11e6..323f60e08c192a91d2934f5e2309c1841591f357 100644 (file)
@@ -506,6 +506,16 @@ body.small-nav {
 }
 
 @include color-mode(dark) {
+  .leaflet-container .leaflet-control-attribution a {
+    color: var(--bs-link-color);
+  }
+
+  .leaflet-control-scale-line {
+    border-color: rgba(var(--bs-light-rgb), .75) !important;
+  }
+}
+
+@mixin dark-map-color-scheme {
   .leaflet-tile-container,
   .mapkey-table-entry td:first-child > * {
     filter: var(--dark-mode-map-filter);
@@ -514,13 +524,15 @@ body.small-nav {
   .leaflet-tile-container .leaflet-tile {
     filter: none;
   }
+}
 
-  .leaflet-container .leaflet-control-attribution a {
-    color: var(--bs-link-color);
-  }
+body[data-map-theme="dark"] {
+  @include dark-map-color-scheme;
+}
 
-  .leaflet-control-scale-line {
-    border-color: rgba(var(--bs-light-rgb), .75) !important;
+@include color-mode(dark) {
+  body:not([data-map-theme]) {
+    @include dark-map-color-scheme;
   }
 }
 
index 28bf569016a607d81b4aa01b994226ca8366845e..07549d69bb33e939238f98e6ef6d1e44eea4a816 100644 (file)
@@ -20,4 +20,3 @@ $table-border-factor: .1;
 $list-group-hover-bg: rgba(var(--bs-emphasis-color-rgb), .075);
 
 $enable-negative-margins: true;
-$color-mode-type: media-query;
diff --git a/app/assets/stylesheets/screen-auto-ltr.scss b/app/assets/stylesheets/screen-auto-ltr.scss
new file mode 100644 (file)
index 0000000..89e3159
--- /dev/null
@@ -0,0 +1,3 @@
+@use "common" with (
+  $color-mode-type: media-query
+);
diff --git a/app/assets/stylesheets/screen-auto-rtl.rtlcss.scss b/app/assets/stylesheets/screen-auto-rtl.rtlcss.scss
new file mode 100644 (file)
index 0000000..89e3159
--- /dev/null
@@ -0,0 +1,3 @@
+@use "common" with (
+  $color-mode-type: media-query
+);
diff --git a/app/assets/stylesheets/screen-ltr.scss b/app/assets/stylesheets/screen-ltr.scss
deleted file mode 100644 (file)
index c525060..0000000
+++ /dev/null
@@ -1 +0,0 @@
-@import "common";
diff --git a/app/assets/stylesheets/screen-manual-ltr.scss b/app/assets/stylesheets/screen-manual-ltr.scss
new file mode 100644 (file)
index 0000000..00f65f7
--- /dev/null
@@ -0,0 +1,3 @@
+@use "common" with (
+  $color-mode-type: data
+);
diff --git a/app/assets/stylesheets/screen-manual-rtl.rtlcss.scss b/app/assets/stylesheets/screen-manual-rtl.rtlcss.scss
new file mode 100644 (file)
index 0000000..00f65f7
--- /dev/null
@@ -0,0 +1,3 @@
+@use "common" with (
+  $color-mode-type: data
+);
diff --git a/app/assets/stylesheets/screen-rtl.rtlcss.scss b/app/assets/stylesheets/screen-rtl.rtlcss.scss
deleted file mode 100644 (file)
index c525060..0000000
+++ /dev/null
@@ -1 +0,0 @@
-@import "common";
diff --git a/app/controllers/api/traces/data_controller.rb b/app/controllers/api/traces/data_controller.rb
new file mode 100644 (file)
index 0000000..e04931c
--- /dev/null
@@ -0,0 +1,36 @@
+module Api
+  module Traces
+    class DataController < ApiController
+      before_action :set_locale
+      before_action :authorize
+
+      authorize_resource :trace
+
+      before_action :offline_error
+
+      def show
+        trace = Trace.visible.find(params[:trace_id])
+
+        if trace.public? || trace.user == current_user
+          if request.format == Mime[:xml]
+            send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
+          elsif request.format == Mime[:gpx]
+            send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
+          elsif trace.file.attached?
+            redirect_to rails_blob_path(trace.file, :disposition => "attachment")
+          else
+            send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
+          end
+        else
+          head :forbidden
+        end
+      end
+
+      private
+
+      def offline_error
+        report_error "GPX files offline for maintenance", :service_unavailable if Settings.status == "gpx_offline"
+      end
+    end
+  end
+end
index 76dfb3a2dc1bd4b6d57728b17b3f074894ef88cd..e91261058efe05db7500626deacec804f562d581 100644 (file)
@@ -6,7 +6,7 @@ module Api
 
     authorize_resource
 
-    before_action :offline_error, :only => [:create, :destroy, :data]
+    before_action :offline_error, :only => [:create, :destroy]
     skip_around_action :api_call_timeout, :only => :create
 
     def show
@@ -71,24 +71,6 @@ module Api
       end
     end
 
-    def data
-      trace = Trace.visible.find(params[:id])
-
-      if trace.public? || trace.user == current_user
-        if request.format == Mime[:xml]
-          send_data(trace.xml_file.read, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
-        elsif request.format == Mime[:gpx]
-          send_data(trace.xml_file.read, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
-        elsif trace.file.attached?
-          redirect_to rails_blob_path(trace.file, :disposition => "attachment")
-        else
-          send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
-        end
-      else
-        head :forbidden
-      end
-    end
-
     private
 
     def do_create(file, tags, description, visibility)
index bde7e028765c81b5426a5eed2e8c74957abee4b2..32b53bad71c3f431d79234d65e354f6cafcf13c9 100644 (file)
@@ -279,7 +279,15 @@ class ApplicationController < ActionController::Base
     end
   end
 
-  helper_method :preferred_editor
+  def preferred_color_scheme(subject)
+    if current_user
+      current_user.preferences.find_by(:k => "#{subject}.color_scheme")&.v || "auto"
+    else
+      "auto"
+    end
+  end
+
+  helper_method :preferred_editor, :preferred_color_scheme
 
   def update_totp
     if Settings.key?(:totp_key)
index dcf0d8b64e2682364b7c5b489ad1c9c72662bd19..1d96766ef227b7dbaa86b870f03ca1534c8513c6 100644 (file)
@@ -21,7 +21,20 @@ class PreferencesController < ApplicationController
                                     else
                                       params[:user][:preferred_editor]
                                     end
-    if current_user.save
+
+    success = current_user.save
+
+    if params[:site_color_scheme]
+      site_color_scheme_preference = current_user.preferences.find_or_create_by(:k => "site.color_scheme")
+      success &= site_color_scheme_preference.update(:v => params[:site_color_scheme])
+    end
+
+    if params[:map_color_scheme]
+      map_color_scheme_preference = current_user.preferences.find_or_create_by(:k => "map.color_scheme")
+      success &= map_color_scheme_preference.update(:v => params[:map_color_scheme])
+    end
+
+    if success
       # Use a partial so that it is rendered during the next page load in the correct language.
       flash[:notice] = { :partial => "preferences/update_success_flash" }
       redirect_to preferences_path
index 3c691612ab1d4c37ec1ad7a0f8c001b334e50272..bab19c217191fb089bc1681a5e93851c3df965dd 100644 (file)
@@ -5,7 +5,11 @@
   <%= javascript_include_tag "turbo", :type => "module" %>
   <%= javascript_include_tag "application" %>
   <%= javascript_include_tag "i18n/#{I18n.locale}" %>
-  <%= stylesheet_link_tag "screen-#{dir}", :media => "screen" %>
+  <% if preferred_color_scheme(:site) == "auto" %>
+    <%= stylesheet_link_tag "screen-auto-#{dir}", :media => "screen" %>
+  <% else %>
+    <%= stylesheet_link_tag "screen-manual-#{dir}", :media => "screen" %>
+  <% end %>
   <%= stylesheet_link_tag "print-#{dir}", :media => "print" %>
   <%= stylesheet_link_tag "leaflet-all", :media => "screen, print" %>
   <%= render :partial => "layouts/meta" %>
index 7c921658d46102d54b720eb5deb57a7107f07d9b..f02f024a57a69e84905c76122f1b16ff053e8f20 100644 (file)
@@ -1,11 +1,14 @@
 <!DOCTYPE html>
-<html lang="<%= I18n.locale %>" dir="<%= dir %>">
+<%= tag.html :lang => I18n.locale,
+             :dir => dir,
+             :data => { :bs_theme => (preferred_color_scheme(:site) if preferred_color_scheme(:site) != "auto") } do %>
   <%= render :partial => "layouts/head" %>
-  <body class="<%= body_class %>">
+  <%= tag.body :class => body_class,
+               :data => { :map_theme => (preferred_color_scheme(:map) if preferred_color_scheme(:map) != "auto") } do %>
     <%= render :partial => "layouts/header" %>
     <%= render :partial => "layouts/content" %>
     <% if defined?(Settings.matomo) -%>
     <noscript><p><img src="<%= request.protocol %><%= Settings.matomo["location"] %>/matomo.php?idsite=<%= Settings.matomo["site"] %>" class="matomo" alt="" /></p></noscript>
     <% end -%>
-  </body>
-</html>
+  <% end %>
+<% end %>
index 07d89fbb5bcb567fe443f8ec30c11175ceffeb3f..aaf07e927e27a11b9d0a599a9ce2d4887563307d 100644 (file)
@@ -7,6 +7,22 @@
 
   <%= f.text_field :languages %>
 
+  <div class="mb-3">
+    <%= label_tag "site_color_scheme", t("preferences.show.preferred_site_color_scheme"), :class => "form-label" %>
+    <%= select_tag "site_color_scheme",
+                   options_for_select(%w[auto light dark].map { |scheme| [t("preferences.show.site_color_schemes.#{scheme}"), scheme] },
+                                      preferred_color_scheme(:site)),
+                   :class => "form-select" %>
+  </div>
+
+  <div class="mb-3">
+    <%= label_tag "map_color_scheme", t("preferences.show.preferred_map_color_scheme"), :class => "form-label" %>
+    <%= select_tag "map_color_scheme",
+                   options_for_select(%w[auto light dark].map { |scheme| [t("preferences.show.map_color_schemes.#{scheme}"), scheme] },
+                                      preferred_color_scheme(:map)),
+                   :class => "form-select" %>
+  </div>
+
   <%= f.primary t(".save") %>
   <%= link_to t(".cancel"), preferences_path, :class => "btn btn-link" %>
 <% end %>
index 7a63d0be8dadeb57514fba42b8b139b7335cce62..9bf83cbf1f0f72b846e3c43bbac278703fcef61a 100644 (file)
         <li><%= locale %></li>
       <% end %>
     </ul>
+  </dd>
 
+  <dt class="col-sm-4"><%= t ".preferred_site_color_scheme" %></dt>
+  <dd class="col-sm-8">
+    <%= t ".site_color_schemes.#{preferred_color_scheme(:site)}" %>
+  </dd>
+
+  <dt class="col-sm-4"><%= t ".preferred_map_color_scheme" %></dt>
+  <dd class="col-sm-8">
+    <%= t ".map_color_schemes.#{preferred_color_scheme(:map)}" %>
   </dd>
 </dl>
 
index c3a0c5aed0802f2afe1c8acaf4eafee1f5c7e8e4..94fc77247b8cadc74f8f433dbbc18a05ddedf1a2 100644 (file)
@@ -1810,6 +1810,16 @@ en:
       title: My Preferences
       preferred_editor: Preferred Editor
       preferred_languages: Preferred Languages
+      preferred_site_color_scheme: Preferred Website Color Scheme
+      site_color_schemes:
+        auto: Auto
+        light: Light
+        dark: Dark
+      preferred_map_color_scheme: Preferred Map Color Scheme
+      map_color_schemes:
+        auto: Auto
+        light: Light
+        dark: Dark
       edit_preferences: Edit Preferences
     edit:
       title: Edit Preferences
index f65042dd7d9ab1c9bf83e22b5c2f1c71c5503ff9..871fef1bf27f667279d32c4a22be320abd2d3a4a 100644 (file)
@@ -86,16 +86,17 @@ OpenStreetMap::Application.routes.draw do
     end
 
     post "/user/messages/:id" => "messages#update", :as => :api_message_update
-
-    post "gpx/create" => "traces#create"
-    get "gpx/:id" => "traces#show", :as => :api_trace, :id => /\d+/
-    put "gpx/:id" => "traces#update", :id => /\d+/
-    delete "gpx/:id" => "traces#destroy", :id => /\d+/
-    get "gpx/:id/details" => "traces#show", :id => /\d+/
-    get "gpx/:id/data" => "traces#data", :as => :api_trace_data
   end
 
   namespace :api, :path => "api/0.6" do
+    resources :traces, :path => "gpx", :only => [:create, :show, :update, :destroy], :id => /\d+/ do
+      scope :module => :traces do
+        resource :data, :only => :show
+      end
+    end
+    post "gpx/create" => "traces#create", :id => /\d+/, :as => :trace_create
+    get "gpx/:id/details" => "traces#show", :id => /\d+/, :as => :trace_details
+
     # Map notes API
     resources :notes, :except => [:new, :edit, :update], :id => /\d+/, :controller => "notes" do
       collection do
diff --git a/test/controllers/api/traces/data_controller_test.rb b/test/controllers/api/traces/data_controller_test.rb
new file mode 100644 (file)
index 0000000..b4aa399
--- /dev/null
@@ -0,0 +1,114 @@
+require "test_helper"
+
+module Api
+  module Traces
+    class DataControllerTest < ActionDispatch::IntegrationTest
+      ##
+      # test all routes which lead to this controller
+      def test_routes
+        assert_routing(
+          { :path => "/api/0.6/gpx/1/data", :method => :get },
+          { :controller => "api/traces/data", :action => "show", :trace_id => "1" }
+        )
+        assert_routing(
+          { :path => "/api/0.6/gpx/1/data.xml", :method => :get },
+          { :controller => "api/traces/data", :action => "show", :trace_id => "1", :format => "xml" }
+        )
+      end
+
+      # Test downloading a trace through the api
+      def test_show
+        public_trace_file = create(:trace, :visibility => "public", :fixture => "a")
+
+        # First with no auth
+        get api_trace_data_path(public_trace_file)
+        assert_response :unauthorized
+
+        # Now with some other user, which should work since the trace is public
+        auth_header = bearer_authorization_header
+        get api_trace_data_path(public_trace_file), :headers => auth_header
+        follow_redirect!
+        follow_redirect!
+        check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
+
+        # And finally we should be able to do it with the owner of the trace
+        auth_header = bearer_authorization_header public_trace_file.user
+        get api_trace_data_path(public_trace_file), :headers => auth_header
+        follow_redirect!
+        follow_redirect!
+        check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
+      end
+
+      # Test downloading a compressed trace through the api
+      def test_data_compressed
+        identifiable_trace_file = create(:trace, :visibility => "identifiable", :fixture => "d")
+
+        # Authenticate as the owner of the trace we will be using
+        auth_header = bearer_authorization_header identifiable_trace_file.user
+
+        # First get the data as is
+        get api_trace_data_path(identifiable_trace_file), :headers => auth_header
+        follow_redirect!
+        follow_redirect!
+        check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/gzip", "gpx.gz"
+
+        # Now ask explicitly for XML format
+        get api_trace_data_path(identifiable_trace_file, :format => "xml"), :headers => auth_header
+        check_trace_data identifiable_trace_file, "abd6675fdf3024a84fc0a1deac147c0d", "application/xml", "xml"
+
+        # Now ask explicitly for GPX format
+        get api_trace_data_path(identifiable_trace_file, :format => "gpx"), :headers => auth_header
+        check_trace_data identifiable_trace_file, "abd6675fdf3024a84fc0a1deac147c0d"
+      end
+
+      # Check an anonymous trace can't be downloaded by another user through the api
+      def test_data_anon
+        anon_trace_file = create(:trace, :visibility => "private", :fixture => "b")
+
+        # First with no auth
+        get api_trace_data_path(anon_trace_file)
+        assert_response :unauthorized
+
+        # Now with some other user, which shouldn't work since the trace is anon
+        auth_header = bearer_authorization_header
+        get api_trace_data_path(anon_trace_file), :headers => auth_header
+        assert_response :forbidden
+
+        # And finally we should be able to do it with the owner of the trace
+        auth_header = bearer_authorization_header anon_trace_file.user
+        get api_trace_data_path(anon_trace_file), :headers => auth_header
+        follow_redirect!
+        follow_redirect!
+        check_trace_data anon_trace_file, "db4cb5ed2d7d2b627b3b504296c4f701"
+      end
+
+      # Test downloading a trace that doesn't exist through the api
+      def test_data_not_found
+        deleted_trace_file = create(:trace, :deleted)
+
+        # Try first with no auth, as it should require it
+        get api_trace_data_path(0)
+        assert_response :unauthorized
+
+        # Login, and try again
+        auth_header = bearer_authorization_header
+        get api_trace_data_path(0), :headers => auth_header
+        assert_response :not_found
+
+        # Now try a trace which did exist but has been deleted
+        auth_header = bearer_authorization_header deleted_trace_file.user
+        get api_trace_data_path(deleted_trace_file), :headers => auth_header
+        assert_response :not_found
+      end
+
+      private
+
+      def check_trace_data(trace, digest, content_type = "application/gpx+xml", extension = "gpx")
+        assert_response :success
+        assert_equal digest, Digest::MD5.hexdigest(response.body)
+        assert_equal content_type, response.media_type
+        assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"; filename*=UTF-8''#{trace.id}.#{extension}", @response.header["Content-Disposition"]
+      end
+    end
+  end
+end
index 6ce35bc7cb6089cb24c8dbe6860e582c999a009f..367bb6d21e1fe0b057d5f7de06abfe7f46e8f9c7 100644 (file)
@@ -6,9 +6,13 @@ module Api
     # test all routes which lead to this controller
     def test_routes
       assert_routing(
-        { :path => "/api/0.6/gpx/create", :method => :post },
+        { :path => "/api/0.6/gpx", :method => :post },
         { :controller => "api/traces", :action => "create" }
       )
+      assert_recognizes(
+        { :controller => "api/traces", :action => "create" },
+        { :path => "/api/0.6/gpx/create", :method => :post }
+      )
       assert_routing(
         { :path => "/api/0.6/gpx/1", :method => :get },
         { :controller => "api/traces", :action => "show", :id => "1" }
@@ -25,14 +29,6 @@ module Api
         { :controller => "api/traces", :action => "show", :id => "1" },
         { :path => "/api/0.6/gpx/1/details", :method => :get }
       )
-      assert_routing(
-        { :path => "/api/0.6/gpx/1/data", :method => :get },
-        { :controller => "api/traces", :action => "data", :id => "1" }
-      )
-      assert_routing(
-        { :path => "/api/0.6/gpx/1/data.xml", :method => :get },
-        { :controller => "api/traces", :action => "data", :id => "1", :format => "xml" }
-      )
     end
 
     # Check getting a specific trace through the api
@@ -93,91 +89,6 @@ module Api
       assert_response :not_found
     end
 
-    # Test downloading a trace through the api
-    def test_data
-      public_trace_file = create(:trace, :visibility => "public", :fixture => "a")
-
-      # First with no auth
-      get api_trace_data_path(public_trace_file)
-      assert_response :unauthorized
-
-      # Now with some other user, which should work since the trace is public
-      auth_header = bearer_authorization_header
-      get api_trace_data_path(public_trace_file), :headers => auth_header
-      follow_redirect!
-      follow_redirect!
-      check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
-
-      # And finally we should be able to do it with the owner of the trace
-      auth_header = bearer_authorization_header public_trace_file.user
-      get api_trace_data_path(public_trace_file), :headers => auth_header
-      follow_redirect!
-      follow_redirect!
-      check_trace_data public_trace_file, "848caa72f2f456d1bd6a0fdf228aa1b9"
-    end
-
-    # Test downloading a compressed trace through the api
-    def test_data_compressed
-      identifiable_trace_file = create(:trace, :visibility => "identifiable", :fixture => "d")
-
-      # Authenticate as the owner of the trace we will be using
-      auth_header = bearer_authorization_header identifiable_trace_file.user
-
-      # First get the data as is
-      get api_trace_data_path(identifiable_trace_file), :headers => auth_header
-      follow_redirect!
-      follow_redirect!
-      check_trace_data identifiable_trace_file, "c6422a3d8750faae49ed70e7e8a51b93", "application/gzip", "gpx.gz"
-
-      # Now ask explicitly for XML format
-      get api_trace_data_path(identifiable_trace_file, :format => "xml"), :headers => auth_header
-      check_trace_data identifiable_trace_file, "abd6675fdf3024a84fc0a1deac147c0d", "application/xml", "xml"
-
-      # Now ask explicitly for GPX format
-      get api_trace_data_path(identifiable_trace_file, :format => "gpx"), :headers => auth_header
-      check_trace_data identifiable_trace_file, "abd6675fdf3024a84fc0a1deac147c0d"
-    end
-
-    # Check an anonymous trace can't be downloaded by another user through the api
-    def test_data_anon
-      anon_trace_file = create(:trace, :visibility => "private", :fixture => "b")
-
-      # First with no auth
-      get api_trace_data_path(anon_trace_file)
-      assert_response :unauthorized
-
-      # Now with some other user, which shouldn't work since the trace is anon
-      auth_header = bearer_authorization_header
-      get api_trace_data_path(anon_trace_file), :headers => auth_header
-      assert_response :forbidden
-
-      # And finally we should be able to do it with the owner of the trace
-      auth_header = bearer_authorization_header anon_trace_file.user
-      get api_trace_data_path(anon_trace_file), :headers => auth_header
-      follow_redirect!
-      follow_redirect!
-      check_trace_data anon_trace_file, "db4cb5ed2d7d2b627b3b504296c4f701"
-    end
-
-    # Test downloading a trace that doesn't exist through the api
-    def test_data_not_found
-      deleted_trace_file = create(:trace, :deleted)
-
-      # Try first with no auth, as it should require it
-      get api_trace_data_path(:id => 0)
-      assert_response :unauthorized
-
-      # Login, and try again
-      auth_header = bearer_authorization_header
-      get api_trace_data_path(:id => 0), :headers => auth_header
-      assert_response :not_found
-
-      # Now try a trace which did exist but has been deleted
-      auth_header = bearer_authorization_header deleted_trace_file.user
-      get api_trace_data_path(deleted_trace_file), :headers => auth_header
-      assert_response :not_found
-    end
-
     # Test creating a trace through the api
     def test_create
       # Get file to use
@@ -186,7 +97,7 @@ module Api
       user = create(:user)
 
       # First with no auth
-      post gpx_create_path, :params => { :file => file, :description => "New Trace", :tags => "new,trace", :visibility => "trackable" }
+      post api_traces_path, :params => { :file => file, :description => "New Trace", :tags => "new,trace", :visibility => "trackable" }
       assert_response :unauthorized
 
       # Rewind the file
@@ -200,7 +111,7 @@ module Api
 
       # Create trace and import tracepoints in background job
       perform_enqueued_jobs do
-        post gpx_create_path, :params => { :file => file, :description => "New Trace", :tags => "new,trace", :visibility => "trackable" }, :headers => auth_header
+        post api_traces_path, :params => { :file => file, :description => "New Trace", :tags => "new,trace", :visibility => "trackable" }, :headers => auth_header
       end
 
       assert_response :success
@@ -232,7 +143,7 @@ module Api
       # Now authenticated, with the legacy public flag
       assert_not_equal "public", user.preferences.find_by(:k => "gps.trace.visibility").v
       auth_header = bearer_authorization_header user
-      post gpx_create_path, :params => { :file => file, :description => "New Trace", :tags => "new,trace", :public => 1 }, :headers => auth_header
+      post api_traces_path, :params => { :file => file, :description => "New Trace", :tags => "new,trace", :public => 1 }, :headers => auth_header
       assert_response :success
       trace = Trace.find(response.body.to_i)
       assert_equal "a.gpx", trace.name
@@ -251,7 +162,7 @@ module Api
       second_user = create(:user)
       assert_nil second_user.preferences.find_by(:k => "gps.trace.visibility")
       auth_header = bearer_authorization_header second_user
-      post gpx_create_path, :params => { :file => file, :description => "New Trace", :tags => "new,trace", :public => 0 }, :headers => auth_header
+      post api_traces_path, :params => { :file => file, :description => "New Trace", :tags => "new,trace", :public => 0 }, :headers => auth_header
       assert_response :success
       trace = Trace.find(response.body.to_i)
       assert_equal "a.gpx", trace.name
@@ -354,13 +265,6 @@ module Api
 
     private
 
-    def check_trace_data(trace, digest, content_type = "application/gpx+xml", extension = "gpx")
-      assert_response :success
-      assert_equal digest, Digest::MD5.hexdigest(response.body)
-      assert_equal content_type, response.media_type
-      assert_equal "attachment; filename=\"#{trace.id}.#{extension}\"; filename*=UTF-8''#{trace.id}.#{extension}", @response.header["Content-Disposition"]
-    end
-
     ##
     # build XML for traces
     # this builds a minimum viable XML for the tests in this suite
index 81760fe5de54816a88b448dcdd6a47e3ea008a8e..1cd07b7d9f68a4adfaa6fc655215a80a21edceab 100644 (file)
@@ -22,6 +22,8 @@ class PreferencesControllerTest < ActionDispatch::IntegrationTest
 
   def test_update_preferred_editor
     user = create(:user, :languages => [])
+    user.preferences.create(:k => "site.color_scheme", :v => "light")
+    user.preferences.create(:k => "map.color_scheme", :v => "light")
     session_for(user)
 
     # Changing to a invalid editor should fail
@@ -32,6 +34,8 @@ class PreferencesControllerTest < ActionDispatch::IntegrationTest
     assert_select ".alert-success", false
     assert_select ".alert-danger", true
     assert_select "form > div > select#user_preferred_editor > option[selected]", false
+    assert_equal "light", user.preferences.find_by(:k => "site.color_scheme")&.v
+    assert_equal "light", user.preferences.find_by(:k => "map.color_scheme")&.v
 
     # Changing to a valid editor should work
     user.preferred_editor = "id"
@@ -41,6 +45,8 @@ class PreferencesControllerTest < ActionDispatch::IntegrationTest
     assert_template :show
     assert_select ".alert-success", /^Preferences updated/
     assert_select "dd", "iD (in-browser editor)"
+    assert_equal "light", user.preferences.find_by(:k => "site.color_scheme")&.v
+    assert_equal "light", user.preferences.find_by(:k => "map.color_scheme")&.v
 
     # Changing to the default editor should work
     user.preferred_editor = "default"
@@ -50,5 +56,51 @@ class PreferencesControllerTest < ActionDispatch::IntegrationTest
     assert_template :show
     assert_select ".alert-success", /^Preferences updated/
     assert_select "dd", "Default (currently iD)"
+    assert_equal "light", user.preferences.find_by(:k => "site.color_scheme")&.v
+    assert_equal "light", user.preferences.find_by(:k => "map.color_scheme")&.v
+  end
+
+  def test_update_preferred_site_color_scheme
+    user = create(:user, :languages => [])
+    session_for(user)
+    assert_nil user.preferences.find_by(:k => "site.color_scheme")
+
+    # Changing when previously not defined
+    put preferences_path, :params => { :user => user.attributes, :site_color_scheme => "light" }
+    assert_redirected_to preferences_path
+    follow_redirect!
+    assert_template :show
+    assert_select ".alert-success", /^Preferences updated/
+    assert_equal "light", user.preferences.find_by(:k => "site.color_scheme")&.v
+
+    # Changing when previously defined
+    put preferences_path, :params => { :user => user.attributes, :site_color_scheme => "auto" }
+    assert_redirected_to preferences_path
+    follow_redirect!
+    assert_template :show
+    assert_select ".alert-success", /^Preferences updated/
+    assert_equal "auto", user.preferences.find_by(:k => "site.color_scheme")&.v
+  end
+
+  def test_update_preferred_map_color_scheme
+    user = create(:user, :languages => [])
+    session_for(user)
+    assert_nil user.preferences.find_by(:k => "map.color_scheme")
+
+    # Changing when previously not defined
+    put preferences_path, :params => { :user => user.attributes, :map_color_scheme => "light" }
+    assert_redirected_to preferences_path
+    follow_redirect!
+    assert_template :show
+    assert_select ".alert-success", /^Preferences updated/
+    assert_equal "light", user.preferences.find_by(:k => "map.color_scheme")&.v
+
+    # Changing when previously defined
+    put preferences_path, :params => { :user => user.attributes, :map_color_scheme => "auto" }
+    assert_redirected_to preferences_path
+    follow_redirect!
+    assert_template :show
+    assert_select ".alert-success", /^Preferences updated/
+    assert_equal "auto", user.preferences.find_by(:k => "map.color_scheme")&.v
   end
 end