# frozen_string_literal: true require 'spec_helper' describe "Roadie functionality" do describe "on full documents" do def parse_html(html) Nokogiri::HTML.parse(html) end it "adds missing structure" do html = "

Hello world!

".encode("Shift_JIS") document = Roadie::Document.new(html) result = document.transform unless defined?(JRuby) # JRuby has a bug that makes DTD manipulation impossible # See Nokogiri bugs #984 and #985 # https://github.com/sparklemotion/nokogiri/issues/984 # https://github.com/sparklemotion/nokogiri/issues/985 expect(result).to include("") end expect(result).to include("") expect(result).to include("") expect(result).to include("") expect(result).to include(" Hello world!

Hello world!

Check out these awesome prices!

HTML document.add_css <<-CSS em { color: red; } h1 { text-align: center; } CSS result = parse_html document.transform expect(result).to have_styling('text-align' => 'center').at_selector('h1') expect(result).to have_styling('color' => 'red').at_selector('p > em') end it "stores styles that cannot be inlined in the " do document = Roadie::Document.new <<-HTML

Hello world!

Check out these awesome prices!

HTML css = <<-CSS em:hover { color: red; } p:fung-shuei { color: spirit; } CSS document.add_css css expect(Roadie::Utils).to receive(:warn).with(/fung-shuei/) result = parse_html document.transform expect(result).to have_selector("html > head > style") styles = result.at_css("html > head > style").text expect(styles).to include Roadie::Stylesheet.new("", css).to_s end it "can be configured to skip styles that cannot be inlined" do document = Roadie::Document.new <<-HTML

Hello world!

Check out these awesome prices!

HTML css = <<-CSS em:hover { color: red; } p:fung-shuei { color: spirit; } CSS document.add_css css document.keep_uninlinable_css = false expect(Roadie::Utils).to receive(:warn).with(/fung-shuei/) result = parse_html document.transform expect(result).to_not have_selector("html > head > style") end it "inlines css from disk" do document = Roadie::Document.new <<-HTML Hello world!

Hello world!

Check out these awesome prices!

HTML result = parse_html document.transform expect(result).to have_styling('font-size' => '200%').at_selector('p > em') end it "crashes when stylesheets cannot be found, unless using NullProvider" do document = Roadie::Document.new <<-HTML HTML expect { document.transform }.to raise_error(Roadie::CssNotFound, /does_not_exist\.css/) document.asset_providers << Roadie::NullProvider.new expect { document.transform }.to_not raise_error end it "ignores external css if no external providers are added" do document = Roadie::Document.new <<-HTML Hello world!

Hello world!

Check out these awesome prices!

HTML document.external_asset_providers = [] result = parse_html document.transform expect(result).to have_selector('head > link') expect(result).to have_styling([]).at_selector('p > em') end it "inlines external css if configured" do document = Roadie::Document.new <<-HTML Hello world!

Hello world!

Check out these awesome prices!

HTML document.external_asset_providers = TestProvider.new( "http://example.com/big_em.css" => "em { font-size: 200%; }" ) result = parse_html document.transform expect(result).to have_styling('font-size' => '200%').at_selector('p > em') expect(result).to_not have_selector('head > link') end it "does not inline the same properties several times" do document = Roadie::Document.new <<-HTML

Hello world

HTML document.asset_providers = TestProvider.new("hello.css" => <<-CSS) p { color: red; } .hello { color: red; } .world { color: red; } CSS result = parse_html document.transform expect(result).to have_styling([ ['color', 'red'] ]).at_selector('p') end it "makes URLs absolute" do document = Roadie::Document.new <<-HTML About us HTML document.asset_providers = TestProvider.new( "/style.css" => "a { background: url(/assets/link-abcdef1234567890.png); }" ) document.url_options = {host: "myapp.com", scheme: "https", path: "rails/app/"} result = parse_html document.transform expect(result.at_css("a")["href"]).to eq("https://myapp.com/rails/app/about_us") expect(result.at_css("img")["src"]).to eq("https://myapp.com/rails/app/assets/about_us-abcdef1234567890.png") expect(result).to have_styling( "background" => 'url("https://myapp.com/rails/app/assets/bg-abcdef1234567890.png")' ).at_selector("body") expect(result).to have_styling( "background" => 'url(https://myapp.com/rails/app/assets/link-abcdef1234567890.png)' ).at_selector("a") end it "does not change URLs of ignored elements, but still inlines styles on them" do document = Roadie::Document.new <<-HTML About us Unsubscribe HTML document.url_options = {host: "myapp.com", scheme: "https", path: "rails/app/"} result = parse_html document.transform expect(result.at_css("a.one")["href"]).to eq("https://myapp.com/rails/app/about_us") # Nokogiri still treats the attribute as an URL and escapes it. expect(result.at_css("a.two")["href"]).to eq("%24UNSUBSCRIBE_URL") expect(result).to have_styling("color" => "green").at_selector("a.one") expect(result).to have_styling("color" => "green").at_selector("a.two") end it "allows custom callbacks during inlining" do document = Roadie::Document.new <<-HTML Hello world HTML document.before_transformation = proc { |dom| dom.at_css("body")["class"] = "roadie" } document.after_transformation = proc { |dom| dom.at_css("span").remove } result = parse_html document.transform expect(result.at_css("body")["class"]).to eq("roadie") expect(result.at_css("span")).to be_nil end it "does not add whitespace between table cells" do document = Roadie::Document.new <<-HTML
One1
Two2
HTML result = document.transform expect(result).to include("One1") expect(result).to include("Two2") end it "doesn't inline styles in media queries with features" do document = Roadie::Document.new <<-HTML
HTML document.asset_providers = TestProvider.new( "/style.css" => <<-CSS .colorful { color: green; } @media screen and (max-width 600px) { .colorful { color: red; } } CSS ) result = parse_html document.transform expect(result).to have_styling('color' => 'green').at_selector('.colorful') end it 'puts non-inlineable media queries in the head' do document = Roadie::Document.new <<-HTML
HTML document.asset_providers = TestProvider.new( "/style.css" => <<-CSS .colorful { color: green; } @media screen and (max-width 800px) { .colorful { color: blue; } } @media screen, print and (max-width 800px) { .colorful { color: blue; } } CSS ) result = parse_html document.transform styles = result.at_css('html > head > style').text expected_result = <<-CSS @media screen and (max-width 800px) { .colorful{color:blue} } @media screen, print and (max-width 800px) { .colorful{color:blue} } CSS expected_result = expected_result.gsub(/[\s]+/, ' ').strip actual_result = styles.gsub(/[\s]+/, ' ').strip expect(actual_result).to eq(expected_result) end it 'groups non-inlineable media queries in the head by default' do document = Roadie::Document.new <<-HTML
HTML document.asset_providers = TestProvider.new( "/style.css" => <<-CSS .colorful { color: green; } @media screen and (max-width 600px) { .colorful { color: red; width: 600px; } } @media screen and (max-width 600px) { .colorful-2 { color: red; width: 600px; } } CSS ) result = parse_html document.transform styles = result.at_css('html > head > style').text expected_result = <<-CSS @media screen and (max-width 600px) { .colorful{color:red;width:600px} .colorful-2{color:red;width:600px} } CSS expected_result = expected_result.gsub(/[\s]+/, ' ').strip actual_result = styles.gsub(/[\s]+/, ' ').strip expect(actual_result).to eq(expected_result) end describe 'if merge_media_queries is set to false' do it "doesn't group non-inlineable media queries in the head" do document = Roadie::Document.new <<-HTML
HTML document.merge_media_queries = false document.asset_providers = TestProvider.new( "/style.css" => <<-CSS .colorful { color: green; } @media screen and (max-width 600px) { .colorful { color: red; width: 600px; } } @media screen and (max-width 600px) { .colorful-2 { color: red; width: 600px; } } CSS ) result = parse_html document.transform styles = result.at_css('html > head > style').text expected_result = <<-CSS @media screen and (max-width 600px) { .colorful{color:red;width:600px} } @media screen and (max-width 600px) { .colorful-2{color:red;width:600px} } CSS expected_result = expected_result.gsub(/[\s]+/, ' ').strip actual_result = styles.gsub(/[\s]+/, ' ').strip expect(actual_result).to eq(expected_result) end end end describe "on partial documents" do def parse_html(html) Nokogiri::HTML.fragment(html) end it "does not add structure" do html = "

Hello world!

".encode("Shift_JIS") document = Roadie::Document.new(html) result = document.transform_partial expect(result).to eq(html) end it "inlines given css" do document = Roadie::Document.new <<-HTML

Hello world!

Check out these awesome prices!

HTML document.add_css <<-CSS em { color: red; } h1 { text-align: center; } CSS result = parse_html document.transform_partial expect(result).to have_styling('text-align' => 'center').at_selector('h1') expect(result).to have_styling('color' => 'red').at_selector('p > em') end it "stores styles that cannot be inlined in a new
About us
HTML document.asset_providers = TestProvider.new( "/style.css" => "a { background: url(/assets/link-abcdef1234567890.png); }" ) document.url_options = {host: "myapp.com", scheme: "https", path: "rails/app/"} result = parse_html document.transform_partial expect(result.at_css("a")["href"]).to eq("https://myapp.com/rails/app/about_us") expect(result.at_css("img")["src"]).to eq( "https://myapp.com/rails/app/assets/about_us-abcdef1234567890.png" ) expect(result).to have_styling( "background" => 'url("https://myapp.com/rails/app/assets/bg-abcdef1234567890.png")' ).at_selector("div") expect(result).to have_styling( "background" => 'url(https://myapp.com/rails/app/assets/link-abcdef1234567890.png)' ).at_selector("a") end it "allows custom callbacks during inlining" do document = Roadie::Document.new <<-HTML

Hello world

HTML document.before_transformation = proc { |dom| dom.at_css("p")["class"] = "roadie" } document.after_transformation = proc { |dom| dom.at_css("span").remove } result = parse_html document.transform_partial expect(result.at_css("p")["class"]).to eq("roadie") expect(result.at_css("span")).to be_nil end it "does not add whitespace between table cells" do document = Roadie::Document.new <<-HTML
One1
Two2
HTML result = document.transform_partial expect(result).to include("One1") expect(result).to include("Two2") end end end