spec/lib/roadie/inliner_spec.rb in roadie-2.3.4 vs spec/lib/roadie/inliner_spec.rb in roadie-2.4.0

- old
+ new

@@ -8,11 +8,12 @@ provider.stub(:all).with(['global.css']).and_return(css) end def rendering(html, options = {}) url_options = options.fetch(:url_options, {:host => 'example.com'}) - Nokogiri::HTML.parse Roadie::Inliner.new(provider, ['global.css'], html, url_options).execute + after_inlining_handler = options[:after_inlining_handler] + Nokogiri::HTML.parse Roadie::Inliner.new(provider, ['global.css'], html, url_options, after_inlining_handler).execute end describe "initialization" do it "warns about asset_path_prefix being non-functional" do expect { @@ -80,14 +81,14 @@ document.should have_styling('color' => 'green').at_selector('p') document.should have_styling('color' => 'green').at_selector('a') end end - it "respects !important properties" do + it "keeps !important properties" do use_css "a { text-decoration: underline !important; } a.hard-to-spot { text-decoration: none; }" - rendering('<a class="hard-to-spot"></a>').should have_styling('text-decoration' => 'underline') + rendering('<a class="hard-to-spot"></a>').should have_styling('text-decoration' => 'underline !important') end it "combines with already present inline styles" do use_css "p { color: green }" rendering('<p style="font-size: 1.1em"></p>').should have_styling([['color', 'green'], ['font-size', '1.1em']]) @@ -96,15 +97,43 @@ it "does not touch already present inline styles" do use_css "p { color: red }" rendering('<p style="color: green"></p>').should have_styling([['color', 'red'], ['color', 'green']]) end - it "ignores selectors with :psuedo-classes" do - use_css 'p:hover { color: red }' - rendering('<p></p>').should_not have_styling('color' => 'red') + it "does not apply link and dynamic pseudo selectors" do + use_css " + p:active { color: red } + p:focus { color: red } + p:hover { color: red } + p:link { color: red } + p:target { color: red } + p:visited { color: red } + + p.active { width: 100%; } + " + rendering('<p class="active"></p>').should have_styling('width' => '100%') end + it "does not crash on any pseudo element selectors" do + use_css " + p.some-element { width: 100%; } + p::some-element { color: red; } + " + rendering('<p class="some-element"></p>').should have_styling('width' => '100%') + end + + it "works with nth-child" do + use_css " + p { color: red; } + p:nth-child(2n) { color: green; } + " + rendering(" + <p class='one'></p> + <p class='two'></p> + ").should have_styling('color' => 'green').at_selector('.two') + end + it "ignores selectors with @" do use_css '@keyframes progress-bar-stripes { from { background-position: 40px 0; } @@ -133,10 +162,21 @@ --> ) expect { rendering '<p></p>' }.not_to raise_error end + it "does not pick up scripts generating styles" do + expect { + rendering <<-HTML + <script> + var color = "red"; + document.write("<style type='text/css'>p { color: " + color + "; }</style>"); + </script> + HTML + }.not_to raise_error + end + describe "inline <style> element" do it "is used for inlined styles" do rendering(<<-HTML).should have_styling([['color', 'green'], ['font-size', '1.1em']]) <html> <head> @@ -188,10 +228,21 @@ rendering(<<-HTML).should have_styling('color' => 'green').at_selector('p') <style type="text/css">p { color: green; }</style> <p>Hello World</p> HTML end + + it "is not touched when inside a SVG element" do + expect { + rendering <<-HTML + <p>Hello World</p> + <svg> + <style>This is not parseable by the CSS parser!</style> + </svg> + HTML + }.to_not raise_error + end end end describe "linked stylesheets" do def fake_file(name, contents) @@ -431,12 +482,49 @@ document.should have_attribute('src' => 'https://example.com:8080/b.jpg').at_selector('img') document.should have_styling('background' => 'url(https://example.com:8080/a.jpg)') end end + # This case was happening for some users when emails were rendered as part + # of the request cycle. I do not know it we *really* should accept these + # values, but it looks like Rails do accept it so we might as well do it + # too. + it "supports protocol settings with additional tokens" do + use_css "img { background: url(/a.jpg); }" + rendering('<img src="/b.jpg" />', :url_options => {:host => 'example.com', :protocol => 'https://'}).tap do |document| + document.should have_attribute('src' => 'https://example.com/b.jpg').at_selector('img') + document.should have_styling('background' => 'url(https://example.com/a.jpg)') + end + end + it "does not touch data: URIs" do use_css "div { background: url(data:abcdef); }" rendering('<div></div>').should have_styling('background' => 'url(data:abcdef)') + end + end + + describe "custom converter" do + let(:html) { '<div id="foo"></div>' } + + it "is invoked" do + after_inlining_handler = double("converter") + after_inlining_handler.should_receive(:call).with(anything) + rendering(html, :after_inlining_handler => after_inlining_handler) + end + + it "modifies the document using lambda" do + after_inlining_handler = lambda {|d| d.css("#foo").first["class"] = "bar"} + rendering(html, :after_inlining_handler => after_inlining_handler).css("#foo").first["class"].should == "bar" + end + + it "modifies the document using object" do + klass = Class.new do + def call(d) + d.css("#foo").first["class"] = "bar" + end + end + after_inlining_handler = klass.new + rendering(html, :after_inlining_handler => after_inlining_handler).css("#foo").first["class"].should == "bar" end end describe "inserting tags" do it "inserts a doctype if not present" do