premailer-rails-revived 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.github/workflows/build.yml +43 -0
  4. data/.gitignore +8 -0
  5. data/.rspec +2 -0
  6. data/CHANGELOG.md +165 -0
  7. data/Gemfile +28 -0
  8. data/LICENSE +14 -0
  9. data/README.md +180 -0
  10. data/Rakefile +7 -0
  11. data/VERSION +1 -0
  12. data/example/.gitignore +16 -0
  13. data/example/Gemfile +10 -0
  14. data/example/README.md +10 -0
  15. data/example/Rakefile +6 -0
  16. data/example/app/assets/stylesheets/email.css +32 -0
  17. data/example/app/mailers/example_mailer.rb +7 -0
  18. data/example/app/views/example_mailer/test_message.html.erb +18 -0
  19. data/example/bin/rails +4 -0
  20. data/example/config/application.rb +12 -0
  21. data/example/config/boot.rb +3 -0
  22. data/example/config/environment.rb +5 -0
  23. data/example/config/environments/development.rb +9 -0
  24. data/example/config/environments/production.rb +9 -0
  25. data/example/config/initializers/assets.rb +2 -0
  26. data/example/config/routes.rb +3 -0
  27. data/example/config/secrets.yml +2 -0
  28. data/example/config.ru +4 -0
  29. data/example/test/mailers/previews/example_mailer_preview.rb +5 -0
  30. data/lib/premailer/rails/css_helper.rb +70 -0
  31. data/lib/premailer/rails/css_loaders/asset_pipeline_loader.rb +36 -0
  32. data/lib/premailer/rails/css_loaders/file_system_loader.rb +37 -0
  33. data/lib/premailer/rails/css_loaders/network_loader.rb +39 -0
  34. data/lib/premailer/rails/css_loaders/propshaft_loader.rb +33 -0
  35. data/lib/premailer/rails/css_loaders.rb +6 -0
  36. data/lib/premailer/rails/customized_premailer.rb +20 -0
  37. data/lib/premailer/rails/hook.rb +140 -0
  38. data/lib/premailer/rails/railtie.rb +9 -0
  39. data/lib/premailer/rails/version.rb +7 -0
  40. data/lib/premailer/rails.rb +31 -0
  41. data/premailer-rails.gemspec +32 -0
  42. data/spec/integration/css_helper_spec.rb +192 -0
  43. data/spec/integration/delivery_spec.rb +13 -0
  44. data/spec/integration/hook_spec.rb +163 -0
  45. data/spec/rails_app/app/assets/config/manifest.js +3 -0
  46. data/spec/rails_app/app/assets/stylesheets/application.css +3 -0
  47. data/spec/rails_app/app/mailers/application_mailer.rb +4 -0
  48. data/spec/rails_app/app/mailers/welcome_mailer.rb +6 -0
  49. data/spec/rails_app/app/views/layouts/mailer.html.erb +11 -0
  50. data/spec/rails_app/app/views/welcome_mailer/welcome_email.html.erb +1 -0
  51. data/spec/rails_app/config/application.rb +16 -0
  52. data/spec/rails_app/config/boot.rb +5 -0
  53. data/spec/rails_app/config/environment.rb +2 -0
  54. data/spec/rails_app/config/environments/test.rb +10 -0
  55. data/spec/rails_app/config/routes.rb +3 -0
  56. data/spec/rails_app/config.ru +5 -0
  57. data/spec/rails_app/log/.keep +0 -0
  58. data/spec/rails_app/tmp/.keep +0 -0
  59. data/spec/spec_helper.rb +23 -0
  60. data/spec/support/fixtures/html.rb +38 -0
  61. data/spec/support/fixtures/message.rb +182 -0
  62. data/spec/unit/css_loaders/asset_pipeline_loader_spec.rb +57 -0
  63. data/spec/unit/css_loaders/file_system_loader_spec.rb +37 -0
  64. data/spec/unit/css_loaders/network_loader_spec.rb +58 -0
  65. data/spec/unit/css_loaders/propshaft_loader_spec.rb +57 -0
  66. data/spec/unit/customized_premailer_spec.rb +64 -0
  67. data/spec/unit/premailer_rails_spec.rb +19 -0
  68. metadata +233 -0
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe Premailer::Rails::Hook do
4
+ def run_hook(message)
5
+ Premailer::Rails::Hook.perform(message)
6
+ end
7
+
8
+ def body_content(message)
9
+ Nokogiri::HTML(message.html_string).at('body').content.gsub("\r\n", "\n")
10
+ end
11
+
12
+ class Mail::Message
13
+ def html_string
14
+ (html_part || self).body.to_s
15
+ end
16
+ end
17
+
18
+ let(:message) { Fixtures::Message.with_parts(:html) }
19
+ let(:processed_message) { run_hook(message) }
20
+
21
+ describe '.delivering_email' do
22
+ it 'is an alias to .perform' do
23
+ method = described_class.method(:delivering_email)
24
+ expected_method = described_class.method(:perform)
25
+
26
+ expect(method).to eq expected_method
27
+ end
28
+ end
29
+
30
+ describe '.previewing_email' do
31
+ it 'is an alias to .perform' do
32
+ method = described_class.method(:previewing_email)
33
+ expected_method = described_class.method(:perform)
34
+
35
+ expect(method).to eq expected_method
36
+ end
37
+ end
38
+
39
+ it 'inlines the CSS' do
40
+ expect { run_hook(message) }.to \
41
+ change { message.html_string.include?("<p style=") }
42
+ end
43
+
44
+ it 'replaces the html part with an alternative part containing text and html parts' do
45
+ expect(processed_message.content_type).to include('multipart/alternative')
46
+ expected_parts = [message.html_part, message.text_part]
47
+ expect(processed_message.parts).to match_array(expected_parts)
48
+ end
49
+
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))
55
+
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))
70
+ end
71
+
72
+ it 'supports US-ASCII output' do
73
+ Premailer::Rails.config.merge!(output_encoding: 'US-ASCII')
74
+
75
+ raw_msg = Fixtures::Message.latin_message
76
+ processed_msg = Fixtures::Message.latin_message
77
+ run_hook(processed_msg)
78
+ expect(body_content(processed_msg)).to eq(body_content(raw_msg))
79
+
80
+ raw_msg = Fixtures::Message.non_latin_message
81
+ processed_msg = Fixtures::Message.non_latin_message
82
+ run_hook(processed_msg)
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)
96
+ end
97
+
98
+ it 'generates a text part from the html' do
99
+ expect { run_hook(message) }.to change(message, :text_part)
100
+ end
101
+
102
+ context 'when message contains no html' do
103
+ let(:message) { Fixtures::Message.with_parts(:text) }
104
+
105
+ it 'does not modify the message' do
106
+ expect { run_hook(message) }.to_not change(message, :html_string)
107
+ end
108
+ end
109
+
110
+ context 'when message also contains a text part' do
111
+ let(:message) { Fixtures::Message.with_parts(:html, :text) }
112
+
113
+ it 'does not generate a text part' do
114
+ expect { run_hook(message) }.to_not change(message, :text_part)
115
+ end
116
+
117
+ it 'does not replace any message part' do
118
+ expect { run_hook(message) }.to_not \
119
+ change { message.all_parts.map(&:content_type).sort }
120
+ end
121
+ end
122
+
123
+ context 'when text generation is disabled' do
124
+ it 'does not generate a text part' do
125
+ begin
126
+ Premailer::Rails.config[:generate_text_part] = false
127
+
128
+ expect { run_hook(message) }.to_not change(message, :text_part)
129
+ ensure
130
+ Premailer::Rails.config[:generate_text_part] = true
131
+ end
132
+ end
133
+ end
134
+
135
+ context 'when message also contains an attachment' do
136
+ let(:message) { Fixtures::Message.with_parts(:html, :attachment) }
137
+ it 'does not mess with it' do
138
+ expect(message.content_type).to include 'multipart/mixed'
139
+ expect(message.parts.first.content_type).to include 'text/html'
140
+ expect(message.parts.last.content_type).to include 'image/png'
141
+
142
+ expect(processed_message.content_type).to include 'multipart/mixed'
143
+ expect(processed_message.parts.first.content_type).to \
144
+ include 'multipart/alternative'
145
+ expect(processed_message.parts.last.content_type).to include 'image/png'
146
+ end
147
+ end
148
+
149
+ context 'when message has a skip premailer header' do
150
+ before do
151
+ message.header[:skip_premailer] = true
152
+ end
153
+
154
+ it 'does not change the message body' do
155
+ expect { run_hook(message) }.to_not change(message, :body)
156
+ end
157
+
158
+ it 'removes that header' do
159
+ expect { run_hook(message) }.to \
160
+ change { message.header[:skip_premailer].nil? }.to(true)
161
+ end
162
+ end
163
+ end
@@ -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,16 @@
1
+ require_relative 'boot'
2
+
3
+ require "action_controller/railtie"
4
+ require "action_mailer/railtie"
5
+ require "action_view/railtie"
6
+ if ENV.fetch("ASSETS_GEM", "sprockets-rails") == "sprockets-rails"
7
+ require "sprockets/railtie"
8
+ end
9
+ require "rails/test_unit/railtie"
10
+
11
+ Bundler.require(*Rails.groups)
12
+
13
+ module Dummy
14
+ class Application < Rails::Application
15
+ end
16
+ 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,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
@@ -0,0 +1,23 @@
1
+ if RUBY_ENGINE == 'ruby'
2
+ if ENV['CI']
3
+ require 'coveralls'
4
+ Coveralls::Output.silent = true
5
+ Coveralls.wear! do
6
+ add_filter 'spec/'
7
+ end
8
+ else
9
+ require 'simplecov'
10
+ SimpleCov.start
11
+ end
12
+ end
13
+
14
+ # Configure Rails Environment
15
+ ENV["RAILS_ENV"] = "test"
16
+ require File.expand_path("../../spec/rails_app/config/environment.rb", __FILE__)
17
+
18
+ require 'support/fixtures/message'
19
+ require 'support/fixtures/html'
20
+
21
+ require 'premailer/rails'
22
+
23
+ require 'nokogiri'
@@ -0,0 +1,38 @@
1
+ module Fixtures
2
+ module HTML
3
+ extend self
4
+
5
+ TEMPLATE = <<-HTML
6
+ <html>
7
+ <head>
8
+ %s
9
+ </head>
10
+ <body>
11
+ <p>
12
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
13
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
14
+ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
15
+ commodo consequat.
16
+ </p>
17
+ </body>
18
+ </html>
19
+ HTML
20
+
21
+ LINK = "<link rel='stylesheet' %s />\n"
22
+
23
+ def with_css_links(*files)
24
+ opts = files.last.is_a?(Hash) ? files.pop : {}
25
+ links = []
26
+ files.each do |file|
27
+ attrs = { href: "http://example.com/#{file}" }.merge(opts)
28
+ links << LINK % hash_to_attributes(attrs)
29
+ end
30
+
31
+ TEMPLATE % links.join
32
+ end
33
+
34
+ def hash_to_attributes(attrs)
35
+ attrs.map { |attr, value| "#{attr}='#{value}'" }.join(' ')
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,182 @@
1
+ # coding: utf-8
2
+
3
+ require 'mail'
4
+
5
+ module Fixtures
6
+ module Message
7
+ extend self
8
+
9
+ HTML_PART = <<-HTML
10
+ <html>
11
+ <head>
12
+ </head>
13
+ <body>
14
+ <p>
15
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
16
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
17
+ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
18
+ commodo consequat.
19
+ </p>
20
+ </body>
21
+ </html>
22
+ HTML
23
+
24
+ UNICODE_STRING = '٩(-̮̮̃-̃)۶ ٩(●̮̮̃•̃)۶ ٩(͡๏̯͡๏)۶ ٩(-̮̮̃•̃).'
25
+
26
+ HTML_PART_WITH_UNICODE = <<-HTML
27
+ <html>
28
+ <head>
29
+ </head>
30
+ <body>
31
+ <p>
32
+ #{UNICODE_STRING}
33
+ </p>
34
+ </body>
35
+ </html>
36
+ HTML
37
+
38
+ HTML_PART_IN_GREEK = <<-HTML.encode(Encoding::ISO_8859_7)
39
+ <html>
40
+ <head>
41
+ </head>
42
+ <body>
43
+ <p>
44
+ Αα Ββ Γγ Δδ Εε Ζζ Ηη Θθ Ιι Κκ Λλ Μμ Νν Ξξ Οο Ππ Ρρ Σσ Ττ Υυ Φφ Χχ Ψψ Ωω
45
+ </p>
46
+ </body>
47
+ </html>
48
+ HTML
49
+
50
+ HTML_PART_WITH_DASHES = <<-HTML
51
+ <html>
52
+ <head>
53
+ </head>
54
+ <body>
55
+ <p>
56
+ Hello there—yes you! What's up with – pardon the interrupion – dashes? I can also do &ndash; and &mdash;.
57
+ </p>
58
+ </body>
59
+ </html>
60
+ HTML
61
+
62
+ HTML_PART_WITH_CSS = <<-HTML
63
+ <html>
64
+ <head>
65
+ <style type="text/css">
66
+ p { color: red; }
67
+ </style>
68
+ </head>
69
+ <body>
70
+ <p>
71
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
72
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
73
+ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
74
+ commodo consequat.
75
+ </p>
76
+ </body>
77
+ </html>
78
+ HTML
79
+
80
+ TEXT_PART = <<-TEXT
81
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
82
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
83
+ nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
84
+ TEXT
85
+
86
+ def with_parts(*part_types)
87
+ if part_types.count == 1 and [:html, :text].include?(part_types.first)
88
+ return with_body(part_types.first)
89
+ end
90
+
91
+ message = base_message
92
+ content_part = message
93
+
94
+ if part_types.include?(:html) and part_types.include?(:text)
95
+ content_part = Mail::Part.new(content_type: 'multipart/alternative')
96
+ message.add_part(content_part)
97
+ end
98
+
99
+ if part_types.include? :html
100
+ html_part = Mail::Part.new do
101
+ body HTML_PART_WITH_CSS
102
+ content_type 'text/html; charset=UTF-8'
103
+ end
104
+ content_part.html_part = html_part
105
+ end
106
+
107
+ if part_types.include? :text
108
+ text_part = Mail::Part.new do
109
+ body TEXT_PART
110
+ content_type 'text/plain; charset=UTF-8'
111
+ end
112
+ content_part.text_part = text_part
113
+ end
114
+
115
+ if part_types.include? :attachment
116
+ message.add_file(filename: 'foo.png', content: 'foobar')
117
+ end
118
+
119
+ message.ready_to_send!
120
+
121
+ message
122
+ end
123
+
124
+ def with_body(body_type)
125
+ message = base_message
126
+
127
+ case body_type
128
+ when :html
129
+ message.body = HTML_PART_WITH_CSS
130
+ message.content_type 'text/html; charset=UTF-8'
131
+ when :text
132
+ message.body = TEXT_PART
133
+ message.content_type 'text/plain; charset=UTF-8'
134
+ end
135
+
136
+ message.ready_to_send!
137
+
138
+ message
139
+ end
140
+
141
+ def latin_message
142
+ base_message.tap do |message|
143
+ message.body = HTML_PART
144
+ message.content_type 'text/html; charset=UTF-8'
145
+ message.ready_to_send!
146
+ end
147
+ end
148
+
149
+ def non_latin_message
150
+ base_message.tap do |message|
151
+ message.body = HTML_PART_WITH_UNICODE
152
+ message.content_type 'text/html; charset=UTF-8'
153
+ message.ready_to_send!
154
+ end
155
+ end
156
+
157
+ def greek_message
158
+ base_message.tap do |message|
159
+ message.body = HTML_PART_IN_GREEK
160
+ message.content_type 'text/html; charset=ISO-8859-7'
161
+ message.ready_to_send!
162
+ end
163
+ end
164
+
165
+ def dash_message
166
+ base_message.tap do |message|
167
+ message.body = HTML_PART_WITH_DASHES
168
+ message.content_type 'text/html; charset=UTF-8'
169
+ message.ready_to_send!
170
+ end
171
+ end
172
+
173
+ private
174
+
175
+ def base_message
176
+ Mail.new do
177
+ to 'some@email.com'
178
+ subject 'testing premailer-rails'
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ if ENV.fetch("ASSETS_GEM", "sprockets") == "sprockets"
4
+ describe Premailer::Rails::CSSLoaders::AssetPipelineLoader do
5
+ before do
6
+ allow(Rails.configuration)
7
+ .to receive(:assets).and_return(double(prefix: '/assets'))
8
+ allow(Rails.configuration).to receive(:relative_url_root).and_return(nil)
9
+ end
10
+
11
+ describe ".file_name" do
12
+ subject do
13
+ Premailer::Rails::CSSLoaders::AssetPipelineLoader.file_name(asset)
14
+ end
15
+
16
+ context "when asset file path contains prefix" do
17
+ let(:asset) { '/assets/application.css' }
18
+ it { is_expected.to eq('application.css') }
19
+ end
20
+
21
+ context "when asset file path contains prefix and relative_url_root is set" do
22
+ before do
23
+ allow(Rails.configuration)
24
+ .to receive(:relative_url_root).and_return('/foo')
25
+ end
26
+
27
+ let(:asset) { '/foo/assets/application.css' }
28
+ it { is_expected.to eq('application.css') }
29
+ end
30
+
31
+ context "when asset file path contains prefix and relative_url_root is set to root" do
32
+ before do
33
+ allow(Rails.configuration)
34
+ .to receive(:relative_url_root).and_return('/')
35
+ end
36
+
37
+ let(:asset) { '/assets/application.css' }
38
+ it { is_expected.to eq('application.css') }
39
+ end
40
+
41
+ context "when asset file path contains 32 chars fingerprint" do
42
+ let(:asset) { 'application-6776f581a4329e299531e1d52aa59832.css' }
43
+ it { is_expected.to eq('application.css') }
44
+ end
45
+
46
+ context "when asset file path contains 64 chars fingerprint" do
47
+ let(:asset) { 'application-02275ccb3fd0c11615bbfb11c99ea123ca2287e75045fe7b72cefafb880dad2b.css' }
48
+ it { is_expected.to eq('application.css') }
49
+ end
50
+
51
+ context "when asset file page contains numbers, but not a fingerprint" do
52
+ let(:asset) { 'test/20130708152545-foo-bar.css' }
53
+ it { is_expected.to eq("test/20130708152545-foo-bar.css") }
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Premailer::Rails::CSSLoaders::FileSystemLoader do
4
+ before do
5
+ allow(Rails.configuration)
6
+ .to receive(:assets).and_return(double(prefix: '/assets'))
7
+ allow(Rails)
8
+ .to receive(:root).and_return(Pathname.new('/rails_root'))
9
+ end
10
+
11
+ describe '#file_name' do
12
+ subject { described_class.file_name(asset) }
13
+ let(:relative_url_root) { nil }
14
+
15
+ before do
16
+ config = double(relative_url_root: relative_url_root)
17
+ allow(Rails).to receive(:configuration).and_return(config)
18
+ end
19
+
20
+ context 'when relative_url_root is not set' do
21
+ let(:asset) { '/assets/application.css' }
22
+ it { is_expected.to eq(File.join(Rails.root, 'public/assets/application.css')) }
23
+ end
24
+
25
+ context 'when relative_url_root is set' do
26
+ let(:relative_url_root) { '/foo' }
27
+ let(:asset) { '/foo/assets/application.css' }
28
+ it { is_expected.to eq(File.join(Rails.root, 'public/assets/application.css')) }
29
+ end
30
+
31
+ context 'when relative_url_root has a trailing slash' do
32
+ let(:relative_url_root) { '/foo/' }
33
+ let(:asset) { '/foo/assets/application.css' }
34
+ it { is_expected.to eq(File.join(Rails.root, 'public/assets/application.css')) }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe Premailer::Rails::CSSLoaders::NetworkLoader do
4
+ describe '#uri_for_url' do
5
+ subject { described_class.uri_for_url(url) }
6
+ let(:asset_host) { nil }
7
+
8
+ before do
9
+ action_controller = double(asset_host: asset_host)
10
+ config = double(action_controller: action_controller)
11
+ allow(Rails).to receive(:configuration).and_return(config)
12
+ end
13
+
14
+ context 'with a valid URL' do
15
+ let(:url) { 'http://example.com/test.css' }
16
+ it { is_expected.to eq(URI(url)) }
17
+ end
18
+
19
+ context 'with a protocol relative URL' do
20
+ let(:url) { '//example.com/test.css' }
21
+ it { is_expected.to eq(URI("http:#{url}")) }
22
+ end
23
+
24
+ context 'with a file path' do
25
+ let(:url) { '/assets/foo.css' }
26
+
27
+ context 'and a domain as asset host' do
28
+ let(:asset_host) { 'example.com' }
29
+ it { is_expected.to eq(URI("http://example.com#{url}")) }
30
+ end
31
+
32
+ context 'and a URL as asset host' do
33
+ let(:asset_host) { 'https://example.com' }
34
+ it { is_expected.to eq(URI("https://example.com/assets/foo.css")) }
35
+ end
36
+
37
+ context 'and a protocol relative URL as asset host' do
38
+ let(:asset_host) { '//example.com' }
39
+ it { is_expected.to eq(URI("http://example.com/assets/foo.css")) }
40
+ end
41
+
42
+ context 'and a callable object as asset host' do
43
+ let(:asset_host) { double }
44
+
45
+ it 'calls #call with the asset path as argument' do
46
+ expect(asset_host).to receive(:call).with(url).and_return(
47
+ 'http://example.com')
48
+ expect(subject).to eq(URI('http://example.com/assets/foo.css'))
49
+ end
50
+ end
51
+
52
+ context 'without an asset host' do
53
+ let(:asset_host) { nil }
54
+ it { is_expected.not_to be }
55
+ end
56
+ end
57
+ end
58
+ end