From de92913bf4761939ed5d8162db8337ffc7c8a00b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Tue, 14 Aug 2018 12:23:32 +0200 Subject: [PATCH] FIX: store the topic links using the cooked upload url --- app/controllers/embed_controller.rb | 2 +- app/controllers/static_controller.rb | 2 +- app/controllers/user_badges_controller.rb | 2 +- .../users/omniauth_callbacks_controller.rb | 2 +- app/helpers/user_notifications_helper.rb | 2 +- .../onceoff/fix_featured_link_for_topics.rb | 2 +- app/jobs/regular/pull_hotlinked_images.rb | 2 +- app/models/embeddable_host.rb | 4 +- app/models/incoming_link.rb | 4 +- app/models/post_analyzer.rb | 2 +- app/models/site_setting.rb | 2 +- app/models/topic_embed.rb | 2 +- app/models/topic_link.rb | 5 +- app/models/topic_link_click.rb | 6 +- app/models/upload.rb | 2 +- app/models/user_profile.rb | 2 +- app/serializers/user_serializer.rb | 2 +- lib/cooked_post_processor.rb | 24 ++----- lib/discourse.rb | 2 +- lib/email/sender.rb | 2 +- lib/email/styles.rb | 4 +- lib/final_destination.rb | 4 +- lib/inline_oneboxer.rb | 2 +- lib/pretty_text.rb | 4 +- lib/site_setting_extension.rb | 4 +- lib/url_helper.rb | 17 +++++ lib/validators/upload_url_validator.rb | 2 +- lib/validators/url_validator.rb | 2 +- spec/components/cooked_post_processor_spec.rb | 63 ++++++++++--------- spec/fabricators/post_fabricator.rb | 26 ++++---- spec/models/topic_link_spec.rb | 25 ++++---- 31 files changed, 116 insertions(+), 110 deletions(-) diff --git a/app/controllers/embed_controller.rb b/app/controllers/embed_controller.rb index d43754709b2..1199710e226 100644 --- a/app/controllers/embed_controller.rb +++ b/app/controllers/embed_controller.rb @@ -112,7 +112,7 @@ class EmbedController < ApplicationController end response.headers['X-Frame-Options'] = "ALLOWALL" - rescue URI::InvalidURIError + rescue URI::Error raise Discourse::InvalidAccess.new('invalid referer host') end diff --git a/app/controllers/static_controller.rb b/app/controllers/static_controller.rb index f3aaef75f7f..5b444fdc87e 100644 --- a/app/controllers/static_controller.rb +++ b/app/controllers/static_controller.rb @@ -88,7 +88,7 @@ class StaticController < ApplicationController destination = uri.path destination = "#{uri.path}?#{uri.query}" if uri.path =~ /new-topic/ || uri.path =~ /new-message/ || uri.path =~ /user-api-key/ end - rescue URI::InvalidURIError + rescue URI::Error # Do nothing if the URI is invalid end end diff --git a/app/controllers/user_badges_controller.rb b/app/controllers/user_badges_controller.rb index 999c987647c..33bafc5241b 100644 --- a/app/controllers/user_badges_controller.rb +++ b/app/controllers/user_badges_controller.rb @@ -60,7 +60,7 @@ class UserBadgesController < ApplicationController if params[:reason].present? path = begin URI.parse(params[:reason]).path - rescue URI::InvalidURIError + rescue URI::Error end route = Rails.application.routes.recognize_path(path) if path diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb index c102d861dec..fe056f1f0ae 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -41,7 +41,7 @@ class Users::OmniauthCallbacksController < ApplicationController if origin.present? parsed = begin URI.parse(origin) - rescue URI::InvalidURIError + rescue URI::Error end if parsed diff --git a/app/helpers/user_notifications_helper.rb b/app/helpers/user_notifications_helper.rb index b284f69c611..fbf647be5c8 100644 --- a/app/helpers/user_notifications_helper.rb +++ b/app/helpers/user_notifications_helper.rb @@ -106,7 +106,7 @@ module UserNotificationsHelper def url_for_email(href) URI(href).host.present? ? href : UrlHelper.absolute("#{Discourse.base_uri}#{href}") - rescue URI::InvalidURIError, URI::InvalidComponentError + rescue URI::Error href end diff --git a/app/jobs/onceoff/fix_featured_link_for_topics.rb b/app/jobs/onceoff/fix_featured_link_for_topics.rb index 3ccd0f29d68..f05d552f8a7 100644 --- a/app/jobs/onceoff/fix_featured_link_for_topics.rb +++ b/app/jobs/onceoff/fix_featured_link_for_topics.rb @@ -6,7 +6,7 @@ module Jobs begin URI.parse(featured_link) - rescue URI::InvalidURIError + rescue URI::Error topic.update_attributes(featured_link: URI.extract(featured_link).first) end end diff --git a/app/jobs/regular/pull_hotlinked_images.rb b/app/jobs/regular/pull_hotlinked_images.rb index d6e03f782d4..b28daaceb2e 100644 --- a/app/jobs/regular/pull_hotlinked_images.rb +++ b/app/jobs/regular/pull_hotlinked_images.rb @@ -149,7 +149,7 @@ module Jobs # parse the src begin uri = URI.parse(src) - rescue URI::InvalidURIError + rescue URI::Error return false end diff --git a/app/models/embeddable_host.rb b/app/models/embeddable_host.rb index aed2a253627..c8cd6158cf6 100644 --- a/app/models/embeddable_host.rb +++ b/app/models/embeddable_host.rb @@ -14,7 +14,7 @@ class EmbeddableHost < ActiveRecord::Base if uri.is_a?(String) uri = begin URI(UrlHelper.escape_uri(uri)) - rescue URI::InvalidURIError + rescue URI::Error end end return false unless uri.present? @@ -45,7 +45,7 @@ class EmbeddableHost < ActiveRecord::Base uri = begin URI(UrlHelper.escape_uri(url)) - rescue URI::InvalidURIError + rescue URI::Error end uri.present? && record_for_url(uri).present? diff --git a/app/models/incoming_link.rb b/app/models/incoming_link.rb index ef680dc4939..82e281ef0ee 100644 --- a/app/models/incoming_link.rb +++ b/app/models/incoming_link.rb @@ -26,7 +26,7 @@ class IncomingLink < ActiveRecord::Base begin host = URI.parse(opts[:referer]).host referer = opts[:referer][0..999] - rescue URI::InvalidURIError + rescue URI::Error # bad uri, skip end end @@ -71,7 +71,7 @@ class IncomingLink < ActiveRecord::Base self.incoming_referer_id = referer_record.id if referer_record end - rescue URI::InvalidURIError + rescue URI::Error # ignore end diff --git a/app/models/post_analyzer.rb b/app/models/post_analyzer.rb index 90c81f096ed..4d4145f1e4c 100644 --- a/app/models/post_analyzer.rb +++ b/app/models/post_analyzer.rb @@ -98,7 +98,7 @@ class PostAnalyzer uri = self.class.parse_uri_rfc2396(u) host = uri.host @linked_hosts[host] ||= 1 unless host.nil? - rescue URI::InvalidURIError, URI::InvalidComponentError + rescue URI::Error # An invalid URI does not count as a host next end diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb index cf36c4b782b..8fa073e773a 100644 --- a/app/models/site_setting.rb +++ b/app/models/site_setting.rb @@ -77,7 +77,7 @@ class SiteSetting < ActiveRecord::Base host = URI.parse(src).host return !(setting.split('|').include?(host)) - rescue URI::InvalidURIError + rescue URI::Error return true end diff --git a/app/models/topic_embed.rb b/app/models/topic_embed.rb index 42d078e0033..db33afe9cdb 100644 --- a/app/models/topic_embed.rb +++ b/app/models/topic_embed.rb @@ -139,7 +139,7 @@ class TopicEmbed < ActiveRecord::Base uri.host = original_uri.host node[url_param] = uri.to_s end - rescue URI::InvalidURIError, URI::InvalidComponentError + rescue URI::Error # If there is a mistyped URL, just do nothing end end diff --git a/app/models/topic_link.rb b/app/models/topic_link.rb index e41b685e69c..22f8feeab73 100644 --- a/app/models/topic_link.rb +++ b/app/models/topic_link.rb @@ -137,8 +137,9 @@ SQL post_number = nil if upload = Upload.get_from_url(url) - url = upload.url internal = Discourse.store.internal? + # Store the same URL that will be used in the cooked version of the post + url = UrlHelper.cook_url(upload.url) elsif route = Discourse.route_for(parsed) internal = true @@ -217,7 +218,7 @@ SQL end end - rescue URI::InvalidURIError + rescue URI::Error # if the URI is invalid, don't store it. rescue ActionController::RoutingError # If we can't find the route, no big deal diff --git a/app/models/topic_link_click.rb b/app/models/topic_link_click.rb index 422c974bfdc..7ae52e6b09d 100644 --- a/app/models/topic_link_click.rb +++ b/app/models/topic_link_click.rb @@ -17,7 +17,7 @@ class TopicLinkClick < ActiveRecord::Base uri = begin URI.parse(url) - rescue URI::InvalidURIError + rescue URI::Error end urls = Set.new @@ -47,7 +47,7 @@ class TopicLinkClick < ActiveRecord::Base if Discourse.asset_host.present? cdn_uri = begin URI.parse(Discourse.asset_host) - rescue URI::InvalidURIError + rescue URI::Error end if cdn_uri && cdn_uri.hostname == uri.hostname && uri.path.starts_with?(cdn_uri.path) @@ -59,7 +59,7 @@ class TopicLinkClick < ActiveRecord::Base if SiteSetting.Upload.s3_cdn_url.present? cdn_uri = begin URI.parse(SiteSetting.Upload.s3_cdn_url) - rescue URI::InvalidURIError + rescue URI::Error end if cdn_uri && cdn_uri.hostname == uri.hostname && uri.path.starts_with?(cdn_uri.path) diff --git a/app/models/upload.rb b/app/models/upload.rb index afe9dbd2bed..022d10b160a 100644 --- a/app/models/upload.rb +++ b/app/models/upload.rb @@ -80,7 +80,7 @@ class Upload < ActiveRecord::Base uri = begin URI(URI.unescape(url)) - rescue URI::InvalidURIError, URI::InvalidComponentError + rescue URI::Error end return if uri&.path.blank? diff --git a/app/models/user_profile.rb b/app/models/user_profile.rb index 11ebf37cb52..ffc62a263f3 100644 --- a/app/models/user_profile.rb +++ b/app/models/user_profile.rb @@ -142,7 +142,7 @@ class UserProfile < ActiveRecord::Base domain = begin URI.parse(self.website).host - rescue URI::InvalidURIError + rescue URI::Error end self.errors.add :base, (I18n.t('user.website.domain_not_allowed', domains: allowed_domains.split('|').join(", "))) unless allowed_domains.split('|').include?(domain) end diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb index 08fdd23dea1..e840be472b8 100644 --- a/app/serializers/user_serializer.rb +++ b/app/serializers/user_serializer.rb @@ -206,7 +206,7 @@ class UserSerializer < BasicUserSerializer def website_name uri = begin URI(website.to_s) - rescue URI::InvalidURIError + rescue URI::Error end return if uri.nil? || uri.host.nil? diff --git a/lib/cooked_post_processor.rb b/lib/cooked_post_processor.rb index 3f78317bca2..72423cf43a7 100644 --- a/lib/cooked_post_processor.rb +++ b/lib/cooked_post_processor.rb @@ -257,14 +257,14 @@ class CookedPostProcessor return unless SiteSetting.crawl_images? || Discourse.store.has_been_uploaded?(url) @size_cache[url] = FastImage.size(absolute_url) - rescue Zlib::BufError, URI::InvalidURIError, URI::InvalidComponentError, OpenSSL::SSL::SSLError + rescue Zlib::BufError, URI::Error, OpenSSL::SSL::SSLError # FastImage.size raises BufError for some gifs, leave it. end def is_valid_image_url?(url) uri = URI.parse(url) %w(http https).include? uri.scheme - rescue URI::InvalidURIError + rescue URI::Error end def convert_to_link!(img) @@ -460,28 +460,14 @@ class CookedPostProcessor end def optimize_urls - # attachments can't be on the CDN when either setting is enabled - if SiteSetting.login_required || SiteSetting.prevent_anons_from_downloading_files - @doc.css("a.attachment[href]").each do |a| - href = a["href"].to_s - a["href"] = UrlHelper.schemaless UrlHelper.absolute_without_cdn(href) if UrlHelper.is_local(href) - end - end - - use_s3_cdn = SiteSetting.Upload.enable_s3_uploads && SiteSetting.Upload.s3_cdn_url.present? - %w{href data-download-href}.each do |selector| @doc.css("a[#{selector}]").each do |a| - href = a[selector].to_s - a[selector] = UrlHelper.schemaless UrlHelper.absolute(href) if UrlHelper.is_local(href) - a[selector] = Discourse.store.cdn_url(a[selector]) if use_s3_cdn + a[selector] = UrlHelper.cook_url(a[selector].to_s) end end @doc.css("img[src]").each do |img| - src = img["src"].to_s - img["src"] = UrlHelper.schemaless UrlHelper.absolute(src) if UrlHelper.is_local(src) - img["src"] = Discourse.store.cdn_url(img["src"]) if use_s3_cdn + img["src"] = UrlHelper.cook_url(img["src"].to_s) end end @@ -544,7 +530,7 @@ class CookedPostProcessor path = begin URI(img["src"]).path - rescue URI::InvalidURIError, URI::InvalidComponentError + rescue URI::Error nil end diff --git a/lib/discourse.rb b/lib/discourse.rb index 9054e79e4b9..8bb5ac29743 100644 --- a/lib/discourse.rb +++ b/lib/discourse.rb @@ -270,7 +270,7 @@ module Discourse unless uri.is_a?(URI) uri = begin URI(uri) - rescue URI::InvalidURIError + rescue URI::Error end end diff --git a/lib/email/sender.rb b/lib/email/sender.rb index 56f427bcaf4..351cc2cc45d 100644 --- a/lib/email/sender.rb +++ b/lib/email/sender.rb @@ -218,7 +218,7 @@ module Email begin uri = URI.parse(base_url) host = uri.host.downcase if uri.host.present? - rescue URI::InvalidURIError + rescue URI::Error end end host diff --git a/lib/email/styles.rb b/lib/email/styles.rb index 6e14c7bcf85..33ae884b7ff 100644 --- a/lib/email/styles.rb +++ b/lib/email/styles.rb @@ -153,7 +153,7 @@ module Email # If an iframe is protocol relative, use SSL when displaying it display_src = "#{src_uri.scheme || 'https'}://#{src_uri.host}#{src_uri.path}#{src_uri.query.nil? ? '' : '?' + src_uri.query}#{src_uri.fragment.nil? ? '' : '#' + src_uri.fragment}" i.replace "

#{CGI.escapeHTML(display_src)}

" - rescue URI::InvalidURIError + rescue URI::Error # If the URL is weird, remove the iframe i.remove end @@ -215,7 +215,7 @@ module Email @fragment.css("a").each do |link| begin link["href"] = "#{site_uri}#{link['href']}" unless URI(link["href"].to_s).host.present? - rescue URI::InvalidURIError, URI::InvalidComponentError + rescue URI::Error # leave it end end diff --git a/lib/final_destination.rb b/lib/final_destination.rb index b1360d20734..7e1ed92396f 100644 --- a/lib/final_destination.rb +++ b/lib/final_destination.rb @@ -378,8 +378,8 @@ class FinalDestination def uri(location) begin - URI(location) - rescue URI::InvalidURIError, ArgumentError + URI.parse(location) + rescue URI::Error end end diff --git a/lib/inline_oneboxer.rb b/lib/inline_oneboxer.rb index 7e1ccfa29fd..7ee57b432e9 100644 --- a/lib/inline_oneboxer.rb +++ b/lib/inline_oneboxer.rb @@ -46,7 +46,7 @@ class InlineOneboxer if always_allow || domains uri = begin URI(url) - rescue URI::InvalidURIError + rescue URI::Error end if uri.present? && diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb index 9e3b5fc94c2..cf6a3eefa4b 100644 --- a/lib/pretty_text.rb +++ b/lib/pretty_text.rb @@ -293,7 +293,7 @@ module PrettyText else l["rel"] = "nofollow noopener" end - rescue URI::InvalidURIError, URI::InvalidComponentError + rescue URI::Error # add a nofollow anyway l["rel"] = "nofollow noopener" end @@ -363,7 +363,7 @@ module PrettyText unless uri.host.present? || href.start_with?('mailto') link["href"] = "#{site_uri}#{link['href']}" end - rescue URI::InvalidURIError, URI::InvalidComponentError + rescue URI::Error # leave it end end diff --git a/lib/site_setting_extension.rb b/lib/site_setting_extension.rb index e8bbacc170e..490cc26b6d5 100644 --- a/lib/site_setting_extension.rb +++ b/lib/site_setting_extension.rb @@ -426,13 +426,13 @@ module SiteSettingExtension host = begin URI.parse(url)&.host - rescue URI::InvalidURIError + rescue URI::Error nil end host ||= begin URI.parse("http://#{url}")&.host - rescue URI::InvalidURIError + rescue URI::Error nil end diff --git a/lib/url_helper.rb b/lib/url_helper.rb index 758528a4a31..5df27575f85 100644 --- a/lib/url_helper.rb +++ b/lib/url_helper.rb @@ -31,4 +31,21 @@ class UrlHelper encoded end + def self.cook_url(url) + return url unless is_local(url) + + uri = URI.parse(url) + filename = File.basename(uri.path) + is_attachment = !FileHelper.is_image?(filename) + + no_cdn = SiteSetting.login_required || SiteSetting.prevent_anons_from_downloading_files + + url = absolute_without_cdn(url) + url = Discourse.store.cdn_url(url) unless is_attachment && no_cdn + + schemaless(url) + rescue URI::Error + url + end + end diff --git a/lib/validators/upload_url_validator.rb b/lib/validators/upload_url_validator.rb index 899d6afa7a7..7823478aa77 100644 --- a/lib/validators/upload_url_validator.rb +++ b/lib/validators/upload_url_validator.rb @@ -4,7 +4,7 @@ class UploadUrlValidator < ActiveModel::EachValidator uri = begin URI.parse(value) - rescue URI::InvalidURIError + rescue URI::Error end unless uri && Upload.exists?(url: value) diff --git a/lib/validators/url_validator.rb b/lib/validators/url_validator.rb index 7edfe431f3c..fec4470cec8 100644 --- a/lib/validators/url_validator.rb +++ b/lib/validators/url_validator.rb @@ -5,7 +5,7 @@ class UrlValidator < ActiveModel::EachValidator begin uri = URI.parse(value) uri.is_a?(URI::HTTP) && !uri.host.nil? && uri.host.include?(".") - rescue URI::InvalidURIError => e + rescue URI::Error => e if (e.message =~ /URI must be ascii only/) value = URI.encode(value) retry diff --git a/spec/components/cooked_post_processor_spec.rb b/spec/components/cooked_post_processor_spec.rb index d099dc9affc..9530383a59d 100644 --- a/spec/components/cooked_post_processor_spec.rb +++ b/spec/components/cooked_post_processor_spec.rb @@ -162,7 +162,7 @@ describe CookedPostProcessor do FileStore::BaseStore.any_instance.expects(:get_depth_for).returns(0) cpp.post_process_images - expect(cpp.html).to match_html "

+ expect(cpp.html).to match_html "

" expect(cpp).to be_dirty @@ -170,25 +170,25 @@ describe CookedPostProcessor do describe 'when image is an svg' do let(:post) do - Fabricate(:post, raw: '') + Fabricate(:post, raw: '') end it 'should not add lightbox' do cpp.post_process_images - expect(cpp.html).to match_html("

") + expect(cpp.html).to match_html("

") end describe 'when image src is an URL' do let(:post) do - Fabricate(:post, raw: '') + Fabricate(:post, raw: '') end it 'should not add lightbox' do SiteSetting.crawl_images = true cpp.post_process_images - expect(cpp.html).to match_html("

") + expect(cpp.html).to match_html("

") end end end @@ -239,7 +239,7 @@ describe CookedPostProcessor do it "crops the image" do cpp.post_process_images - expect(cpp.html).to match_html "

+ expect(cpp.html).to match_html "

" expect(cpp).to be_dirty @@ -270,7 +270,7 @@ describe CookedPostProcessor do it "generates overlay information" do cpp.post_process_images - expect(cpp.html).to match_html "

+ expect(cpp.html).to match_html "

" expect(cpp).to be_dirty @@ -279,7 +279,7 @@ describe CookedPostProcessor do it "should escape the filename" do upload.update_attributes!(original_filename: ">.png") cpp.post_process_images - expect(cpp.html).to match_html "

+ expect(cpp.html).to match_html "

" end @@ -305,7 +305,7 @@ describe CookedPostProcessor do it "generates overlay information" do cpp.post_process_images - expect(cpp.html).to match_html "

+ expect(cpp.html).to match_html "

" expect(cpp).to be_dirty @@ -594,13 +594,14 @@ describe CookedPostProcessor do it "uses schemaless url for uploads" do cpp.optimize_urls - expect(cpp.html).to match_html '

Link
-
+ expect(cpp.html).to match_html <<~HTML +

Link
+
Google

text.txt (20 Bytes)
- :smile: -

' + :smile:

+ HTML end context "when CDN is enabled" do @@ -608,51 +609,55 @@ describe CookedPostProcessor do it "uses schemaless CDN url for http uploads" do Rails.configuration.action_controller.stubs(:asset_host).returns("http://my.cdn.com") cpp.optimize_urls - expect(cpp.html).to match_html '

Link
-
+ expect(cpp.html).to match_html <<~HTML +

Link
+
Google

text.txt (20 Bytes)
- :smile: -

' + :smile:

+ HTML end it "doesn't use schemaless CDN url for https uploads" do Rails.configuration.action_controller.stubs(:asset_host).returns("https://my.cdn.com") cpp.optimize_urls - expect(cpp.html).to match_html '

Link
-
+ expect(cpp.html).to match_html <<~HTML +

Link
+
Google

text.txt (20 Bytes)
- :smile: -

' + :smile:

+ HTML end it "doesn't use CDN when login is required" do SiteSetting.login_required = true Rails.configuration.action_controller.stubs(:asset_host).returns("http://my.cdn.com") cpp.optimize_urls - expect(cpp.html).to match_html '

Link
-
+ expect(cpp.html).to match_html <<~HTML +

Link
+
Google

text.txt (20 Bytes)
- :smile: -

' + :smile:

+ HTML end it "doesn't use CDN when preventing anons from downloading files" do SiteSetting.prevent_anons_from_downloading_files = true Rails.configuration.action_controller.stubs(:asset_host).returns("http://my.cdn.com") cpp.optimize_urls - expect(cpp.html).to match_html '

Link
-
+ expect(cpp.html).to match_html <<~HTML +

Link
+
Google

text.txt (20 Bytes)
- :smile: -

' + :smile:

+ HTML end end diff --git a/spec/fabricators/post_fabricator.rb b/spec/fabricators/post_fabricator.rb index e566d949b81..2f3aaf0a1b3 100644 --- a/spec/fabricators/post_fabricator.rb +++ b/spec/fabricators/post_fabricator.rb @@ -46,25 +46,25 @@ end Fabricator(:post_with_plenty_of_images, from: :post) do cooked ' - -
-
+ +
+

With an emoji! smile

' end Fabricator(:post_with_uploaded_image, from: :post) do - raw '' + raw '' end Fabricator(:post_with_an_attachment, from: :post) do - raw 'archive.zip' + raw 'archive.zip' end Fabricator(:post_with_unsized_images, from: :post) do raw ' - + ' end @@ -76,28 +76,28 @@ Fabricator(:post_with_image_urls, from: :post) do end Fabricator(:post_with_large_image, from: :post) do - raw '' + raw '' end Fabricator(:post_with_large_image_and_title, from: :post) do - raw '' + raw '' end Fabricator(:post_with_large_image_on_subfolder, from: :post) do - raw '' + raw '' end Fabricator(:post_with_uploads, from: :post) do raw ' -Link - +Link + ' end Fabricator(:post_with_uploads_and_links, from: :post) do raw ' -Link - +Link + Google text.txt (20 Bytes) diff --git a/spec/models/topic_link_spec.rb b/spec/models/topic_link_spec.rb index 165239cd6e5..20a81c648a0 100644 --- a/spec/models/topic_link_spec.rb +++ b/spec/models/topic_link_spec.rb @@ -27,25 +27,22 @@ describe TopicLink do describe 'external links' do before do - post = Fabricate(:post, raw: " -http://a.com/ -http://b.com/b -http://#{'a' * 200}.com/invalid -http://b.com/#{'a' * 500} - ", user: user, topic: topic) + post = Fabricate(:post, raw: <<~RAW, user: user, topic: topic) + http://a.com/ + https://b.com/b + http://#{'a' * 200}.com/invalid + //b.com/#{'a' * 500} + RAW TopicLink.extract_from(post) end it 'works' do - # has the forum topic links - expect(topic.topic_links.count).to eq(3) - - # works with markdown links - expect(topic.topic_links.exists?(url: "http://a.com/")).to eq(true) - - #works with markdown links followed by a period - expect(topic.topic_links.exists?(url: "http://b.com/b")).to eq(true) + expect(topic.topic_links.pluck(:url)).to contain_exactly( + "http://a.com/", + "https://b.com/b", + "//b.com/#{'a' * 500}"[0...TopicLink.max_url_length] + ) end end