premailer-rails 1.5.1 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,6 +5,7 @@ class Premailer
5
5
 
6
6
  def self.delivering_email(message)
7
7
  self.new(message).perform
8
+ message
8
9
  end
9
10
 
10
11
  def initialize(message)
@@ -12,15 +13,23 @@ class Premailer
12
13
  end
13
14
 
14
15
  def perform
15
- if message_contains_html?
16
+ if skip_premailer_header_present?
17
+ remove_skip_premailer_header
18
+ elsif message_contains_html?
16
19
  replace_html_part(generate_html_part_replacement)
17
20
  end
18
-
19
- message
20
21
  end
21
22
 
22
23
  private
23
24
 
25
+ def skip_premailer_header_present?
26
+ message.header[:skip_premailer]
27
+ end
28
+
29
+ def remove_skip_premailer_header
30
+ message.header[:skip_premailer] = nil
31
+ end
32
+
24
33
  def message_contains_html?
25
34
  html_part.present?
26
35
  end
@@ -20,13 +20,11 @@ Gem::Specification.new do |s|
20
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
21
  s.require_paths = ["lib"]
22
22
 
23
- s.add_dependency 'premailer', '~> 1.7'
24
- s.add_dependency 'rails', '>= 3'
23
+ s.add_dependency 'premailer', '~> 1.7', '>= 1.7.9'
24
+ s.add_dependency 'actionmailer', '>= 3', '< 5'
25
25
 
26
- s.add_development_dependency 'rspec-core'
27
- s.add_development_dependency 'rspec-expectations'
28
- s.add_development_dependency 'mocha'
29
- s.add_development_dependency 'mail'
26
+ s.add_development_dependency 'rspec', '>= 3.0.0.beta1'
30
27
  s.add_development_dependency 'nokogiri'
31
28
  s.add_development_dependency 'hpricot' unless RUBY_PLATFORM == 'java'
29
+ s.add_development_dependency 'coveralls'
32
30
  end
@@ -0,0 +1,168 @@
1
+ require 'spec_helper'
2
+
3
+ describe Premailer::Rails::CSSHelper do
4
+ # Reset the CSS cache:
5
+ after do
6
+ Premailer::Rails::CSSHelper.send(:instance_variable_set, '@cache', {})
7
+ end
8
+
9
+ def load_css(path)
10
+ Premailer::Rails::CSSHelper.send(:load_css, path)
11
+ end
12
+
13
+ def css_for_doc(doc)
14
+ Premailer::Rails::CSSHelper.css_for_doc(doc)
15
+ end
16
+
17
+ def expect_file(path, content='file content')
18
+ allow(File).to receive(:exist?).with(path).and_return(true)
19
+ expect(File).to receive(:read).with(path).and_return(content)
20
+ end
21
+
22
+ describe '#css_for_doc' do
23
+ let(:html) { Fixtures::HTML.with_css_links(*files) }
24
+ let(:doc) { Nokogiri(html) }
25
+
26
+ context 'when HTML contains linked CSS files' do
27
+ let(:files) { %w[ stylesheets/base.css stylesheets/font.css ] }
28
+
29
+ it 'should return the content of both files concatenated' do
30
+ allow(Premailer::Rails::CSSHelper).to \
31
+ receive(:load_css)
32
+ .with('http://example.com/stylesheets/base.css')
33
+ .and_return('content of base.css')
34
+ allow(Premailer::Rails::CSSHelper).to \
35
+ receive(:load_css)
36
+ .with('http://example.com/stylesheets/font.css')
37
+ .and_return('content of font.css')
38
+
39
+ expect(css_for_doc(doc)).to eq("content of base.css\ncontent of font.css")
40
+ end
41
+ end
42
+ end
43
+
44
+ describe '#load_css' do
45
+ context 'when path is a url' do
46
+ it 'should load the CSS at the local path' do
47
+ expect_file('public/stylesheets/base.css')
48
+
49
+ load_css('http://example.com/stylesheets/base.css?test')
50
+ end
51
+ end
52
+
53
+ context 'when path is a relative url' do
54
+ it 'should load the CSS at the local path' do
55
+ expect_file('public/stylesheets/base.css')
56
+ load_css('/stylesheets/base.css?test')
57
+ end
58
+ end
59
+
60
+ context 'when file is cached' do
61
+ it 'should return the cached value' do
62
+ cache =
63
+ Premailer::Rails::CSSHelper.send(:instance_variable_get, '@cache')
64
+ cache['http://example.com/stylesheets/base.css'] = 'content of base.css'
65
+
66
+ expect(load_css('http://example.com/stylesheets/base.css')).to \
67
+ eq('content of base.css')
68
+ end
69
+ end
70
+
71
+ context 'when in development mode' do
72
+ it 'should not return cached values' do
73
+ cache =
74
+ Premailer::Rails::CSSHelper.send(:instance_variable_get, '@cache')
75
+ cache['http://example.com/stylesheets/base.css'] =
76
+ 'cached content of base.css'
77
+ content = 'new content of base.css'
78
+ expect_file('public/stylesheets/base.css', content)
79
+ allow(Rails.env).to receive(:development?).and_return(true)
80
+
81
+ expect(load_css('http://example.com/stylesheets/base.css')).to eq(content)
82
+ end
83
+ end
84
+
85
+ context 'when Rails asset pipeline is used' do
86
+ before do
87
+ allow(Rails.configuration).to receive(:assets).and_return(double(prefix: '/assets'))
88
+ end
89
+
90
+ context 'and a precompiled file exists' do
91
+ it 'should return that file' do
92
+ path = '/assets/email-digest.css'
93
+ content = 'read from file'
94
+ expect_file("public#{path}", content)
95
+ expect(load_css(path)).to eq(content)
96
+ end
97
+ end
98
+
99
+ it 'should return the content of the file compiled by Rails' do
100
+ expect(Rails.application.assets).to \
101
+ receive(:find_asset)
102
+ .with('base.css')
103
+ .and_return(double(to_s: 'content of base.css'))
104
+
105
+ expect(load_css('http://example.com/assets/base.css')).to \
106
+ eq('content of base.css')
107
+ end
108
+
109
+ it 'should return same file when path contains file fingerprint' do
110
+ expect(Rails.application.assets).to \
111
+ receive(:find_asset)
112
+ .with('base.css')
113
+ .and_return(double(to_s: 'content of base.css'))
114
+
115
+ expect(load_css(
116
+ 'http://example.com/assets/base-089e35bd5d84297b8d31ad552e433275.css'
117
+ )).to eq('content of base.css')
118
+ end
119
+
120
+ context 'when asset can not be found' do
121
+ let(:response) { 'content of base.css' }
122
+ let(:path) { '/assets/base-089e35bd5d84297b8d31ad552e433275.css' }
123
+ let(:url) { "http://assets.example.com#{path}" }
124
+ let(:asset_host) { 'http://assets.example.com' }
125
+
126
+ before do
127
+ allow(Rails.application.assets).to \
128
+ receive(:find_asset).and_return(nil)
129
+
130
+ config = double(asset_host: asset_host)
131
+ allow(Rails.configuration).to \
132
+ receive(:action_controller).and_return(config)
133
+
134
+ uri_satisfaction = satisfy { |uri| uri.to_s == url }
135
+ allow(Net::HTTP).to \
136
+ receive(:get).with(uri_satisfaction).and_return(response)
137
+ end
138
+
139
+ it 'should request the file' do
140
+ expect(load_css(url)).to eq('content of base.css')
141
+ end
142
+
143
+ context 'when file url does not include the host' do
144
+ it 'should request the file using the asset host as host' do
145
+ expect(load_css(path)).to eq('content of base.css')
146
+ end
147
+
148
+ context 'and the asset host uses protocol relative scheme' do
149
+ let(:asset_host) { '//assets.example.com' }
150
+
151
+ it 'should request the file using http as the scheme' do
152
+ expect(load_css(path)).to eq('content of base.css')
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ context 'when static stylesheets are used' do
160
+ it 'should return the content of the static file' do
161
+ content = 'content of base.css'
162
+ expect_file('public/stylesheets/base.css', content)
163
+ loaded_content = load_css('http://example.com/stylesheets/base.css')
164
+ expect(loaded_content).to eq(content)
165
+ end
166
+ end
167
+ end
168
+ end
@@ -2,9 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  describe 'ActionMailer::Base.register_interceptor' do
4
4
  it 'should register interceptor Premailer::Rails::Hook' do
5
- ActionMailer::Base
6
- .expects(:register_interceptor)
7
- .with(Premailer::Rails::Hook)
5
+ expect(ActionMailer::Base).to \
6
+ receive(:register_interceptor).with(Premailer::Rails::Hook)
8
7
  load 'premailer/rails.rb'
9
8
  end
10
9
  end
@@ -11,7 +11,7 @@ describe Premailer::Rails::Hook do
11
11
  end
12
12
  end
13
13
 
14
- let(:message) { Fixtures::Message.with_body(:html) }
14
+ let(:message) { Fixtures::Message.with_parts(:html) }
15
15
  let(:processed_message) { run_hook(message) }
16
16
 
17
17
  it 'inlines the CSS' do
@@ -20,8 +20,9 @@ describe Premailer::Rails::Hook do
20
20
  end
21
21
 
22
22
  it 'replaces the html part with an alternative part containing text and html parts' do
23
- processed_message.content_type.should include 'multipart/alternative'
24
- processed_message.parts.should =~ [message.html_part, message.text_part]
23
+ expect(processed_message.content_type).to include('multipart/alternative')
24
+ expected_parts = [message.html_part, message.text_part]
25
+ expect(processed_message.parts).to match_array(expected_parts)
25
26
  end
26
27
 
27
28
  it 'generates a text part from the html' do
@@ -29,7 +30,7 @@ describe Premailer::Rails::Hook do
29
30
  end
30
31
 
31
32
  context 'when message contains no html' do
32
- let(:message) { Fixtures::Message.with_body(:text) }
33
+ let(:message) { Fixtures::Message.with_parts(:text) }
33
34
 
34
35
  it 'does not modify the message' do
35
36
  expect { run_hook(message) }.to_not change(message, :html_string)
@@ -64,14 +65,29 @@ describe Premailer::Rails::Hook do
64
65
  context 'when message also contains an attachment' do
65
66
  let(:message) { Fixtures::Message.with_parts(:html, :attachment) }
66
67
  it 'does not mess with it' do
67
- message.content_type.should include 'multipart/mixed'
68
- message.parts.first.content_type.should include 'text/html'
69
- message.parts.last.content_type.should include 'image/png'
68
+ expect(message.content_type).to include 'multipart/mixed'
69
+ expect(message.parts.first.content_type).to include 'text/html'
70
+ expect(message.parts.last.content_type).to include 'image/png'
70
71
 
71
- processed_message.content_type.should include 'multipart/mixed'
72
- processed_message.parts.first.content_type.should \
72
+ expect(processed_message.content_type).to include 'multipart/mixed'
73
+ expect(processed_message.parts.first.content_type).to \
73
74
  include 'multipart/alternative'
74
- processed_message.parts.last.content_type.should include 'image/png'
75
+ expect(processed_message.parts.last.content_type).to include 'image/png'
76
+ end
77
+ end
78
+
79
+ context 'when message has a skip premailer header' do
80
+ before do
81
+ message.header[:skip_premailer] = true
82
+ end
83
+
84
+ it 'does not change the message body' do
85
+ expect { run_hook(message) }.to_not change(message, :body)
86
+ end
87
+
88
+ it 'removes that header' do
89
+ expect { run_hook(message) }.to \
90
+ change { message.header[:skip_premailer].nil? }.to(true)
75
91
  end
76
92
  end
77
93
  end
@@ -1,13 +1,25 @@
1
+ if ENV['CI']
2
+ require 'coveralls'
3
+ Coveralls::Output.silent = true
4
+ Coveralls.wear! do
5
+ add_filter 'spec/'
6
+ end
7
+ else
8
+ require 'simplecov'
9
+ SimpleCov.start
10
+ end
11
+
1
12
  require 'premailer/rails'
2
13
 
3
- require 'stubs/action_mailer'
4
- require 'stubs/rails'
5
- require 'fixtures/message'
6
- require 'fixtures/html'
14
+ require 'support/stubs/action_mailer'
15
+ require 'support/stubs/rails'
16
+ require 'support/fixtures/message'
17
+ require 'support/fixtures/html'
7
18
 
8
19
  require 'hpricot' unless RUBY_PLATFORM == 'java'
9
20
  require 'nokogiri'
10
21
 
11
22
  RSpec.configure do |config|
12
- config.mock_with :mocha
23
+ config.raise_errors_for_deprecations!
24
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
13
25
  end
@@ -30,13 +30,5 @@ module Fixtures
30
30
 
31
31
  TEMPLATE % links.join
32
32
  end
33
-
34
- def with_no_css_link
35
- with_css_links
36
- end
37
-
38
- def with_style_block
39
- TEMPLATE % '<style type="text/css">p { color: red; }</style>'
40
- end
41
33
  end
42
34
  end
@@ -1,26 +1,8 @@
1
- require 'stubs/dummy'
2
-
3
- class Logger
4
- def self.try(*args); end
5
- end
6
-
7
1
  module Rails
8
2
  extend self
9
3
 
10
4
  module Configuration
11
5
  extend self
12
-
13
- module Middleware
14
- extend self
15
-
16
- def include?(what)
17
- false
18
- end
19
- end
20
-
21
- def middleware
22
- Middleware
23
- end
24
6
  end
25
7
 
26
8
  module Env
@@ -51,14 +33,6 @@ module Rails
51
33
  Configuration
52
34
  end
53
35
 
54
- def logger
55
- Logger
56
- end
57
-
58
- def root
59
- 'RAILS_ROOT'
60
- end
61
-
62
36
  def application
63
37
  Application
64
38
  end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Premailer::Rails::CSSLoaders::AssetPipelineLoader do
4
+ before do
5
+ assets = double(prefix: '/assets')
6
+ config = double(assets: assets)
7
+ allow(Rails).to receive(:configuration).and_return(config)
8
+ end
9
+
10
+ describe ".file_name" do
11
+ subject do
12
+ Premailer::Rails::CSSLoaders::AssetPipelineLoader.file_name(asset)
13
+ end
14
+
15
+ context "when asset file path contains prefix" do
16
+ let(:asset) { '/assets/application.css' }
17
+ it { should == 'application.css' }
18
+ end
19
+
20
+ context "when asset file path contains fingerprint" do
21
+ let(:asset) { 'application-6776f581a4329e299531e1d52aa59832.css' }
22
+ it { should == 'application.css' }
23
+ end
24
+
25
+ context "when asset file page contains numbers, but not a fingerprint" do
26
+ let(:asset) { 'test/20130708152545-foo-bar.css' }
27
+ it { should == "test/20130708152545-foo-bar.css" }
28
+ end
29
+ end
30
+ end
@@ -1,5 +1,3 @@
1
- # coding: UTF-8
2
-
3
1
  require 'spec_helper'
4
2
 
5
3
  describe Premailer::Rails::CustomizedPremailer do
@@ -7,27 +5,28 @@ describe Premailer::Rails::CustomizedPremailer do
7
5
  next if adapter == :hpricot and RUBY_PLATFORM == 'java'
8
6
 
9
7
  context "when adapter is #{adapter}" do
10
- before { Premailer::Adapter.stubs(:use).returns(adapter) }
8
+ before { allow(Premailer::Adapter).to receive(:use).and_return(adapter) }
11
9
 
12
10
  describe '#to_plain_text' do
13
11
  it 'should include the text from the HTML part' do
14
12
  premailer =
15
13
  Premailer::Rails::CustomizedPremailer
16
14
  .new(Fixtures::Message::HTML_PART)
17
- premailer.to_plain_text.gsub(/\s/, ' ').strip
18
- .should == Fixtures::Message::TEXT_PART.gsub(/\s/, ' ').strip
15
+ expect(premailer.to_plain_text.gsub(/\s/, ' ').strip).to \
16
+ eq(Fixtures::Message::TEXT_PART.gsub(/\s/, ' ').strip)
19
17
  end
20
18
  end
21
19
 
22
20
  describe '#to_inline_css' do
21
+ let(:regex) { %r{<p style=("|')color: ?red;?\1>} }
22
+
23
23
  context 'when inline CSS block present' do
24
24
  it 'should return the HTML with the CSS inlined' do
25
- Premailer::Rails::CSSHelper
26
- .stubs(:css_for_doc)
27
- .returns('p { color: red; }')
25
+ allow(Premailer::Rails::CSSHelper).to \
26
+ receive(:css_for_doc).and_return('p { color: red; }')
28
27
  html = Fixtures::Message::HTML_PART
29
28
  premailer = Premailer::Rails::CustomizedPremailer.new(html)
30
- premailer.to_inline_css.should =~ /<p style=("|')color: ?red;?\1>/
29
+ expect(premailer.to_inline_css).to match(regex)
31
30
  end
32
31
  end
33
32
 
@@ -35,7 +34,7 @@ describe Premailer::Rails::CustomizedPremailer do
35
34
  it 'should return the HTML with the CSS inlined' do
36
35
  html = Fixtures::Message::HTML_PART_WITH_CSS
37
36
  premailer = Premailer::Rails::CustomizedPremailer.new(html)
38
- premailer.to_inline_css.should =~ /<p style=("|')color: ?red;?\1>/
37
+ expect(premailer.to_inline_css).to match(regex)
39
38
  end
40
39
  end
41
40
  end
@@ -44,21 +43,21 @@ describe Premailer::Rails::CustomizedPremailer do
44
43
 
45
44
  describe '.new' do
46
45
  it 'should extract the CSS' do
47
- Premailer::Rails::CSSHelper.expects(:css_for_doc)
46
+ expect(Premailer::Rails::CSSHelper).to receive(:css_for_doc)
48
47
  Premailer::Rails::CustomizedPremailer.new('some html')
49
48
  end
50
49
 
51
50
  it 'should pass on the configs' do
52
51
  Premailer::Rails.config = { foo: :bar }
53
52
  premailer = Premailer::Rails::CustomizedPremailer.new('some html')
54
- premailer.instance_variable_get(:'@options')[:foo].should == :bar
53
+ expect(premailer.instance_variable_get(:'@options')[:foo]).to eq(:bar)
55
54
  end
56
55
 
57
56
  it 'should not allow to override with_html_string' do
58
57
  Premailer::Rails.config = { with_html_string: false }
59
58
  premailer = Premailer::Rails::CustomizedPremailer.new('some html')
60
59
  options = premailer.instance_variable_get(:'@options')
61
- options[:with_html_string].should == true
60
+ expect(options[:with_html_string]).to eq(true)
62
61
  end
63
62
  end
64
63
  end