premailer-rails 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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