premailer-rails-revived 1.12.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.
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