# frozen_string_literal: true require 'email' describe Email::Styles do let(:attachments) { {} } def basic_fragment(html) styler = Email::Styles.new(html) styler.format_basic Nokogiri::HTML5.fragment(styler.to_html) end def html_fragment(html) styler = Email::Styles.new(html) styler.format_basic styler.format_html Nokogiri::HTML5.fragment(styler.to_html) end context "basic formatter" do it "adds a max-width to large images" do frag = basic_fragment("") expect(frag.at("img")["style"]).to match("max-width") end it "adds a width and height to emojis" do frag = basic_fragment("") expect(frag.at("img")["width"]).to eq("20") expect(frag.at("img")["height"]).to eq("20") end it "adds a width and height to custom emojis" do frag = basic_fragment("") expect(frag.at("img")["width"]).to eq("20") expect(frag.at("img")["height"]).to eq("20") end it "converts relative paths to absolute paths" do frag = basic_fragment("") expect(frag.at("img")["src"]).to eq("#{Discourse.base_url}/some-image.png") end it "strips classes and ids" do frag = basic_fragment("
" do fragment = html_fragment('') expect(fragment.to_s.squish).to match(/^$/) end it "removes GitHub excerpts" do stub_request(:head, "https://github.com/discourse/discourse/pull/1253").to_return(status: 200, body: "", headers: {}) stub_request(:get, "https://api.github.com/repos/discourse/discourse/pulls/1253").to_return(status: 200, body: onebox_response("githubpullrequest")) onebox = Oneboxer.onebox("https://github.com/discourse/discourse/pull/1253") fragment = html_fragment(onebox) expect(fragment.css(".github-body-container .excerpt")).to be_empty end end context "replace_secure_media_urls" do before do setup_s3 SiteSetting.secure_media = true end let(:attachments) { { 'testimage.png' => stub(url: 'email/test.png') } } it "replaces secure media within a link with a placeholder" do frag = html_fragment("") expect(frag.at('img')).not_to be_present expect(frag.to_s).to include("Redacted") end it "replaces secure images with a placeholder" do frag = html_fragment("") expect(frag.at('img')).not_to be_present expect(frag.to_s).to include("Redacted") end it "does not replace topic links with secure-media-uploads in the name" do frag = html_fragment("Visit Topic") expect(frag.to_s).not_to include("Redacted") end it "works in lightboxes with missing srcset attribute" do frag = html_fragment("") expect(frag.at('img')).not_to be_present expect(frag.to_s).to include("Redacted") end it "works in lightboxes with srcset attribute set" do frag = html_fragment( <<~HTML HTML ) expect(frag.at('img')).not_to be_present expect(frag.to_s).to include("Redacted") end it "skips links with no images as children" do frag = html_fragment("Clearly not an image") expect(frag.to_s).to include("not an image") end end context "inline_secure_images" do before do setup_s3 SiteSetting.secure_media = true end fab!(:upload) { Fabricate(:upload, original_filename: 'testimage.png', secure: true, sha1: '123456') } let(:attachments) { [stub(url: 'cid:email/test.png')] } let(:attachments_index) { { upload.sha1 => 0 } } let(:html) { "" } def strip_and_inline # strip out the secure media styler = Email::Styles.new(html) styler.format_basic styler.format_html html = styler.to_html # pass in the attachments to match uploads based on sha + original filename styler = Email::Styles.new(html) styler.inline_secure_images(attachments, attachments_index) @frag = Nokogiri::HTML5.fragment(styler.to_s) end it "inlines attachments where stripped-secure-media data attr is present" do strip_and_inline expect(@frag.to_s).to include("cid:email/test.png") expect(@frag.css('[data-stripped-secure-media]')).not_to be_present expect(@frag.children.attr('style').value).to eq("width: 20px; height: 30px;") end it "does not inline anything if the upload cannot be found" do upload.update(sha1: 'blah12') strip_and_inline expect(@frag.to_s).not_to include("cid:email/test.png") expect(@frag.css('[data-stripped-secure-media]')).to be_present end context "when an optimized image is used instead of the original" do let(:html) { "" } it "inlines attachments where the stripped-secure-media data attr is present" do optimized = Fabricate(:optimized_image, upload: upload, width: 20, height: 30) strip_and_inline expect(@frag.to_s).to include("cid:email/test.png") expect(@frag.css('[data-stripped-secure-media]')).not_to be_present expect(@frag.children.attr('style').value).to eq("width: 20px; height: 30px;") end end context "when inlining an originally oneboxed image" do before do SiteSetting.authorized_extensions = "*" end let(:siteicon) { Fabricate(:upload, original_filename: "siteicon.ico") } let(:attachments) { [stub(url: 'cid:email/test.png'), stub(url: 'cid:email/test2.ico')] } let(:attachments_index) { { upload.sha1 => 0, siteicon.sha1 => 1 } } let(:html) do <<~HTML HTML end it "keeps the special site icon width and height and onebox styles" do optimized = Fabricate(:optimized_image, upload: upload, width: 20, height: 30) strip_and_inline expect(@frag.to_s).to include("cid:email/test.png") expect(@frag.to_s).to include("cid:email/test2.ico") expect(@frag.css('[data-stripped-secure-media]')).not_to be_present expect(@frag.css('[data-embedded-secure-image]')[0].attr('style')).to eq('width: 16px; height: 16px;') expect(@frag.css('[data-embedded-secure-image]')[1].attr('style')).to eq('width: 60px; max-height: 80%; max-width: 20%; height: auto; float: left; margin-right: 10px;') end context "when inlining a oneboxed image with a direct parent of onebox-body" do let(:html) do <<~HTML HTML end it "keeps the special onebox styles" do strip_and_inline expect(@frag.to_s).to include("cid:email/test.png") expect(@frag.to_s).to include("cid:email/test2.ico") expect(@frag.css('[data-stripped-secure-media]')).not_to be_present expect(@frag.css('[data-embedded-secure-image]')[1].attr('style')).to eq('width: 60px; max-height: 80%; max-width: 20%; height: auto; float: left; margin-right: 10px;') end end context "when there is an inline-avatar in the onebox" do let(:html) do <<~HTML @martin check this out:
HTML end it "keeps the special onebox styles" do strip_and_inline expect(@frag.to_s).to include("cid:email/test.png") expect(@frag.css('[data-stripped-secure-media]')).not_to be_present expect(@frag.css('[data-embedded-secure-image]')[0].attr('style')).to eq('width: 20px; height: 20px; float: none; vertical-align: middle; max-height: 80%; max-width: 20%; height: auto; float: left; margin-right: 10px;') end end end end end