premailer-rails 1.9.5 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/test.yml +64 -0
  3. data/.gitignore +4 -0
  4. data/CHANGELOG.md +40 -0
  5. data/Gemfile +15 -11
  6. data/README.md +32 -37
  7. data/VERSION +1 -1
  8. data/examples/rails5/Gemfile +4 -0
  9. data/{example → examples/rails5}/Rakefile +1 -1
  10. data/{example → examples/rails5}/bin/rails +1 -1
  11. data/{example → examples/rails5}/config/application.rb +4 -1
  12. data/examples/rails5/config/boot.rb +3 -0
  13. data/{example → examples/rails5}/config/environment.rb +1 -1
  14. data/{example → examples/rails5}/config.ru +2 -1
  15. data/examples/rails6/.gitignore +16 -0
  16. data/examples/rails6/Gemfile +5 -0
  17. data/examples/rails6/README.md +10 -0
  18. data/examples/rails6/Rakefile +6 -0
  19. data/examples/rails6/app/assets/config/manifest.js +1 -0
  20. data/examples/rails6/app/assets/stylesheets/email.css +32 -0
  21. data/examples/rails6/app/mailers/example_mailer.rb +7 -0
  22. data/examples/rails6/app/views/example_mailer/test_message.html.erb +18 -0
  23. data/examples/rails6/bin/rails +4 -0
  24. data/examples/rails6/config/application.rb +15 -0
  25. data/examples/rails6/config/boot.rb +3 -0
  26. data/examples/rails6/config/environment.rb +5 -0
  27. data/examples/rails6/config/environments/development.rb +9 -0
  28. data/examples/rails6/config/environments/production.rb +9 -0
  29. data/examples/rails6/config/routes.rb +3 -0
  30. data/examples/rails6/config.ru +6 -0
  31. data/examples/rails6/test/mailers/previews/example_mailer_preview.rb +5 -0
  32. data/examples/rails7-propshaft/.gitignore +16 -0
  33. data/examples/rails7-propshaft/Gemfile +6 -0
  34. data/examples/rails7-propshaft/README.md +10 -0
  35. data/examples/rails7-propshaft/Rakefile +6 -0
  36. data/examples/rails7-propshaft/app/assets/stylesheets/email.css +32 -0
  37. data/examples/rails7-propshaft/app/mailers/example_mailer.rb +7 -0
  38. data/examples/rails7-propshaft/app/views/example_mailer/test_message.html.erb +18 -0
  39. data/examples/rails7-propshaft/bin/rails +4 -0
  40. data/examples/rails7-propshaft/config/application.rb +14 -0
  41. data/examples/rails7-propshaft/config/boot.rb +3 -0
  42. data/examples/rails7-propshaft/config/environment.rb +5 -0
  43. data/examples/rails7-propshaft/config/environments/development.rb +9 -0
  44. data/examples/rails7-propshaft/config/environments/production.rb +9 -0
  45. data/examples/rails7-propshaft/config/routes.rb +3 -0
  46. data/examples/rails7-propshaft/config.ru +6 -0
  47. data/examples/rails7-propshaft/test/mailers/previews/example_mailer_preview.rb +5 -0
  48. data/examples/rails7-sprockets/.gitignore +16 -0
  49. data/examples/rails7-sprockets/Gemfile +6 -0
  50. data/examples/rails7-sprockets/README.md +10 -0
  51. data/examples/rails7-sprockets/Rakefile +6 -0
  52. data/examples/rails7-sprockets/app/assets/config/manifest.js +1 -0
  53. data/examples/rails7-sprockets/app/assets/stylesheets/email.css +32 -0
  54. data/examples/rails7-sprockets/app/mailers/example_mailer.rb +7 -0
  55. data/examples/rails7-sprockets/app/views/example_mailer/test_message.html.erb +18 -0
  56. data/examples/rails7-sprockets/bin/rails +4 -0
  57. data/examples/rails7-sprockets/config/application.rb +14 -0
  58. data/examples/rails7-sprockets/config/boot.rb +3 -0
  59. data/examples/rails7-sprockets/config/environment.rb +5 -0
  60. data/examples/rails7-sprockets/config/environments/development.rb +9 -0
  61. data/examples/rails7-sprockets/config/environments/production.rb +9 -0
  62. data/examples/rails7-sprockets/config/routes.rb +3 -0
  63. data/examples/rails7-sprockets/config.ru +6 -0
  64. data/examples/rails7-sprockets/test/mailers/previews/example_mailer_preview.rb +5 -0
  65. data/lib/premailer/rails/css_helper.rb +32 -11
  66. data/lib/premailer/rails/css_loaders/asset_pipeline_loader.rb +16 -15
  67. data/lib/premailer/rails/css_loaders/file_system_loader.rb +24 -2
  68. data/lib/premailer/rails/css_loaders/network_loader.rb +2 -2
  69. data/lib/premailer/rails/css_loaders/propshaft_loader.rb +38 -0
  70. data/lib/premailer/rails/css_loaders.rb +1 -1
  71. data/lib/premailer/rails/customized_premailer.rb +4 -4
  72. data/lib/premailer/rails/hook.rb +2 -6
  73. data/lib/premailer/rails/railtie.rb +1 -1
  74. data/lib/premailer/rails.rb +2 -1
  75. data/premailer-rails.gemspec +4 -3
  76. data/spec/integration/css_helper_spec.rb +262 -129
  77. data/spec/integration/delivery_spec.rb +13 -0
  78. data/spec/integration/hook_spec.rb +36 -11
  79. data/spec/rails_app/app/assets/config/manifest.js +3 -0
  80. data/spec/rails_app/app/assets/stylesheets/application.css +3 -0
  81. data/spec/rails_app/app/mailers/application_mailer.rb +4 -0
  82. data/spec/rails_app/app/mailers/welcome_mailer.rb +6 -0
  83. data/spec/rails_app/app/views/layouts/mailer.html.erb +11 -0
  84. data/spec/rails_app/app/views/welcome_mailer/welcome_email.html.erb +1 -0
  85. data/spec/rails_app/config/application.rb +19 -0
  86. data/spec/rails_app/config/boot.rb +5 -0
  87. data/spec/rails_app/config/environment.rb +2 -0
  88. data/spec/rails_app/config/environments/test.rb +10 -0
  89. data/spec/rails_app/config/initializers/assets.rb +1 -0
  90. data/spec/rails_app/config/routes.rb +3 -0
  91. data/spec/rails_app/config.ru +5 -0
  92. data/spec/rails_app/log/.keep +0 -0
  93. data/spec/rails_app/tmp/.keep +0 -0
  94. data/spec/spec_helper.rb +3 -17
  95. data/spec/support/fixtures/message.rb +40 -0
  96. data/spec/unit/css_loaders/asset_pipeline_loader_spec.rb +44 -32
  97. data/spec/unit/css_loaders/file_system_loader_spec.rb +37 -0
  98. data/spec/unit/css_loaders/network_loader_spec.rb +1 -1
  99. data/spec/unit/css_loaders/propshaft_loader_spec.rb +57 -0
  100. data/spec/unit/customized_premailer_spec.rb +32 -40
  101. metadata +121 -81
  102. data/.coveralls.yml +0 -1
  103. data/.travis.yml +0 -22
  104. data/example/Gemfile +0 -10
  105. data/example/config/boot.rb +0 -3
  106. data/example/config/secrets.yml +0 -2
  107. data/lib/premailer/rails/css_loaders/cache_loader.rb +0 -29
  108. data/spec/integration/hook_registration_spec.rb +0 -11
  109. data/spec/support/stubs/action_mailer.rb +0 -5
  110. data/spec/support/stubs/rails.rb +0 -51
  111. /data/{example → examples/rails5}/.gitignore +0 -0
  112. /data/{example → examples/rails5}/README.md +0 -0
  113. /data/{example → examples/rails5}/app/assets/stylesheets/email.css +0 -0
  114. /data/{example → examples/rails5}/app/mailers/example_mailer.rb +0 -0
  115. /data/{example → examples/rails5}/app/views/example_mailer/test_message.html.erb +0 -0
  116. /data/{example → examples/rails5}/config/environments/development.rb +0 -0
  117. /data/{example → examples/rails5}/config/environments/production.rb +0 -0
  118. /data/{example → examples/rails5}/config/initializers/assets.rb +0 -0
  119. /data/{example → examples/rails5}/config/routes.rb +0 -0
  120. /data/{example → examples/rails5}/test/mailers/previews/example_mailer_preview.rb +0 -0
@@ -1,186 +1,319 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Premailer::Rails::CSSHelper do
4
- [ :Nokogiri, :Hpricot ].each do |adapter|
5
- next if adapter == :Hpricot and RUBY_PLATFORM == 'java'
4
+ # Reset the CSS cache:
5
+ after do
6
+ Premailer::Rails::CSSHelper.cache = {}
7
+ end
6
8
 
7
- context "when adapter is #{adapter}" do
8
- # Reset the CSS cache:
9
- after do
10
- Premailer::Rails::CSSLoaders::CacheLoader.clear!
11
- end
9
+ def css_for_url(path)
10
+ Premailer::Rails::CSSHelper.css_for_url(path)
11
+ end
12
12
 
13
- def css_for_url(path)
14
- Premailer::Rails::CSSHelper.css_for_url(path)
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
+ path = "#{Rails.root}/#{path}"
19
+ allow(File).to receive(:file?).with(path).and_return(true)
20
+ expect(File).to receive(:read).with(path).and_return(content)
21
+ end
22
+
23
+ describe '#css_for_doc' do
24
+ let(:html) { Fixtures::HTML.with_css_links(*files) }
25
+ let(:doc) { Nokogiri(html) }
26
+
27
+ context 'when HTML contains linked CSS files' do
28
+ let(:files) { %w[ stylesheets/base.css stylesheets/font.css ] }
29
+
30
+ it 'returns the content of both files concatenated' do
31
+ allow(Premailer::Rails::CSSHelper).to \
32
+ receive(:css_for_url)
33
+ .with('http://example.com/stylesheets/base.css')
34
+ .and_return('content of base.css')
35
+ allow(Premailer::Rails::CSSHelper).to \
36
+ receive(:css_for_url)
37
+ .with('http://example.com/stylesheets/font.css')
38
+ .and_return('content of font.css')
39
+
40
+ expect(css_for_doc(doc)).to eq("content of base.css\ncontent of font.css")
15
41
  end
42
+ end
16
43
 
17
- def css_for_doc(doc)
18
- Premailer::Rails::CSSHelper.css_for_doc(doc)
44
+ context 'when HTML contains ignored links' do
45
+ let(:files) { ['ignore.css', 'data-premailer' => 'ignore'] }
46
+
47
+ it 'ignores links' do
48
+ expect(Premailer::Rails::CSSHelper).to_not receive(:css_for_url)
49
+ css_for_doc(doc)
19
50
  end
51
+ end
52
+ end
20
53
 
21
- def expect_file(path, content='file content')
22
- allow(File).to receive(:file?).with(path).and_return(true)
23
- expect(File).to receive(:read).with(path).and_return(content)
54
+ describe '#css_for_url' do
55
+ context 'when path is a url' do
56
+ it 'loads the CSS at the local path' do
57
+ expect_file('public/stylesheets/base.css')
58
+
59
+ css_for_url('http://example.com/stylesheets/base.css?test')
24
60
  end
61
+ end
25
62
 
26
- describe '#css_for_doc' do
27
- let(:html) { Fixtures::HTML.with_css_links(*files) }
28
- let(:doc) { send(adapter, html) }
63
+ context 'when path is a relative url' do
64
+ it 'loads the CSS at the local path' do
65
+ expect_file('public/stylesheets/base.css')
66
+ css_for_url('/stylesheets/base.css?test')
67
+ end
68
+ end
29
69
 
30
- context 'when HTML contains linked CSS files' do
31
- let(:files) { %w[ stylesheets/base.css stylesheets/font.css ] }
70
+ context 'when cache is enabled' do
71
+ before do
72
+ allow(Premailer::Rails::CSSHelper).to receive(:cache_enabled?).and_return(true)
73
+ end
32
74
 
33
- it 'returns the content of both files concatenated' do
34
- allow(Premailer::Rails::CSSHelper).to \
35
- receive(:css_for_url)
36
- .with('http://example.com/stylesheets/base.css')
37
- .and_return('content of base.css')
38
- allow(Premailer::Rails::CSSHelper).to \
39
- receive(:css_for_url)
40
- .with('http://example.com/stylesheets/font.css')
41
- .and_return('content of font.css')
75
+ context 'when file is cached' do
76
+ it 'returns the cached value' do
77
+ Premailer::Rails::CSSHelper.cache['http://example.com/stylesheets/base.css'] = 'content of base.css'
42
78
 
43
- expect(css_for_doc(doc)).to eq("content of base.css\ncontent of font.css")
44
- end
79
+ expect(css_for_url('http://example.com/stylesheets/base.css')).to \
80
+ eq('content of base.css')
45
81
  end
82
+ end
83
+ end
46
84
 
47
- context 'when HTML contains ignored links' do
48
- let(:files) { ['ignore.css', 'data-premailer' => 'ignore'] }
85
+ context 'when cache is disabled' do
86
+ before do
87
+ allow(Premailer::Rails::CSSHelper).to receive(:cache_enabled?).and_return(false)
88
+ end
49
89
 
50
- it 'ignores links' do
51
- expect(Premailer::Rails::CSSHelper).to_not receive(:css_for_url)
52
- css_for_doc(doc)
53
- end
54
- end
90
+ it 'does not return cached values' do
91
+ Premailer::Rails::CSSHelper.cache['http://example.com/stylesheets/base.css'] = 'cached content'
92
+ content = 'new content of base.css'
93
+ expect_file('public/stylesheets/base.css', content)
94
+
95
+ expect(css_for_url('http://example.com/stylesheets/base.css')).to eq(content)
55
96
  end
97
+ end
56
98
 
57
- describe '#css_for_url' do
58
- context 'when path is a url' do
59
- it 'loads the CSS at the local path' do
60
- expect_file('public/stylesheets/base.css')
99
+ if defined?(::Sprockets)
100
+ context 'when Rails asset pipeline is used' do
101
+ before do
102
+ allow(Rails.configuration)
103
+ .to receive(:assets).and_return(double(prefix: '/assets'))
104
+ allow(Rails.configuration)
105
+ .to receive(:relative_url_root).and_return(nil)
106
+ end
61
107
 
62
- css_for_url('http://example.com/stylesheets/base.css?test')
108
+ context 'and a precompiled file exists' do
109
+ it 'returns that file' do
110
+ path = '/assets/email-digest.css'
111
+ content = 'read from file'
112
+ expect_file("public#{path}", content)
113
+ expect(css_for_url(path)).to eq(content)
63
114
  end
64
115
  end
65
116
 
66
- context 'when path is a relative url' do
67
- it 'loads the CSS at the local path' do
68
- expect_file('public/stylesheets/base.css')
69
- css_for_url('/stylesheets/base.css?test')
117
+ context "when find_sources raises TypeError" do
118
+ let(:response) { 'content of base.css' }
119
+ let(:uri) { URI('http://example.com/assets/base.css') }
120
+
121
+ it "falls back to Net::HTTP" do
122
+ expect(Rails.application.assets_manifest).to \
123
+ receive(:find_sources)
124
+ .with('base.css')
125
+ .and_raise(TypeError)
126
+
127
+ allow(Net::HTTP).to \
128
+ receive(:get)
129
+ .with(uri, { 'Accept' => 'text/css' })
130
+ .and_return(response)
131
+ expect(css_for_url('http://example.com/assets/base.css')).to \
132
+ eq(response)
70
133
  end
71
134
  end
72
135
 
73
- context 'when file is cached' do
74
- it 'returns the cached value' do
75
- Premailer::Rails::CSSLoaders::CacheLoader.store(
76
- 'http://example.com/stylesheets/base.css',
77
- 'content of base.css'
78
- )
136
+ context "when find_sources raises Errno::ENOENT" do
137
+ let(:response) { 'content of base.css' }
138
+ let(:uri) { URI('http://example.com/assets/base.css') }
139
+
140
+ it "falls back to Net::HTTP" do
141
+ expect(Rails.application.assets_manifest).to \
142
+ receive(:find_sources)
143
+ .with('base.css')
144
+ .and_raise(Errno::ENOENT)
79
145
 
80
- expect(css_for_url('http://example.com/stylesheets/base.css')).to \
81
- eq('content of base.css')
146
+ allow(Net::HTTP).to \
147
+ receive(:get)
148
+ .with(uri, { 'Accept' => 'text/css' })
149
+ .and_return(response)
150
+ expect(css_for_url('http://example.com/assets/base.css')).to \
151
+ eq(response)
82
152
  end
83
153
  end
84
154
 
85
- context 'when in development mode' do
86
- it 'does not return cached values' do
87
- Premailer::Rails::CSSLoaders::CacheLoader.store(
88
- 'http://example.com/stylesheets/base.css',
89
- 'cached content of base.css'
90
- )
91
- content = 'new content of base.css'
92
- expect_file('public/stylesheets/base.css', content)
93
- allow(Rails.env).to receive(:development?).and_return(true)
94
-
95
- expect(css_for_url('http://example.com/stylesheets/base.css')).to eq(content)
96
- end
155
+ it 'returns the content of the file compiled by Rails' do
156
+ expect(Rails.application.assets_manifest).to \
157
+ receive(:find_sources)
158
+ .with('base.css')
159
+ .and_return(['content of base.css'])
160
+
161
+ expect(css_for_url('http://example.com/assets/base.css')).to \
162
+ eq('content of base.css')
97
163
  end
98
164
 
99
- context 'when Rails asset pipeline is used' do
165
+ it 'returns same file when path contains file fingerprint' do
166
+ expect(Rails.application.assets_manifest).to \
167
+ receive(:find_sources)
168
+ .with('base.css')
169
+ .and_return(['content of base.css'])
170
+
171
+ expect(css_for_url(
172
+ 'http://example.com/assets/base-089e35bd5d84297b8d31ad552e433275.css'
173
+ )).to eq('content of base.css')
174
+ end
175
+
176
+ context 'when asset can not be found' do
177
+ let(:response) { 'content of base.css' }
178
+ let(:path) { '/assets/base-089e35bd5d84297b8d31ad552e433275.css' }
179
+ let(:url) { "http://assets.example.com#{path}" }
180
+ let(:asset_host) { 'http://assets.example.com' }
181
+
100
182
  before do
101
- allow(Rails.configuration)
102
- .to receive(:assets).and_return(double(prefix: '/assets'))
103
- allow(Rails.configuration)
104
- .to receive(:relative_url_root).and_return(nil)
183
+ allow(Rails.application.assets_manifest).to \
184
+ receive(:find_sources).and_return([])
185
+
186
+ config = double(asset_host: asset_host)
187
+ allow(Rails.configuration).to \
188
+ receive(:action_controller).and_return(config)
189
+
190
+ allow(Net::HTTP).to \
191
+ receive(:get)
192
+ .with(URI(url), { 'Accept' => 'text/css' })
193
+ .and_return(response)
105
194
  end
106
195
 
107
- context 'and a precompiled file exists' do
108
- it 'returns that file' do
109
- path = '/assets/email-digest.css'
110
- content = 'read from file'
111
- expect_file("public#{path}", content)
112
- expect(css_for_url(path)).to eq(content)
113
- end
196
+ it 'requests the file' do
197
+ expect(css_for_url(url)).to eq('content of base.css')
114
198
  end
115
199
 
116
- it 'returns the content of the file compiled by Rails' do
117
- expect(Rails.application.assets).to \
118
- receive(:find_asset)
119
- .with('base.css')
120
- .and_return(double(to_s: 'content of base.css'))
200
+ context 'when file url does not include the host' do
201
+ it 'requests the file using the asset host as host' do
202
+ expect(css_for_url(path)).to eq('content of base.css')
203
+ end
121
204
 
122
- expect(css_for_url('http://example.com/assets/base.css')).to \
123
- eq('content of base.css')
124
- end
205
+ context 'and the asset host uses protocol relative scheme' do
206
+ let(:asset_host) { '//assets.example.com' }
125
207
 
126
- it 'returns same file when path contains file fingerprint' do
127
- expect(Rails.application.assets).to \
128
- receive(:find_asset)
129
- .with('base.css')
130
- .and_return(double(to_s: 'content of base.css'))
208
+ it 'requests the file using http as the scheme' do
209
+ expect(css_for_url(path)).to eq('content of base.css')
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
215
+ elsif defined?(::Propshaft)
216
+ context 'when Propshaft is used' do
217
+ before do
218
+ allow(Rails.configuration)
219
+ .to receive(:assets).and_return(double(prefix: '/assets'))
220
+ allow(Rails.configuration)
221
+ .to receive(:relative_url_root).and_return(nil)
222
+ end
131
223
 
132
- expect(css_for_url(
133
- 'http://example.com/assets/base-089e35bd5d84297b8d31ad552e433275.css'
134
- )).to eq('content of base.css')
224
+ context 'and a precompiled file exists' do
225
+ it 'returns that file' do
226
+ path = '/assets/email-digest.css'
227
+ content = 'read from file'
228
+ expect_file("public#{path}", content)
229
+ expect(css_for_url(path)).to eq(content)
135
230
  end
231
+ end
136
232
 
137
- context 'when asset can not be found' do
138
- let(:response) { 'content of base.css' }
139
- let(:path) { '/assets/base-089e35bd5d84297b8d31ad552e433275.css' }
140
- let(:url) { "http://assets.example.com#{path}" }
141
- let(:asset_host) { 'http://assets.example.com' }
233
+ it 'returns the content of the file compiled by Propshaft' do
234
+ asset = double()
142
235
 
143
- before do
144
- allow(Rails.application.assets).to \
145
- receive(:find_asset).and_return(nil)
236
+ expect(Rails.application.assets.load_path).to \
237
+ receive(:find)
238
+ .with('base.css')
239
+ .and_return(asset)
146
240
 
147
- config = double(asset_host: asset_host)
148
- allow(Rails.configuration).to \
149
- receive(:action_controller).and_return(config)
241
+ expect(Rails.application.assets.compilers).to \
242
+ receive(:compile)
243
+ .with(asset)
244
+ .and_return('content of base.css')
150
245
 
151
- uri_satisfaction = satisfy { |uri| uri.to_s == url }
152
- allow(Net::HTTP).to \
153
- receive(:get).with(uri_satisfaction).and_return(response)
154
- end
246
+ expect(css_for_url('http://example.com/assets/base.css')).to \
247
+ eq('content of base.css')
248
+ end
155
249
 
156
- it 'requests the file' do
157
- expect(css_for_url(url)).to eq('content of base.css')
158
- end
250
+ it 'returns same file when path contains file fingerprint' do
251
+ asset = double()
159
252
 
160
- context 'when file url does not include the host' do
161
- it 'requests the file using the asset host as host' do
162
- expect(css_for_url(path)).to eq('content of base.css')
163
- end
253
+ expect(Rails.application.assets.load_path).to \
254
+ receive(:find)
255
+ .with('base.css')
256
+ .and_return(asset)
257
+
258
+ expect(Rails.application.assets.compilers).to \
259
+ receive(:compile)
260
+ .with(asset)
261
+ .and_return('content of base.css')
262
+
263
+ expect(css_for_url(
264
+ 'http://example.com/assets/base-089e35bd5d84297b8d31ad552e433275.css'
265
+ )).to eq('content of base.css')
266
+ end
267
+
268
+ context 'when asset can not be found' do
269
+ let(:response) { 'content of base.css' }
270
+ let(:path) { '/assets/base-089e35bd5d84297b8d31ad552e433275.css' }
271
+ let(:url) { "http://assets.example.com#{path}" }
272
+ let(:asset_host) { 'http://assets.example.com' }
273
+
274
+ before do
275
+ expect(Rails.application.assets.load_path).to \
276
+ receive(:find)
277
+ .with('base.css')
278
+ .and_return(nil)
279
+
280
+ config = double(asset_host: asset_host)
281
+ allow(Rails.configuration).to \
282
+ receive(:action_controller).and_return(config)
283
+
284
+ allow(Net::HTTP).to \
285
+ receive(:get)
286
+ .with(URI(url), { 'Accept' => 'text/css' })
287
+ .and_return(response)
288
+ end
289
+
290
+ it 'requests the file' do
291
+ expect(css_for_url(url)).to eq('content of base.css')
292
+ end
293
+
294
+ context 'when file url does not include the host' do
295
+ it 'requests the file using the asset host as host' do
296
+ expect(css_for_url(path)).to eq('content of base.css')
297
+ end
164
298
 
165
- context 'and the asset host uses protocol relative scheme' do
166
- let(:asset_host) { '//assets.example.com' }
299
+ context 'and the asset host uses protocol relative scheme' do
300
+ let(:asset_host) { '//assets.example.com' }
167
301
 
168
- it 'requests the file using http as the scheme' do
169
- expect(css_for_url(path)).to eq('content of base.css')
170
- end
302
+ it 'requests the file using http as the scheme' do
303
+ expect(css_for_url(path)).to eq('content of base.css')
171
304
  end
172
305
  end
173
306
  end
174
307
  end
308
+ end
309
+ end
175
310
 
176
- context 'when static stylesheets are used' do
177
- it 'returns the content of the static file' do
178
- content = 'content of base.css'
179
- expect_file('public/stylesheets/base.css', content)
180
- loaded_content = css_for_url('http://example.com/stylesheets/base.css')
181
- expect(loaded_content).to eq(content)
182
- end
183
- end
311
+ context 'when static stylesheets are used' do
312
+ it 'returns the content of the static file' do
313
+ content = 'content of base.css'
314
+ expect_file('public/stylesheets/base.css', content)
315
+ loaded_content = css_for_url('http://example.com/stylesheets/base.css')
316
+ expect(loaded_content).to eq(content)
184
317
  end
185
318
  end
186
319
  end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'ActionMailer::Base delivery' do
4
+ it 'delivers email with inlined CSS' do
5
+ WelcomeMailer.welcome_email("world").deliver_now
6
+
7
+ mail = ActionMailer::Base.deliveries.last
8
+ expect(mail).to be_present
9
+ body = mail.html_part.body.to_s
10
+ expect(body).to be_present
11
+ expect(body).to include(%{<p style="font-size: 12px;">Hello world</p>})
12
+ end
13
+ end
@@ -6,7 +6,7 @@ describe Premailer::Rails::Hook do
6
6
  end
7
7
 
8
8
  def body_content(message)
9
- Nokogiri::HTML(message.html_string).at('body').content
9
+ Nokogiri::HTML(message.html_string).at('body').content.gsub("\r\n", "\n")
10
10
  end
11
11
 
12
12
  class Mail::Message
@@ -47,18 +47,31 @@ describe Premailer::Rails::Hook do
47
47
  expect(processed_message.parts).to match_array(expected_parts)
48
48
  end
49
49
 
50
- describe 'when the content-transfer-encoding is set' do
51
- before { message.content_transfer_encoding = 'quoted-printable' }
50
+ it 'does not screw up the text by maintaining the original body encoding' do
51
+ raw_msg = Fixtures::Message.latin_message
52
+ processed_msg = Fixtures::Message.latin_message
53
+ run_hook(processed_msg)
54
+ expect(body_content(processed_msg)).to eq(body_content(raw_msg))
52
55
 
53
- it 'should maintain the value' do
54
- expect(processed_message.parts.first.content_transfer_encoding).to \
55
- eq 'quoted-printable'
56
- expect(processed_message.parts.last.content_transfer_encoding).to \
57
- eq 'quoted-printable'
58
- end
56
+ raw_msg = Fixtures::Message.non_latin_message
57
+ processed_msg = Fixtures::Message.non_latin_message
58
+ run_hook(processed_msg)
59
+ expect(body_content(processed_msg)).to eq(body_content(raw_msg))
60
+
61
+ raw_msg = Fixtures::Message.greek_message
62
+ processed_msg = Fixtures::Message.greek_message
63
+ run_hook(processed_msg)
64
+ expect(body_content(processed_msg)).to eq(body_content(raw_msg))
65
+
66
+ raw_msg = Fixtures::Message.dash_message
67
+ processed_msg = Fixtures::Message.dash_message
68
+ run_hook(processed_msg)
69
+ expect(body_content(processed_msg)).to eq(body_content(raw_msg))
59
70
  end
60
71
 
61
- it 'does not screw up the text by maintaining the original body encoding' do
72
+ it 'supports US-ASCII output' do
73
+ Premailer::Rails.config.merge!(output_encoding: 'US-ASCII')
74
+
62
75
  raw_msg = Fixtures::Message.latin_message
63
76
  processed_msg = Fixtures::Message.latin_message
64
77
  run_hook(processed_msg)
@@ -68,6 +81,18 @@ describe Premailer::Rails::Hook do
68
81
  processed_msg = Fixtures::Message.non_latin_message
69
82
  run_hook(processed_msg)
70
83
  expect(body_content(processed_msg)).to eq(body_content(raw_msg))
84
+
85
+ raw_msg = Fixtures::Message.greek_message
86
+ processed_msg = Fixtures::Message.greek_message
87
+ run_hook(processed_msg)
88
+ expect(body_content(processed_msg)).to eq(body_content(raw_msg))
89
+
90
+ raw_msg = Fixtures::Message.dash_message
91
+ processed_msg = Fixtures::Message.dash_message
92
+ run_hook(processed_msg)
93
+ expect(body_content(processed_msg)).to eq(body_content(raw_msg))
94
+ ensure
95
+ Premailer::Rails.config.delete(:output_encoding)
71
96
  end
72
97
 
73
98
  it 'generates a text part from the html' do
@@ -91,7 +116,7 @@ describe Premailer::Rails::Hook do
91
116
 
92
117
  it 'does not replace any message part' do
93
118
  expect { run_hook(message) }.to_not \
94
- change { message.all_parts.map(&:content_type) }
119
+ change { message.all_parts.map(&:content_type).sort }
95
120
  end
96
121
  end
97
122
 
@@ -0,0 +1,3 @@
1
+ //= link_tree ../images
2
+ //= link_directory ../javascripts .js
3
+ //= link_directory ../stylesheets .css
@@ -0,0 +1,3 @@
1
+ p {
2
+ font-size: 12px;
3
+ }
@@ -0,0 +1,4 @@
1
+ class ApplicationMailer < ActionMailer::Base
2
+ default from: 'from@example.com'
3
+ layout 'mailer'
4
+ end
@@ -0,0 +1,6 @@
1
+ class WelcomeMailer < ApplicationMailer
2
+ def welcome_email(greeting)
3
+ @greeting = greeting
4
+ mail to: "example@example.com"
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
+ <link rel="stylesheet" href="/assets/application.css"/>
6
+ </head>
7
+
8
+ <body>
9
+ <%= yield %>
10
+ </body>
11
+ </html>
@@ -0,0 +1 @@
1
+ <p>Hello <%= @greeting %></p>
@@ -0,0 +1,19 @@
1
+ require_relative 'boot'
2
+
3
+ require "action_controller/railtie"
4
+ require "action_mailer/railtie"
5
+ require "action_view/railtie"
6
+
7
+ begin
8
+ require "sprockets/railtie"
9
+ rescue LoadError
10
+ end
11
+
12
+ require "rails/test_unit/railtie"
13
+
14
+ Bundler.require(*Rails.groups)
15
+
16
+ module Dummy
17
+ class Application < Rails::Application
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ # Set up gems listed in the Gemfile.
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__)
3
+
4
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
5
+ $LOAD_PATH.unshift File.expand_path('../../../lib', __dir__)
@@ -0,0 +1,2 @@
1
+ require_relative 'application'
2
+ Rails.application.initialize!
@@ -0,0 +1,10 @@
1
+ Rails.application.configure do
2
+ config.cache_classes = true
3
+ config.eager_load = false
4
+ config.consider_all_requests_local = true
5
+ config.action_controller.perform_caching = false
6
+ config.action_dispatch.show_exceptions = false
7
+ config.action_controller.allow_forgery_protection = false
8
+ config.action_mailer.delivery_method = :test
9
+ config.active_support.deprecation = :stderr
10
+ end
@@ -0,0 +1 @@
1
+ Rails.application.config.assets.version = '1.0'
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ root 'application#main'
3
+ end
@@ -0,0 +1,5 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require_relative 'config/environment'
4
+
5
+ run Rails.application
File without changes
File without changes