roadie-rails 1.0.0.pre1

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 (166) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.travis.yml +15 -0
  4. data/Changelog.md +9 -0
  5. data/Gemfile +17 -0
  6. data/Guardfile +16 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +317 -0
  9. data/Rakefile +14 -0
  10. data/Upgrading.md +70 -0
  11. data/lib/roadie-rails.rb +1 -0
  12. data/lib/roadie/rails.rb +21 -0
  13. data/lib/roadie/rails/asset_pipeline_provider.rb +24 -0
  14. data/lib/roadie/rails/automatic.rb +16 -0
  15. data/lib/roadie/rails/document_builder.rb +18 -0
  16. data/lib/roadie/rails/inline_on_delivery.rb +17 -0
  17. data/lib/roadie/rails/mail_inliner.rb +26 -0
  18. data/lib/roadie/rails/mailer.rb +14 -0
  19. data/lib/roadie/rails/options.rb +101 -0
  20. data/lib/roadie/rails/railtie.rb +22 -0
  21. data/lib/roadie/rails/version.rb +5 -0
  22. data/roadie-rails.gemspec +29 -0
  23. data/setup.sh +62 -0
  24. data/spec/integration_spec.rb +119 -0
  25. data/spec/lib/roadie/rails/asset_pipeline_provider_spec.rb +47 -0
  26. data/spec/lib/roadie/rails/automatic_spec.rb +44 -0
  27. data/spec/lib/roadie/rails/document_builder_spec.rb +20 -0
  28. data/spec/lib/roadie/rails/mail_inliner_spec.rb +57 -0
  29. data/spec/lib/roadie/rails/mailer_spec.rb +57 -0
  30. data/spec/lib/roadie/rails/options_spec.rb +136 -0
  31. data/spec/lib/roadie/rails/railtie_spec.rb +48 -0
  32. data/spec/railsapps/README.md +69 -0
  33. data/spec/railsapps/rails_30/.gitignore +2 -0
  34. data/spec/railsapps/rails_30/Gemfile +7 -0
  35. data/spec/railsapps/rails_30/app/mailers/auto_mailer.rb +17 -0
  36. data/spec/railsapps/rails_30/app/mailers/mailer.rb +17 -0
  37. data/spec/railsapps/rails_30/app/views/auto_mailer/normal_email.html.erb +11 -0
  38. data/spec/railsapps/rails_30/app/views/auto_mailer/normal_email.text +1 -0
  39. data/spec/railsapps/rails_30/app/views/mailer/normal_email.html.erb +11 -0
  40. data/spec/railsapps/rails_30/app/views/mailer/normal_email.text +1 -0
  41. data/spec/railsapps/rails_30/config/application.rb +19 -0
  42. data/spec/railsapps/rails_30/config/boot.rb +6 -0
  43. data/spec/railsapps/rails_30/config/environment.rb +5 -0
  44. data/spec/railsapps/rails_30/config/environments/development.rb +10 -0
  45. data/spec/railsapps/rails_30/config/initializers/secret_token.rb +1 -0
  46. data/spec/railsapps/rails_30/config/initializers/session_store.rb +1 -0
  47. data/spec/railsapps/rails_30/config/routes.rb +2 -0
  48. data/spec/railsapps/rails_30/public/images/rails.png +0 -0
  49. data/spec/railsapps/rails_30/public/stylesheets/email.css +2 -0
  50. data/spec/railsapps/rails_30/script/rails +6 -0
  51. data/spec/railsapps/rails_31/.gitignore +2 -0
  52. data/spec/railsapps/rails_31/Gemfile +11 -0
  53. data/spec/railsapps/rails_31/app/assets/images/rails.png +0 -0
  54. data/spec/railsapps/rails_31/app/assets/stylesheets/email.css.scss +2 -0
  55. data/spec/railsapps/rails_31/app/mailers/auto_mailer.rb +17 -0
  56. data/spec/railsapps/rails_31/app/mailers/mailer.rb +17 -0
  57. data/spec/railsapps/rails_31/app/views/auto_mailer/normal_email.html.erb +11 -0
  58. data/spec/railsapps/rails_31/app/views/auto_mailer/normal_email.text +1 -0
  59. data/spec/railsapps/rails_31/app/views/mailer/normal_email.html.erb +11 -0
  60. data/spec/railsapps/rails_31/app/views/mailer/normal_email.text +1 -0
  61. data/spec/railsapps/rails_31/config/application.rb +22 -0
  62. data/spec/railsapps/rails_31/config/boot.rb +6 -0
  63. data/spec/railsapps/rails_31/config/environment.rb +5 -0
  64. data/spec/railsapps/rails_31/config/environments/development.rb +11 -0
  65. data/spec/railsapps/rails_31/config/initializers/secret_token.rb +1 -0
  66. data/spec/railsapps/rails_31/config/initializers/session_store.rb +1 -0
  67. data/spec/railsapps/rails_31/config/initializers/wrap_parameters.rb +4 -0
  68. data/spec/railsapps/rails_31/config/routes.rb +2 -0
  69. data/spec/railsapps/rails_31/script/rails +6 -0
  70. data/spec/railsapps/rails_32/.gitignore +2 -0
  71. data/spec/railsapps/rails_32/Gemfile +11 -0
  72. data/spec/railsapps/rails_32/app/assets/images/rails.png +0 -0
  73. data/spec/railsapps/rails_32/app/assets/stylesheets/email.css.scss +2 -0
  74. data/spec/railsapps/rails_32/app/mailers/auto_mailer.rb +17 -0
  75. data/spec/railsapps/rails_32/app/mailers/mailer.rb +17 -0
  76. data/spec/railsapps/rails_32/app/views/auto_mailer/normal_email.html.erb +11 -0
  77. data/spec/railsapps/rails_32/app/views/auto_mailer/normal_email.text +1 -0
  78. data/spec/railsapps/rails_32/app/views/mailer/normal_email.html.erb +11 -0
  79. data/spec/railsapps/rails_32/app/views/mailer/normal_email.text +1 -0
  80. data/spec/railsapps/rails_32/config/application.rb +22 -0
  81. data/spec/railsapps/rails_32/config/boot.rb +6 -0
  82. data/spec/railsapps/rails_32/config/environment.rb +5 -0
  83. data/spec/railsapps/rails_32/config/environments/development.rb +11 -0
  84. data/spec/railsapps/rails_32/config/initializers/secret_token.rb +1 -0
  85. data/spec/railsapps/rails_32/config/initializers/session_store.rb +1 -0
  86. data/spec/railsapps/rails_32/config/initializers/wrap_parameters.rb +4 -0
  87. data/spec/railsapps/rails_32/config/routes.rb +2 -0
  88. data/spec/railsapps/rails_32/script/rails +6 -0
  89. data/spec/railsapps/rails_40/Gemfile +9 -0
  90. data/spec/railsapps/rails_40/app/assets/images/rails.png +0 -0
  91. data/spec/railsapps/rails_40/app/assets/stylesheets/email.css.scss +2 -0
  92. data/spec/railsapps/rails_40/app/mailers/auto_mailer.rb +17 -0
  93. data/spec/railsapps/rails_40/app/mailers/mailer.rb +17 -0
  94. data/spec/railsapps/rails_40/app/views/auto_mailer/normal_email.html.erb +11 -0
  95. data/spec/railsapps/rails_40/app/views/auto_mailer/normal_email.text +1 -0
  96. data/spec/railsapps/rails_40/app/views/mailer/normal_email.html.erb +11 -0
  97. data/spec/railsapps/rails_40/app/views/mailer/normal_email.text +1 -0
  98. data/spec/railsapps/rails_40/bin/rails +4 -0
  99. data/spec/railsapps/rails_40/config/application.rb +18 -0
  100. data/spec/railsapps/rails_40/config/boot.rb +4 -0
  101. data/spec/railsapps/rails_40/config/environment.rb +5 -0
  102. data/spec/railsapps/rails_40/config/environments/development.rb +9 -0
  103. data/spec/railsapps/rails_40/config/initializers/secret_token.rb +1 -0
  104. data/spec/railsapps/rails_40/config/initializers/session_store.rb +1 -0
  105. data/spec/railsapps/rails_40/config/routes.rb +2 -0
  106. data/spec/railsapps/rails_40_no_pipeline/Gemfile +9 -0
  107. data/spec/railsapps/rails_40_no_pipeline/app/mailers/auto_mailer.rb +17 -0
  108. data/spec/railsapps/rails_40_no_pipeline/app/mailers/mailer.rb +17 -0
  109. data/spec/railsapps/rails_40_no_pipeline/app/views/auto_mailer/normal_email.html.erb +11 -0
  110. data/spec/railsapps/rails_40_no_pipeline/app/views/auto_mailer/normal_email.text +1 -0
  111. data/spec/railsapps/rails_40_no_pipeline/app/views/mailer/normal_email.html.erb +11 -0
  112. data/spec/railsapps/rails_40_no_pipeline/app/views/mailer/normal_email.text +1 -0
  113. data/spec/railsapps/rails_40_no_pipeline/bin/rails +4 -0
  114. data/spec/railsapps/rails_40_no_pipeline/config/application.rb +19 -0
  115. data/spec/railsapps/rails_40_no_pipeline/config/boot.rb +4 -0
  116. data/spec/railsapps/rails_40_no_pipeline/config/environment.rb +5 -0
  117. data/spec/railsapps/rails_40_no_pipeline/config/environments/development.rb +9 -0
  118. data/spec/railsapps/rails_40_no_pipeline/config/initializers/secret_token.rb +1 -0
  119. data/spec/railsapps/rails_40_no_pipeline/config/initializers/session_store.rb +1 -0
  120. data/spec/railsapps/rails_40_no_pipeline/config/routes.rb +2 -0
  121. data/spec/railsapps/rails_40_no_pipeline/log/dee +0 -0
  122. data/spec/railsapps/rails_40_no_pipeline/public/images/rails.png +0 -0
  123. data/spec/railsapps/rails_40_no_pipeline/public/stylesheets/email.css +2 -0
  124. data/spec/railsapps/rails_40_precompiled/Gemfile +9 -0
  125. data/spec/railsapps/rails_40_precompiled/Rakefile +6 -0
  126. data/spec/railsapps/rails_40_precompiled/app/assets/images/rails.png +0 -0
  127. data/spec/railsapps/rails_40_precompiled/app/assets/stylesheets/email.css.scss +2 -0
  128. data/spec/railsapps/rails_40_precompiled/app/mailers/mailer.rb +17 -0
  129. data/spec/railsapps/rails_40_precompiled/app/views/mailer/normal_email.html.erb +11 -0
  130. data/spec/railsapps/rails_40_precompiled/app/views/mailer/normal_email.text +1 -0
  131. data/spec/railsapps/rails_40_precompiled/bin/rails +4 -0
  132. data/spec/railsapps/rails_40_precompiled/config/application.rb +18 -0
  133. data/spec/railsapps/rails_40_precompiled/config/boot.rb +4 -0
  134. data/spec/railsapps/rails_40_precompiled/config/environment.rb +5 -0
  135. data/spec/railsapps/rails_40_precompiled/config/environments/development.rb +14 -0
  136. data/spec/railsapps/rails_40_precompiled/config/initializers/secret_token.rb +1 -0
  137. data/spec/railsapps/rails_40_precompiled/config/initializers/session_store.rb +1 -0
  138. data/spec/railsapps/rails_40_precompiled/config/routes.rb +2 -0
  139. data/spec/railsapps/rails_40_precompiled/public/assets/email-fad0c62b8f82e2835c1d0bdc19894257.css +5 -0
  140. data/spec/railsapps/rails_40_precompiled/public/assets/email-fad0c62b8f82e2835c1d0bdc19894257.css.gz +0 -0
  141. data/spec/railsapps/rails_40_precompiled/public/assets/manifest-8a3d16aeb2a40fe5057dd998c3edab10.json +1 -0
  142. data/spec/railsapps/rails_40_precompiled/public/assets/rails-231a680f23887d9dd70710ea5efd3c62.png +0 -0
  143. data/spec/railsapps/rails_41/.gitignore +16 -0
  144. data/spec/railsapps/rails_41/Gemfile +8 -0
  145. data/spec/railsapps/rails_41/app/assets/images/rails.png +0 -0
  146. data/spec/railsapps/rails_41/app/assets/stylesheets/email.css.scss +2 -0
  147. data/spec/railsapps/rails_41/app/mailers/auto_mailer.rb +17 -0
  148. data/spec/railsapps/rails_41/app/mailers/mailer.rb +17 -0
  149. data/spec/railsapps/rails_41/app/views/auto_mailer/normal_email.html.erb +11 -0
  150. data/spec/railsapps/rails_41/app/views/auto_mailer/normal_email.text +1 -0
  151. data/spec/railsapps/rails_41/app/views/mailer/normal_email.html.erb +11 -0
  152. data/spec/railsapps/rails_41/app/views/mailer/normal_email.text +1 -0
  153. data/spec/railsapps/rails_41/bin/rails +4 -0
  154. data/spec/railsapps/rails_41/config.ru +4 -0
  155. data/spec/railsapps/rails_41/config/application.rb +13 -0
  156. data/spec/railsapps/rails_41/config/boot.rb +4 -0
  157. data/spec/railsapps/rails_41/config/environment.rb +5 -0
  158. data/spec/railsapps/rails_41/config/environments/development.rb +9 -0
  159. data/spec/railsapps/rails_41/config/initializers/secret_token.rb +1 -0
  160. data/spec/railsapps/rails_41/config/initializers/session_store.rb +1 -0
  161. data/spec/railsapps/rails_41/config/routes.rb +2 -0
  162. data/spec/spec_helper.rb +14 -0
  163. data/spec/support/have_selector_matcher.rb +3 -0
  164. data/spec/support/have_styling_matcher.rb +63 -0
  165. data/spec/support/rails_app.rb +70 -0
  166. metadata +443 -0
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+ require 'tempfile'
3
+ require 'mail'
4
+
5
+ describe "Integrations" do
6
+ def parse_html_in_email(mail)
7
+ Nokogiri::HTML.parse mail.html_part.body.decoded
8
+ end
9
+
10
+ [
11
+ RailsApp.new("Rails 3.0.x", 'rails_30', runner: :script, asset_pipeline: false),
12
+ ## We do not yet support live-compilation through asset pipeline
13
+ RailsApp.new("Rails 3.1.x", 'rails_31', runner: :script, asset_pipeline: true),
14
+ RailsApp.new("Rails 3.2.x", 'rails_32', runner: :script, asset_pipeline: true),
15
+ RailsApp.new("Rails 4.0.x", 'rails_40', runner: :bin, asset_pipeline: true),
16
+ RailsApp.new("Rails 4.0.x (without asset pipeline)", 'rails_40_no_pipeline', runner: :bin, asset_pipeline: false),
17
+ RailsApp.new("Rails 4.1.x", 'rails_41', runner: :bin, asset_pipeline: true),
18
+ ].each do |app|
19
+ describe "with #{app}" do
20
+ before { app.reset }
21
+
22
+ it "inlines styles for multipart emails" do
23
+ email = app.read_email(:normal_email)
24
+
25
+ expect(email.to).to eq(['example@example.org'])
26
+ expect(email.from).to eq(['john@example.com'])
27
+ expect(email).to have(2).parts
28
+
29
+ expect(email.text_part.body.decoded).not_to match(/<.*>/)
30
+
31
+ html = email.html_part.body.decoded
32
+ expect(html).to include '<!DOCTYPE'
33
+ expect(html).to include '<head'
34
+
35
+ document = parse_html_in_email(email)
36
+ expect(document).to have_selector('body h1')
37
+
38
+ if app.using_asset_pipeline?
39
+ expected_image_url = 'https://example.app.org/assets/rails.png'
40
+ else
41
+ expected_image_url = 'https://example.app.org/images/rails.png'
42
+ end
43
+ expect(document).to have_styling('background' => "url(#{expected_image_url})").at_selector('.image')
44
+
45
+ # If we deliver mails we can catch weird problems with headers being invalid
46
+ email.delivery_method :test
47
+ email.deliver
48
+ end
49
+
50
+ it "automatically inlines styles with automatic mailer" do
51
+ email = app.read_delivered_email(:normal_email)
52
+
53
+ expect(email.to).to eq(['example@example.org'])
54
+ expect(email.from).to eq(['john@example.com'])
55
+ expect(email).to have(2).parts
56
+
57
+ expect(email.text_part.body.decoded).not_to match(/<.*>/)
58
+
59
+ html = email.html_part.body.decoded
60
+ expect(html).to include '<!DOCTYPE'
61
+ expect(html).to include '<head'
62
+
63
+ document = parse_html_in_email(email)
64
+ expect(document).to have_selector('body h1')
65
+
66
+ if app.using_asset_pipeline?
67
+ expected_image_url = 'https://example.app.org/assets/rails.png'
68
+ else
69
+ expected_image_url = 'https://example.app.org/images/rails.png'
70
+ end
71
+ expect(document).to have_styling('background' => "url(#{expected_image_url})").at_selector('.image')
72
+
73
+ # If we deliver mails we can catch weird problems with headers being invalid
74
+ email.delivery_method :test
75
+ email.deliver
76
+ end
77
+
78
+ if app.using_asset_pipeline?
79
+ it "has a AssetPipelineProvider together with a FilesystemProvider" do
80
+ expect(app.read_providers).to eq(%w[Roadie::FilesystemProvider Roadie::Rails::AssetPipelineProvider])
81
+ end
82
+ else
83
+ it "only has a FilesystemProvider" do
84
+ expect(app.read_providers).to eq(["Roadie::FilesystemProvider"])
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ describe "with precompiled assets" do
91
+ let(:app) {
92
+ RailsApp.new("Rails 4.0.x (precompiled)", 'rails_40_precompiled', runner: :bin, asset_pipeline: false)
93
+ }
94
+
95
+ before { app.reset }
96
+
97
+ let(:document) do
98
+ parse_html_in_email app.read_email(:normal_email)
99
+ end
100
+
101
+ # It still has an AssetPipelineProvider in case some asset isn't
102
+ # precompiled, or the user want to combine. As long as the user is using
103
+ # the correct asset helpers a precompiled asset will be picked up by the
104
+ # FilesystemProvider.
105
+ it "has a AssetPipelineProvider together with a FilesystemProvider" do
106
+ expect(app.read_providers).to eq(%w[Roadie::FilesystemProvider Roadie::Rails::AssetPipelineProvider])
107
+ end
108
+
109
+ it "inlines the precompiled stylesheet" do
110
+ # Precompiled version has green color; the file in app/assets have red
111
+ expect(document).to have_styling('background-color' => 'green').at_selector('body')
112
+ end
113
+
114
+ it "inlines images with digests" do
115
+ image_url = "https://example.app.org/assets/rails-231a680f23887d9dd70710ea5efd3c62.png"
116
+ expect(document).to have_styling('background' => "url(#{image_url})").at_selector('.image')
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'roadie/rspec'
3
+
4
+ module Roadie
5
+ module Rails
6
+ describe AssetPipelineProvider do
7
+ let(:pipeline) { FakePipeline.new }
8
+
9
+ it_behaves_like "roadie asset provider", valid_name: "existing.css", invalid_name: "bad.css" do
10
+ subject { AssetPipelineProvider.new(pipeline) }
11
+ before do
12
+ pipeline.add_asset "existing.css", "existing.css", ""
13
+ end
14
+ end
15
+
16
+ describe "finding stylesheets" do
17
+ it "searches the asset pipeline" do
18
+ pipeline.add_asset "good.css", "/path/to/good.css.scss", "body { color: red; }"
19
+ provider = AssetPipelineProvider.new(pipeline)
20
+
21
+ stylesheet = provider.find_stylesheet("good.css")
22
+ expect(stylesheet.name).to eq("/path/to/good.css.scss (live compiled)")
23
+ expect(stylesheet.to_s).to eq("body{color:red}")
24
+ end
25
+
26
+ it "ignores query string and asset prefix" do
27
+ pipeline.add_asset "good.css", "good.css.scss", ""
28
+ provider = AssetPipelineProvider.new(pipeline)
29
+ expect(provider.find_stylesheet("/assets/good.css?body=1")).not_to be_nil
30
+ end
31
+ end
32
+
33
+ class FakePipeline
34
+ # Interface
35
+ def [](name)
36
+ @files.find { |file| file.matching_name == name }
37
+ end
38
+
39
+ # Test helpers
40
+ def initialize() @files = [] end
41
+ def add_asset(matching_name, path, content) @files << AssetFile.new(matching_name, path, content) end
42
+ private
43
+ AssetFile = Struct.new(:matching_name, :pathname, :to_s)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'mail'
3
+
4
+ module Roadie
5
+ module Rails
6
+ describe Automatic do
7
+ base_mailer = Class.new do
8
+ def initialize(email = nil)
9
+ @email = email
10
+ end
11
+
12
+ def mail(options = {})
13
+ @email
14
+ end
15
+ end
16
+
17
+ some_mailer = Class.new(base_mailer) do
18
+ include Automatic
19
+ end
20
+
21
+ describe "#roadie_options" do
22
+ it "returns Rails' roadie config" do
23
+ allow(::Rails).to receive_message_chain(:application, :config, :roadie).and_return "roadie config"
24
+ expect(some_mailer.new.roadie_options).to eq("roadie config")
25
+ end
26
+ end
27
+
28
+ describe "#mail" do
29
+ let(:email) { Mail.new(to: "foo@example.com", from: "me@example.com") }
30
+ let(:roadie_options) { Options.new(url_options: {host: "somehost.com"}) }
31
+ let(:instance) { some_mailer.new(email) }
32
+
33
+ before { allow(instance).to receive(:roadie_options).and_return roadie_options }
34
+
35
+ it "extends the email with InlineOnDelivery and assigns roadie options" do
36
+ email = instance.mail
37
+ expect(email).to be_kind_of(InlineOnDelivery)
38
+ expect(email.roadie_options).not_to be_nil
39
+ expect(email.roadie_options.url_options).to eq roadie_options.url_options
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ module Roadie
5
+ module Rails
6
+ describe DocumentBuilder do
7
+ it "builds documents with the given HTML" do
8
+ document = DocumentBuilder.build("foo", Options.new)
9
+ expect(document.html).to eq("foo")
10
+ end
11
+
12
+ it "applies the options to the document" do
13
+ options = Options.new
14
+ expect(options).to receive(:apply_to).with(instance_of Document).and_call_original
15
+
16
+ DocumentBuilder.build("", options)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,57 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+ require 'mail'
4
+
5
+ module Roadie
6
+ module Rails
7
+ describe MailInliner do
8
+ let(:email) { Mail.new }
9
+ let(:options) { Options.new }
10
+ subject(:inliner) { MailInliner.new(email, options) }
11
+
12
+ it "takes an email and options" do
13
+ inliner = MailInliner.new(email, options)
14
+ expect(inliner.email).to eq(email)
15
+ expect(inliner.options).to eq(options)
16
+ end
17
+
18
+ context "with an plaintext email" do
19
+ let(:email) do
20
+ Mail.new do
21
+ body "Hello world"
22
+ end
23
+ end
24
+
25
+ it "returns the email without doing anything" do
26
+ expect(inliner.execute).to eq(email)
27
+ expect(email.html_part).to be_nil
28
+ expect(email.body.decoded).to eq("Hello world")
29
+ end
30
+ end
31
+
32
+ context "with an multipart email" do
33
+ let(:html) { "<h1>Hello world!</h1>" }
34
+ let(:email) do
35
+ html_string = html
36
+ Mail.new do
37
+ text_part { body "Hello world" }
38
+ html_part { body html_string }
39
+ end
40
+ end
41
+
42
+ it "returns the email" do
43
+ expect(inliner.execute).to eq(email)
44
+ end
45
+
46
+ it "adjusts the html part using Roadie" do
47
+ document = double "A document", transform: "transformed HTML"
48
+ expect(DocumentBuilder).to receive(:build).with(html, instance_of(Options)).and_return document
49
+
50
+ inliner.execute
51
+
52
+ expect(email.html_part.body.decoded).to eq("transformed HTML")
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+ require 'mail'
3
+
4
+ module Roadie
5
+ module Rails
6
+ describe Mailer do
7
+ some_mailer = Class.new do
8
+ include Mailer
9
+
10
+ def initialize(email = nil)
11
+ @email = email
12
+ end
13
+
14
+ def mail(options = {})
15
+ @email
16
+ end
17
+ end
18
+
19
+ describe "#roadie_options" do
20
+ it "returns Rails' roadie config" do
21
+ allow(::Rails).to receive_message_chain(:application, :config, :roadie).and_return "roadie config"
22
+ expect(some_mailer.new.roadie_options).to eq("roadie config")
23
+ end
24
+ end
25
+
26
+ describe "#roadie_mail" do
27
+ let(:email) { Mail.new }
28
+ let(:instance) { some_mailer.new(email) }
29
+
30
+ before { allow(instance).to receive(:roadie_options).and_return(Options.new) }
31
+
32
+ before do
33
+ inliner = double "Mail inliner"
34
+ allow(inliner).to receive(:execute) { |email| email }
35
+ allow(MailInliner).to receive(:new).and_return(inliner)
36
+ end
37
+
38
+ it "calls the original mail method with all options and the block" do
39
+ expect(instance).to receive(:mail) do |options, &block|
40
+ expect(options).to eq({some: "option"})
41
+ expect(block).not_to be_nil
42
+ email
43
+ end
44
+
45
+ instance.roadie_mail(some: "option") { }
46
+ end
47
+
48
+ it "inlines the email" do
49
+ inliner = double "Inliner"
50
+ expect(MailInliner).to receive(:new).with(email, instance_of(Options)).and_return inliner
51
+ expect(inliner).to receive(:execute).and_return "inlined email"
52
+ expect(instance.roadie_mail).to eq("inlined email")
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,136 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+ require 'ostruct'
4
+
5
+ module Roadie
6
+ module Rails
7
+ describe Options do
8
+ it "raises errors when constructed with unknown options" do
9
+ expect {
10
+ Options.new(unknown_option: "maybe a misspelling?")
11
+ }.to raise_error(ArgumentError, /unknown_option/)
12
+ end
13
+
14
+ shared_examples_for "attribute" do |name|
15
+ describe name do
16
+ it "defaults to nil" do
17
+ expect(Options.new.send(name)).to be_nil
18
+ end
19
+
20
+ it "can be set in the constructor" do
21
+ expect(Options.new(name => valid_value).send(name)).to eq(valid_value)
22
+ end
23
+
24
+ it "can be changed using setter" do
25
+ options = Options.new
26
+ options.send :"#{name}=", valid_value
27
+ expect(options.send(name)).to eq(valid_value)
28
+ end
29
+
30
+ it "can be applied to documents" do
31
+ fake_document = OpenStruct.new
32
+ options = Options.new(name => valid_value)
33
+ options.apply_to(fake_document)
34
+ expect(fake_document.send(name)).to eq(valid_value)
35
+ end
36
+
37
+ describe "merging" do
38
+ it "replaces values" do
39
+ options = Options.new(name => valid_value)
40
+ expect(options.merge(name => other_valid_value).send(name)).to eq(other_valid_value)
41
+ end
42
+
43
+ it "does not mutate instance" do
44
+ options = Options.new(name => valid_value)
45
+ options.merge(name => other_valid_value)
46
+ expect(options.send(name)).to eq(valid_value)
47
+ end
48
+ end
49
+
50
+ describe "destructive merging" do
51
+ it "replaces values" do
52
+ options = Options.new(name => valid_value)
53
+ expect(options.merge(name => other_valid_value).send(name)).to eq(other_valid_value)
54
+ end
55
+ end
56
+
57
+ describe "combining" do
58
+ it "combines the old and the new value" do
59
+ options = Options.new(name => valid_value)
60
+ combined = options.combine(name => other_valid_value)
61
+ expect_combinated_value combined.send(name)
62
+ end
63
+
64
+ it "does not mutate instance" do
65
+ options = Options.new(name => valid_value)
66
+ options.combine(name => other_valid_value)
67
+ expect(options.send(name)).to eq(valid_value)
68
+ end
69
+ end
70
+
71
+ describe "destructive combining" do
72
+ it "combines the old and the new value in the instance" do
73
+ options = Options.new(name => valid_value)
74
+ options.combine!(name => other_valid_value)
75
+ expect_combinated_value options.send(name)
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ it_behaves_like "attribute", :url_options do
82
+ let(:valid_value) { {host: "foo.com", port: 3000} }
83
+ let(:other_valid_value) { {host: "bar.com", scheme: "https"} }
84
+
85
+ def expect_combinated_value(value)
86
+ expect(value).to eq({host: "bar.com", port: 3000, scheme: "https"})
87
+ end
88
+ end
89
+
90
+ it_behaves_like "attribute", :before_transformation do
91
+ let(:valid_value) { Proc.new { } }
92
+ let(:other_valid_value) { Proc.new { } }
93
+
94
+ def expect_combinated_value(value)
95
+ expect(valid_value).to receive(:call).ordered.and_return 1
96
+ expect(other_valid_value).to receive(:call).ordered.and_return 2
97
+
98
+ expect(value.call).to eq(2)
99
+ end
100
+ end
101
+
102
+ it_behaves_like "attribute", :after_transformation do
103
+ let(:valid_value) { Proc.new { } }
104
+ let(:other_valid_value) { Proc.new { } }
105
+
106
+ def expect_combinated_value(value)
107
+ expect(valid_value).to receive(:call).ordered.and_return 1
108
+ expect(other_valid_value).to receive(:call).ordered.and_return 2
109
+ expect(value.call).to eq(2)
110
+ end
111
+ end
112
+
113
+ it_behaves_like "attribute", :asset_providers do
114
+ let(:provider1) { double "Asset provider 1" }
115
+ let(:provider2) { double "Asset provider 2" }
116
+
117
+ let(:valid_value) { ProviderList.new([provider1]) }
118
+ let(:other_valid_value) { ProviderList.new([provider2]) }
119
+
120
+ def expect_combinated_value(value)
121
+ expect(value).to be_instance_of(ProviderList)
122
+ expect(value.to_a).to eq([provider1, provider2])
123
+ end
124
+ end
125
+
126
+ describe "asset_providers" do
127
+ it "automatically wraps values in a ProviderList" do
128
+ provider = double "Asset provider"
129
+ options = Options.new(asset_providers: [provider])
130
+ expect(options.asset_providers).to be_instance_of(ProviderList)
131
+ expect(options.asset_providers.to_a).to eq([provider])
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end