]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/5053'
authorTom Hughes <tom@compton.nu>
Wed, 7 Aug 2024 17:37:17 +0000 (18:37 +0100)
committerTom Hughes <tom@compton.nu>
Wed, 7 Aug 2024 17:37:17 +0000 (18:37 +0100)
15 files changed:
Gemfile.lock
app/controllers/diary_entries_controller.rb
app/helpers/open_graph_helper.rb
app/views/api/changesets/index.json.jbuilder
app/views/api/messages/inbox.json.jbuilder
app/views/api/messages/outbox.json.jbuilder
app/views/api/notes/index.json.jbuilder
app/views/api/users/index.json.jbuilder
app/views/layouts/_meta.html.erb
lib/rich_text.rb
script/cleanup
test/controllers/api/changesets_controller_test.rb
test/controllers/api/nodes_controller_test.rb
test/controllers/diary_entries_controller_test.rb
test/lib/rich_text_test.rb

index e8d918ff5e2e01d48c3fa007dcc7a0d39db20a13..00984911cba78e05b9f568389776d9b6d2e2f30c 100644 (file)
@@ -92,10 +92,10 @@ GEM
       ffi (~> 1.15)
       ffi-compiler (~> 1.0)
     ast (2.4.2)
-    autoprefixer-rails (10.4.16.0)
+    autoprefixer-rails (10.4.19.0)
       execjs (~> 2)
     aws-eventstream (1.3.0)
-    aws-partitions (1.959.0)
+    aws-partitions (1.962.0)
     aws-sdk-core (3.201.3)
       aws-eventstream (~> 1, >= 1.3.0)
       aws-partitions (~> 1, >= 1.651.0)
@@ -104,7 +104,7 @@ GEM
     aws-sdk-kms (1.88.0)
       aws-sdk-core (~> 3, >= 3.201.0)
       aws-sigv4 (~> 1.5)
-    aws-sdk-s3 (1.156.0)
+    aws-sdk-s3 (1.157.0)
       aws-sdk-core (~> 3, >= 3.201.0)
       aws-sdk-kms (~> 1)
       aws-sigv4 (~> 1.5)
@@ -125,7 +125,7 @@ GEM
     bigdecimal (3.1.8)
     binding_of_caller (1.0.1)
       debug_inspector (>= 1.2.0)
-    bootsnap (1.18.3)
+    bootsnap (1.18.4)
       msgpack (~> 1.2)
     bootstrap (5.3.3)
       autoprefixer-rails (>= 9.1.0)
@@ -219,12 +219,12 @@ GEM
       dry-initializer (~> 3.0)
       dry-schema (>= 1.12, < 2)
       zeitwerk (~> 2.6)
-    erb_lint (0.5.0)
+    erb_lint (0.6.0)
       activesupport
       better_html (>= 2.0.1)
       parser (>= 2.7.1.4)
       rainbow
-      rubocop
+      rubocop (>= 1)
       smart_properties
     erubi (1.13.0)
     execjs (2.9.1)
@@ -234,7 +234,7 @@ GEM
     factory_bot_rails (6.4.3)
       factory_bot (~> 6.4)
       railties (>= 5.0.0)
-    faraday (2.10.0)
+    faraday (2.10.1)
       faraday-net_http (>= 2.0, < 3.2)
       logger
     faraday-net_http (3.1.1)
@@ -254,7 +254,7 @@ GEM
     globalid (1.2.1)
       activesupport (>= 6.1)
     google-protobuf (3.25.4)
-    hashdiff (1.1.0)
+    hashdiff (1.1.1)
     hashie (5.0.0)
     highline (3.1.0)
       reline
@@ -485,14 +485,14 @@ GEM
       io-console (~> 0.5)
     request_store (1.7.0)
       rack (>= 1.4)
-    rexml (3.3.3)
+    rexml (3.3.4)
       strscan
     rinku (2.0.6)
     rotp (6.3.0)
     rouge (4.3.0)
     rtlcss (0.2.1)
       mini_racer (>= 0.6.3)
-    rubocop (1.65.0)
+    rubocop (1.65.1)
       json (~> 2.3)
       language_server-protocol (>= 3.17.0)
       parallel (~> 1.10)
@@ -503,7 +503,7 @@ GEM
       rubocop-ast (>= 1.31.1, < 2.0)
       ruby-progressbar (~> 1.7)
       unicode-display_width (>= 2.4.0, < 3.0)
-    rubocop-ast (1.31.3)
+    rubocop-ast (1.32.0)
       parser (>= 3.3.1.0)
     rubocop-capybara (2.21.0)
       rubocop (~> 1.41)
@@ -558,7 +558,7 @@ GEM
     sprockets-exporters_pack (0.1.2)
       brotli (>= 0.2.0)
       sprockets (>= 4.0.0.beta3)
-    sprockets-rails (3.5.1)
+    sprockets-rails (3.5.2)
       actionpack (>= 6.1)
       activesupport (>= 6.1)
       sprockets (>= 3.0.0)
index eaf6ddf9c519021e5d9a0809585fb94edf0f85ce..9962c7efd5f019f0f333bc6174931a7f8791276e 100644 (file)
@@ -69,6 +69,7 @@ class DiaryEntriesController < ApplicationController
     if @entry
       @title = t ".title", :user => params[:display_name], :title => @entry.title
       @og_image = @entry.body.image
+      @og_image_alt = @entry.body.image_alt
       @comments = can?(:unhide, DiaryComment) ? @entry.comments : @entry.visible_comments
     else
       @title = t "diary_entries.no_such_entry.title", :id => params[:id]
index a41831ca69d98bc6e287c495ec94653817245b2b..ad24c73b2fb3c2115d3b0a19b4c3809f18cd0638 100644 (file)
@@ -1,15 +1,16 @@
 module OpenGraphHelper
   require "addressable/uri"
 
-  def opengraph_tags(title = nil, og_image = nil)
+  def opengraph_tags(title = nil, og_image = nil, og_image_alt = nil)
     tags = {
       "og:site_name" => t("layouts.project_name.title"),
       "og:title" => title || t("layouts.project_name.title"),
       "og:type" => "website",
-      "og:image" => og_image_url(og_image),
       "og:url" => url_for(:only_path => false),
       "og:description" => t("layouts.intro_text")
-    }
+    }.merge(
+      opengraph_image_properties(og_image, og_image_alt)
+    )
 
     safe_join(tags.map do |property, content|
       tag.meta(:property => property, :content => content)
@@ -18,12 +19,20 @@ module OpenGraphHelper
 
   private
 
-  def og_image_url(og_image)
+  def opengraph_image_properties(og_image, og_image_alt)
     begin
-      return Addressable::URI.join(root_url, og_image).normalize if og_image
+      if og_image
+        properties = {}
+        properties["og:image"] = Addressable::URI.join(root_url, og_image).normalize
+        properties["og:image:alt"] = og_image_alt if og_image_alt
+        return properties
+      end
     rescue Addressable::URI::InvalidURIError
       # return default image
     end
-    image_url("osm_logo_256.png")
+    {
+      "og:image" => image_url("osm_logo_256.png"),
+      "og:image:alt" => t("layouts.logo.alt_text")
+    }
   end
 end
index f52d69865d9d2f63f3205641f9d5c028e52b1e5c..ce094fa3457ef5fb21093f6eba365c4fda5fb5cb 100644 (file)
@@ -1,5 +1,5 @@
 json.partial! "api/root_attributes"
 
-json.changesets(@changesets) do |changeset|
-  json.partial! changeset
+json.changesets do
+  json.array! @changesets, :partial => "changeset", :as => :changeset
 end
index 524006ded54588099e51aba88cea05b81dc66f9f..122a82495b93abdf08eb9b10dce48fd8d60199f8 100644 (file)
@@ -1,5 +1,5 @@
 json.partial! "api/root_attributes"
 
-json.messages(@messages) do |message|
-  json.partial! message
+json.messages do
+  json.array! @messages, :partial => "message", :as => :message
 end
index 524006ded54588099e51aba88cea05b81dc66f9f..122a82495b93abdf08eb9b10dce48fd8d60199f8 100644 (file)
@@ -1,5 +1,5 @@
 json.partial! "api/root_attributes"
 
-json.messages(@messages) do |message|
-  json.partial! message
+json.messages do
+  json.array! @messages, :partial => "message", :as => :message
 end
index 7909391f5ae939f231121b01c958134ad0afce72..5660a8ad5038b0006b0b0f2fd6abd7709d06cbfc 100644 (file)
@@ -1,5 +1,5 @@
 json.type "FeatureCollection"
 
-json.features(@notes) do |note|
-  json.partial! note
+json.features do
+  json.array! @notes, :partial => "note", :as => :note
 end
index 1ad07d47cd2639cc63d49ae093b9785478a5868b..d2dbd4d4f5c6113fd03a381e779215dabe3e58c4 100644 (file)
@@ -1,5 +1,5 @@
 json.partial! "api/root_attributes"
 
-json.users(@users) do |user|
-  json.partial! user
+json.users do
+  json.array! @users, :partial => "user", :as => :user
 end
index 37afbb89498e5cc67a2e101a17c4e83d312bc62f..f09449761a4990c9226fb17c4b9cf64e4fc0d533 100644 (file)
@@ -21,7 +21,7 @@
 <% end -%>
 <%= tag.link :rel => "search", :type => "application/opensearchdescription+xml", :title => "OpenStreetMap Search", :href => asset_path("osm.xml") %>
 <%= tag.meta :name => "description", :content => "OpenStreetMap is the free wiki world map." %>
-<%= opengraph_tags(@title, @og_image) %>
+<%= opengraph_tags(@title, @og_image, @og_image_alt) %>
 <% if flash[:matomo_goal] -%>
 <%= tag.meta :name => "matomo-goal", :content => flash[:matomo_goal] %>
 <% end -%>
index edfa535f434c07d23fb88412ad9dd673c38645d5..a439342f7743f9b1fb8682147f6562a9ff0750ab 100644 (file)
@@ -53,6 +53,10 @@ module RichText
       nil
     end
 
+    def image_alt
+      nil
+    end
+
     protected
 
     def simple_format(text)
@@ -92,9 +96,13 @@ module RichText
     end
 
     def image
-      return @image if defined? @image
+      @image_element = first_image_element(document.root) unless defined? @image_element
+      @image_element.attr["src"] if @image_element
+    end
 
-      @image = first_image_element(document.root)&.attr&.[]("src")
+    def image_alt
+      @image_element = first_image_element(document.root) unless defined? @image_element
+      @image_element.attr["alt"] if @image_element
     end
 
     private
index 7601d35cf9386a276a1fabd7199a3e00a6cb9c23..e829be176b9ece957a1a36a87db9942717c27ebf 100755 (executable)
@@ -6,4 +6,7 @@ OauthNonce.where("timestamp < EXTRACT(EPOCH FROM NOW() - INTERVAL '1 day')").del
 OauthToken.where("invalidated_at < NOW() - INTERVAL '28 days'").delete_all
 RequestToken.where("authorized_at IS NULL AND created_at < NOW() - INTERVAL '28 days'").delete_all
 
+Doorkeeper::AccessGrant.where("revoked_at < NOW() - INTERVAL '28 days' OR (created_at + expires_in * INTERVAL '1 second') < NOW() - INTERVAL '28 days'").delete_all
+Doorkeeper::AccessToken.where("revoked_at < NOW() - INTERVAL '28 days' OR (created_at + expires_in * INTERVAL '1 second') < NOW() - INTERVAL '28 days'").delete_all
+
 exit 0
index cfb4241691116597cdcd8c77a293396d14d9e559..1d7afa03586130e5041b17a4722857a97f5561cf 100644 (file)
@@ -636,26 +636,27 @@ module Api
                       "can't upload a simple valid creation to changeset: #{@response.body}"
 
       # check the returned payload
-      assert_select "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1
-      assert_select "diffResult>node", 1
-      assert_select "diffResult>way", 1
-      assert_select "diffResult>relation", 1
-
-      # inspect the response to find out what the new element IDs are
-      doc = XML::Parser.string(@response.body).parse
-      new_node_id = doc.find("//diffResult/node").first["new_id"].to_i
-      new_way_id = doc.find("//diffResult/way").first["new_id"].to_i
-      new_rel_id = doc.find("//diffResult/relation").first["new_id"].to_i
-
-      # check the old IDs are all present and negative one
-      assert_equal(-1, doc.find("//diffResult/node").first["old_id"].to_i)
-      assert_equal(-1, doc.find("//diffResult/way").first["old_id"].to_i)
-      assert_equal(-1, doc.find("//diffResult/relation").first["old_id"].to_i)
-
-      # check the versions are present and equal one
-      assert_equal 1, doc.find("//diffResult/node").first["new_version"].to_i
-      assert_equal 1, doc.find("//diffResult/way").first["new_version"].to_i
-      assert_equal 1, doc.find("//diffResult/relation").first["new_version"].to_i
+      new_node_id, new_way_id, new_rel_id = nil
+      assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
+        # inspect the response to find out what the new element IDs are
+        # check the old IDs are all present and negative one
+        # check the versions are present and equal one
+        assert_dom "> node", 1 do |(node_el)|
+          new_node_id = node_el["new_id"].to_i
+          assert_dom "> @old_id", "-1"
+          assert_dom "> @new_version", "1"
+        end
+        assert_dom "> way", 1 do |(way_el)|
+          new_way_id = way_el["new_id"].to_i
+          assert_dom "> @old_id", "-1"
+          assert_dom "> @new_version", "1"
+        end
+        assert_dom "> relation", 1 do |(rel_el)|
+          new_rel_id = rel_el["new_id"].to_i
+          assert_dom "> @old_id", "-1"
+          assert_dom "> @new_version", "1"
+        end
+      end
 
       # check that the changes made it into the database
       assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
@@ -878,28 +879,26 @@ module Api
                       "can't do a conditional delete of in use objects: #{@response.body}"
 
       # check the returned payload
-      assert_select "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1
-      assert_select "diffResult>node", 1
-      assert_select "diffResult>way", 1
-      assert_select "diffResult>relation", 1
-
-      # parse the response
-      doc = XML::Parser.string(@response.body).parse
-
-      # check the old IDs are all present and what we expect
-      assert_equal used_node.id, doc.find("//diffResult/node").first["old_id"].to_i
-      assert_equal used_way.id, doc.find("//diffResult/way").first["old_id"].to_i
-      assert_equal used_relation.id, doc.find("//diffResult/relation").first["old_id"].to_i
-
-      # check the new IDs are all present and unchanged
-      assert_equal used_node.id, doc.find("//diffResult/node").first["new_id"].to_i
-      assert_equal used_way.id, doc.find("//diffResult/way").first["new_id"].to_i
-      assert_equal used_relation.id, doc.find("//diffResult/relation").first["new_id"].to_i
-
-      # check the new versions are all present and unchanged
-      assert_equal used_node.version, doc.find("//diffResult/node").first["new_version"].to_i
-      assert_equal used_way.version, doc.find("//diffResult/way").first["new_version"].to_i
-      assert_equal used_relation.version, doc.find("//diffResult/relation").first["new_version"].to_i
+      assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
+        # check the old IDs are all present and what we expect
+        # check the new IDs are all present and unchanged
+        # check the new versions are all present and unchanged
+        assert_dom "> node", 1 do
+          assert_dom "> @old_id", used_node.id.to_s
+          assert_dom "> @new_id", used_node.id.to_s
+          assert_dom "> @new_version", used_node.version.to_s
+        end
+        assert_dom "> way", 1 do
+          assert_dom "> @old_id", used_way.id.to_s
+          assert_dom "> @new_id", used_way.id.to_s
+          assert_dom "> @new_version", used_way.version.to_s
+        end
+        assert_dom "> relation", 1 do
+          assert_dom "> @old_id", used_relation.id.to_s
+          assert_dom "> @new_id", used_relation.id.to_s
+          assert_dom "> @new_version", used_relation.version.to_s
+        end
+      end
 
       # check that nothing was, in fact, deleted
       assert Node.find(used_node.id).visible
@@ -973,14 +972,14 @@ module Api
                       "can't upload a complex diff to changeset: #{@response.body}"
 
       # check the returned payload
-      assert_select "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1
-      assert_select "diffResult>node", 1
-      assert_select "diffResult>way", 1
-      assert_select "diffResult>relation", 1
-
-      # inspect the response to find out what the new element IDs are
-      doc = XML::Parser.string(@response.body).parse
-      new_node_id = doc.find("//diffResult/node").first["new_id"].to_i
+      new_node_id = nil
+      assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
+        assert_dom "> node", 1 do |(node_el)|
+          new_node_id = node_el["new_id"].to_i
+        end
+        assert_dom "> way", 1
+        assert_dom "> relation", 1
+      end
 
       # check that the changes made it into the database
       assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
@@ -2173,11 +2172,11 @@ module Api
 
       get changesets_path(:bbox => "-10,-10, 10, 10")
       assert_response :success, "can't get changesets in bbox"
-      assert_changesets [changeset2, changeset3]
+      assert_changesets_in_order [changeset3, changeset2]
 
       get changesets_path(:bbox => "4.5,4.5,4.6,4.6")
       assert_response :success, "can't get changesets in bbox"
-      assert_changesets [changeset3]
+      assert_changesets_in_order [changeset3]
 
       # not found when looking for changesets of non-existing users
       get changesets_path(:user => User.maximum(:id) + 1)
@@ -2197,11 +2196,11 @@ module Api
       auth_header = basic_authorization_header private_user.email, "test"
       get changesets_path(:user => private_user.id), :headers => auth_header
       assert_response :success, "can't get changesets by user ID"
-      assert_changesets [private_user_changeset, private_user_closed_changeset]
+      assert_changesets_in_order [private_user_changeset, private_user_closed_changeset]
 
       get changesets_path(:display_name => private_user.display_name), :headers => auth_header
       assert_response :success, "can't get changesets by user name"
-      assert_changesets [private_user_changeset, private_user_closed_changeset]
+      assert_changesets_in_order [private_user_changeset, private_user_closed_changeset]
 
       # test json endpoint
       get changesets_path(:display_name => private_user.display_name), :headers => auth_header, :params => { :format => "json" }
@@ -2221,39 +2220,39 @@ module Api
 
       get changesets_path(:user => private_user.id, :open => true), :headers => auth_header
       assert_response :success, "can't get changesets by user and open"
-      assert_changesets [private_user_changeset]
+      assert_changesets_in_order [private_user_changeset]
 
       get changesets_path(:time => "2007-12-31"), :headers => auth_header
       assert_response :success, "can't get changesets by time-since"
-      assert_changesets [private_user_changeset, private_user_closed_changeset, changeset, closed_changeset, changeset2, changeset3]
+      assert_changesets_in_order [changeset3, changeset2, changeset, private_user_changeset, private_user_closed_changeset, closed_changeset]
 
       get changesets_path(:time => "2008-01-01T12:34Z"), :headers => auth_header
       assert_response :success, "can't get changesets by time-since with hour"
-      assert_changesets [private_user_changeset, private_user_closed_changeset, changeset, closed_changeset, changeset2, changeset3]
+      assert_changesets_in_order [changeset3, changeset2, changeset, private_user_changeset, private_user_closed_changeset, closed_changeset]
 
       get changesets_path(:time => "2007-12-31T23:59Z,2008-01-02T00:01Z"), :headers => auth_header
       assert_response :success, "can't get changesets by time-range"
-      assert_changesets [closed_changeset]
+      assert_changesets_in_order [closed_changeset]
 
       get changesets_path(:open => "true"), :headers => auth_header
       assert_response :success, "can't get changesets by open-ness"
-      assert_changesets [private_user_changeset, changeset, changeset2, changeset3]
+      assert_changesets_in_order [changeset3, changeset2, changeset, private_user_changeset]
 
       get changesets_path(:closed => "true"), :headers => auth_header
       assert_response :success, "can't get changesets by closed-ness"
-      assert_changesets [private_user_closed_changeset, closed_changeset]
+      assert_changesets_in_order [private_user_closed_changeset, closed_changeset]
 
       get changesets_path(:closed => "true", :user => private_user.id), :headers => auth_header
       assert_response :success, "can't get changesets by closed-ness and user"
-      assert_changesets [private_user_closed_changeset]
+      assert_changesets_in_order [private_user_closed_changeset]
 
       get changesets_path(:closed => "true", :user => user.id), :headers => auth_header
       assert_response :success, "can't get changesets by closed-ness and user"
-      assert_changesets [closed_changeset]
+      assert_changesets_in_order [closed_changeset]
 
       get changesets_path(:changesets => "#{private_user_changeset.id},#{changeset.id},#{closed_changeset.id}"), :headers => auth_header
       assert_response :success, "can't get changesets by id (as comma-separated string)"
-      assert_changesets [private_user_changeset, changeset, closed_changeset]
+      assert_changesets_in_order [changeset, private_user_changeset, closed_changeset]
 
       get changesets_path(:changesets => ""), :headers => auth_header
       assert_response :bad_request, "should be a bad request since changesets is empty"
@@ -2683,15 +2682,6 @@ module Api
       end
     end
 
-    ##
-    # check that certain changesets exist in the output
-    def assert_changesets(changesets)
-      assert_select "osm>changeset", changesets.size
-      changesets.each do |changeset|
-        assert_select "osm>changeset[id='#{changeset.id}']", 1
-      end
-    end
-
     ##
     # check that certain changesets exist in the output in the specified order
     def assert_changesets_in_order(changesets)
index 5fde0277cf8d34bc12aac31fc60a6c77d0489c10..d70c92861e9b563f7df5eab1fb933dfce1ead943 100644 (file)
@@ -297,6 +297,8 @@ module Api
     # tests whether the API works and prevents incorrect use while trying
     # to update nodes.
     def test_update
+      invalid_attr_values = [["lat", 91.0], ["lat", -91.0], ["lon", 181.0], ["lon", -181.0]]
+
       ## First test with no user credentials
       # try and update a node without authorisation
       # first try to delete node without auth
@@ -334,21 +336,11 @@ module Api
       assert_require_public_data "update with changeset=0 should be forbidden, when data isn't public"
 
       ## try and submit invalid updates
-      xml = xml_attr_rewrite(xml_for_node(private_node), "lat", 91.0)
-      put api_node_path(private_node), :params => xml.to_s, :headers => auth_header
-      assert_require_public_data "node at lat=91 should be forbidden, when data isn't public"
-
-      xml = xml_attr_rewrite(xml_for_node(private_node), "lat", -91.0)
-      put api_node_path(private_node), :params => xml.to_s, :headers => auth_header
-      assert_require_public_data "node at lat=-91 should be forbidden, when data isn't public"
-
-      xml = xml_attr_rewrite(xml_for_node(private_node), "lon", 181.0)
-      put api_node_path(private_node), :params => xml.to_s, :headers => auth_header
-      assert_require_public_data "node at lon=181 should be forbidden, when data isn't public"
-
-      xml = xml_attr_rewrite(xml_for_node(private_node), "lon", -181.0)
-      put api_node_path(private_node), :params => xml.to_s, :headers => auth_header
-      assert_require_public_data "node at lon=-181 should be forbidden, when data isn't public"
+      invalid_attr_values.each do |name, value|
+        xml = xml_attr_rewrite(xml_for_node(private_node), name, value)
+        put api_node_path(private_node), :params => xml.to_s, :headers => auth_header
+        assert_require_public_data "node at #{name}=#{value} should be forbidden, when data isn't public"
+      end
 
       ## finally, produce a good request which still won't work
       xml = xml_for_node(private_node)
@@ -386,21 +378,11 @@ module Api
       assert_response :conflict, "update with changeset=0 should be rejected"
 
       ## try and submit invalid updates
-      xml = xml_attr_rewrite(xml_for_node(node), "lat", 91.0)
-      put api_node_path(node), :params => xml.to_s, :headers => auth_header
-      assert_response :bad_request, "node at lat=91 should be rejected"
-
-      xml = xml_attr_rewrite(xml_for_node(node), "lat", -91.0)
-      put api_node_path(node), :params => xml.to_s, :headers => auth_header
-      assert_response :bad_request, "node at lat=-91 should be rejected"
-
-      xml = xml_attr_rewrite(xml_for_node(node), "lon", 181.0)
-      put api_node_path(node), :params => xml.to_s, :headers => auth_header
-      assert_response :bad_request, "node at lon=181 should be rejected"
-
-      xml = xml_attr_rewrite(xml_for_node(node), "lon", -181.0)
-      put api_node_path(node), :params => xml.to_s, :headers => auth_header
-      assert_response :bad_request, "node at lon=-181 should be rejected"
+      invalid_attr_values.each do |name, value|
+        xml = xml_attr_rewrite(xml_for_node(node), name, value)
+        put api_node_path(node), :params => xml.to_s, :headers => auth_header
+        assert_response :bad_request, "node at #{name}=#{value} should be rejected"
+      end
 
       ## next, attack the versioning
       current_node_version = node.version
index 24475fc80ac4786ca7b9c77ecce7687c4ca01b3b..e3bbb490dfdf3c56a4d566647405379dd7db5571 100644 (file)
@@ -657,6 +657,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", ActionController::Base.helpers.image_url("osm_logo_256.png", :host => root_url)
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "OpenStreetMap logo"
+    end
   end
 
   def test_show_og_image
@@ -668,6 +671,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", "https://example.com/picture.jpg"
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "some picture"
+    end
   end
 
   def test_show_og_image_with_relative_uri
@@ -679,6 +685,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", "#{root_url}picture.jpg"
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "some local picture"
+    end
   end
 
   def test_show_og_image_with_spaces
@@ -690,6 +699,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", "https://example.com/the%20picture.jpg"
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "some picture"
+    end
   end
 
   def test_show_og_image_with_relative_uri_and_spaces
@@ -701,6 +713,9 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", "#{root_url}the%20picture.jpg"
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "some local picture"
+    end
   end
 
   def test_show_og_image_with_invalid_uri
@@ -712,6 +727,21 @@ class DiaryEntriesControllerTest < ActionDispatch::IntegrationTest
     assert_dom "head meta[property='og:image']" do
       assert_dom "> @content", ActionController::Base.helpers.image_url("osm_logo_256.png", :host => root_url)
     end
+    assert_dom "head meta[property='og:image:alt']" do
+      assert_dom "> @content", "OpenStreetMap logo"
+    end
+  end
+
+  def test_show_og_image_without_alt
+    user = create(:user)
+    diary_entry = create(:diary_entry, :user => user, :body => "<img src='https://example.com/no_alt.gif'>")
+
+    get diary_entry_path(user, diary_entry)
+    assert_response :success
+    assert_dom "head meta[property='og:image']" do
+      assert_dom "> @content", "https://example.com/no_alt.gif"
+    end
+    assert_dom "head meta[property='og:image:alt']", :count => 0
   end
 
   def test_hide
index e601c36fc5d3b1c27a1443985e9110840fded551..e0b31527669d5f1d8583cdfbe65c483d58a6ec58 100644 (file)
@@ -253,61 +253,79 @@ class RichTextTest < ActiveSupport::TestCase
   def test_text_no_image
     r = RichText.new("text", "foo https://example.com/ bar")
     assert_nil r.image
+    assert_nil r.image_alt
   end
 
   def test_html_no_image
     r = RichText.new("html", "foo <a href='https://example.com/'>bar</a> baz")
     assert_nil r.image
+    assert_nil r.image_alt
   end
 
   def test_markdown_no_image
     r = RichText.new("markdown", "foo [bar](https://example.com/) baz")
     assert_nil r.image
+    assert_nil r.image_alt
   end
 
   def test_markdown_image
     r = RichText.new("markdown", "foo ![bar](https://example.com/image.jpg) baz")
     assert_equal "https://example.com/image.jpg", r.image
+    assert_equal "bar", r.image_alt
   end
 
   def test_markdown_first_image
     r = RichText.new("markdown", "foo ![bar1](https://example.com/image1.jpg) baz\nfoo ![bar2](https://example.com/image2.jpg) baz")
     assert_equal "https://example.com/image1.jpg", r.image
+    assert_equal "bar1", r.image_alt
   end
 
   def test_markdown_image_with_empty_src
     r = RichText.new("markdown", "![invalid]()")
     assert_nil r.image
+    assert_nil r.image_alt
   end
 
   def test_markdown_skip_image_with_empty_src
     r = RichText.new("markdown", "![invalid]() ![valid](https://example.com/valid.gif)")
     assert_equal "https://example.com/valid.gif", r.image
+    assert_equal "valid", r.image_alt
   end
 
   def test_markdown_html_image
+    r = RichText.new("markdown", "<img src='https://example.com/img_element.png' alt='alt text here'>")
+    assert_equal "https://example.com/img_element.png", r.image
+    assert_equal "alt text here", r.image_alt
+  end
+
+  def test_markdown_html_image_without_alt
     r = RichText.new("markdown", "<img src='https://example.com/img_element.png'>")
     assert_equal "https://example.com/img_element.png", r.image
+    assert_nil r.image_alt
   end
 
   def test_markdown_html_image_with_empty_src
-    r = RichText.new("markdown", "<img src=''>")
+    r = RichText.new("markdown", "<img src='' alt='forgot src'>")
     assert_nil r.image
+    assert_nil r.image_alt
   end
 
   def test_markdown_skip_html_image_with_empty_src
-    r = RichText.new("markdown", "<img src=''> <img src='https://example.com/next_img_element.png'>")
+    r = RichText.new("markdown", "<img src='' alt='forgot src'> <img src='https://example.com/next_img_element.png' alt='have src'>")
     assert_equal "https://example.com/next_img_element.png", r.image
+    assert_equal "have src", r.image_alt
   end
 
   def test_markdown_html_image_without_src
-    r = RichText.new("markdown", "<img>")
+    r = RichText.new("markdown", "<img alt='totally forgot src'>")
     assert_nil r.image
+    assert_nil r.image_alt
   end
 
   def test_markdown_skip_html_image_without_src
-    r = RichText.new("markdown", "<img> <img src='https://example.com/next_img_element.png'>")
+    r = RichText.new("markdown", "<img alt='totally forgot src'> <img src='https://example.com/next_img_element.png' alt='have src'>")
     assert_equal "https://example.com/next_img_element.png", r.image
+    assert_equal "have src", r.image_alt
   end
 
   private