Skip to content

Commit fba0669

Browse files
committed
Merge pull request #1327 from rspec/update-action-mailer-railtie
Fix action mailer preview path setup.
2 parents f5af60f + f61100e commit fba0669

File tree

7 files changed

+342
-50
lines changed

7 files changed

+342
-50
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Bug Fixes:
1010

1111
* Fix auto-including of generic `Helper` object for view specs sitting in the
1212
`app/views` root (David Daniell, #1289)
13+
* Remove pre-loading of ActionMailer in the Railtie (Aaron Kromer, #1327)
1314

1415
### 3.2.1 / 2015-02-23
1516
[Full Changelog](http://github.com/rspec/rspec-rails/compare/v3.2.0...v3.2.1)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
require 'active_support'
2+
require 'active_support/core_ext/module'
3+
4+
# We need to copy this method from Thor for older Rails versions
5+
def comment_lines(path, flag, *args)
6+
flag = flag.respond_to?(:source) ? flag.source : flag
7+
gsub_file(path, /^(\s*)([^#|\n]*#{flag})/, '\1# \2', *args)
8+
end
9+
10+
using_source_path(File.expand_path('..', __FILE__)) do
11+
# Comment out the default mailer stuff
12+
comment_lines 'config/environments/development.rb', /action_mailer/
13+
comment_lines 'config/environments/test.rb', /action_mailer/
14+
15+
initializer 'action_mailer.rb', <<-CODE
16+
if ENV['DEFAULT_URL']
17+
Rails.application.configure do
18+
config.action_mailer.default_url_options = { :host => ENV['DEFAULT_URL'] }
19+
end
20+
end
21+
CODE
22+
23+
copy_file 'spec/support/default_preview_path'
24+
chmod 'spec/support/default_preview_path', 0755
25+
gsub_file 'spec/support/default_preview_path',
26+
/ExampleApp/,
27+
Rails.application.class.parent.to_s
28+
if skip_active_record?
29+
comment_lines 'spec/support/default_preview_path', /active_record/
30+
end
31+
copy_file 'spec/verify_mailer_preview_path_spec.rb'
32+
end

example_app_generator/generate_stuff.rb

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
require 'rspec/rails/feature_check'
22

3-
module ExampleAppHooks
4-
DEFAULT_SOURCE_PATH = File.expand_path('..', __FILE__)
3+
DEFAULT_SOURCE_PATH = File.expand_path('..', __FILE__)
54

5+
module ExampleAppHooks
66
module AR
77
def source_paths
8-
[DEFAULT_SOURCE_PATH]
8+
@__source_paths__ ||= [DEFAULT_SOURCE_PATH]
99
end
1010

1111
def setup_tasks
@@ -19,11 +19,15 @@ def final_tasks
1919
run('bin/rake db:migrate RAILS_ENV=test')
2020
end
2121
end
22+
23+
def skip_active_record?
24+
false
25+
end
2226
end
2327

2428
module NoAR
2529
def source_paths
26-
[File.join(DEFAULT_SOURCE_PATH, 'no_active_record')]
30+
@__source_paths__ ||= [File.join(DEFAULT_SOURCE_PATH, 'no_active_record')]
2731
end
2832

2933
def setup_tasks
@@ -40,6 +44,10 @@ def setup_tasks
4044
def final_tasks
4145
copy_file 'spec/verify_no_active_record_spec.rb'
4246
end
47+
48+
def skip_active_record?
49+
true
50+
end
4351
end
4452

4553
def self.environment_hooks
@@ -56,6 +64,14 @@ def generate(*)
5664
$?.success? || abort
5765
end
5866

67+
def using_source_path(path)
68+
source_paths.unshift path
69+
yield
70+
ensure
71+
# Remove our path munging
72+
source_paths.shift
73+
end
74+
5975
# Generally polluting `main` is bad as it monkey patches all objects. In this
6076
# context, `self` is an _instance_ of a `Rails::Generators::AppGenerator`. So
6177
# this won't pollute anything.
@@ -68,32 +84,7 @@ def generate(*)
6884
generate('controller welcome index') # singular
6985
generate('integration_test widgets')
7086
generate('mailer Notifications signup')
71-
if ::RSpec::Rails::FeatureCheck.has_action_mailer_preview?
72-
create_file "spec/support/default_preview_path.rb", <<-EOS.strip_heredoc
73-
ENV['RAILS_ENV'] = 'development'
74-
75-
CONFIG_PATH = File.expand_path('../../../config', __FILE__)
76-
APP_PATH = File.expand_path(File.join(CONFIG_PATH, 'application'))
77-
# Default rails setup
78-
require File.join(CONFIG_PATH, 'boot')
79-
require 'rails/all'
80-
require File.join(CONFIG_PATH, 'environment')
81-
82-
puts Rails.application.config.action_mailer.preview_path
83-
EOS
84-
create_file "spec/verify_mailer_preview_path_spec.rb", <<-EOS.strip_heredoc
85-
RSpec.describe 'Verifying the railtie sets the preview path' do
86-
it 'is set to the rspec path' do
87-
exec_script = File.expand_path(
88-
File.join(__FILE__, '../support/default_preview_path.rb')
89-
)
90-
expect(%x(ruby #\{exec_script\}).chomp).to eq(
91-
"#\{::Rails.root\}/spec/mailers/previews"
92-
)
93-
end
94-
end
95-
EOS
96-
end
87+
9788
generate('model thing name:string')
9889
generate('helper things')
9990
generate('scaffold widget name:string category:string instock:boolean foo_id:integer bar_id:integer --force')
@@ -113,6 +104,9 @@ def generate(*)
113104
"This is a template for a custom action.",
114105
:force => true
115106

107+
# Use the absolute path so we can load it without active record too
108+
apply File.join(DEFAULT_SOURCE_PATH, 'generate_action_mailer_specs.rb')
109+
116110
gsub_file 'spec/spec_helper.rb', /^=(begin|end)/, ''
117111

118112
# Warnings are too noisy in the sample apps
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/usr/bin/env ruby
2+
# Transparent helper to simply document code sections
3+
def require_file_stub(name)
4+
yield
5+
end
6+
7+
ENV['RAILS_ENV'] ||= 'development'
8+
9+
require_file_stub 'config/environment' do
10+
# Load the Rails application.
11+
require_file_stub 'config/application' do
12+
require_file_stub 'config/boot' do
13+
# Set up gems listed in the Gemfile.
14+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
15+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
16+
end
17+
18+
# Pick the frameworks you want:
19+
require "active_record/railtie"
20+
require "action_controller/railtie"
21+
require "action_mailer/railtie" unless ENV['NO_ACTION_MAILER']
22+
require "action_view/railtie"
23+
24+
# Require the gems listed in Gemfile, including any gems
25+
# you've limited to :test, :development, or :production.
26+
if Rails::VERSION::STRING.to_f < 3.1
27+
Bundler.require(:default, Rails.env)
28+
else
29+
Bundler.require(*Rails.groups)
30+
end
31+
32+
module ExampleApp
33+
class Application < Rails::Application
34+
config.eager_load = false
35+
36+
# Don't care if the mailer can't send.
37+
config.action_mailer.raise_delivery_errors = false unless ENV['NO_ACTION_MAILER']
38+
39+
if ENV['CUSTOM_PREVIEW_PATH']
40+
config.action_mailer.preview_path = ENV['CUSTOM_PREVIEW_PATH']
41+
end
42+
if ENV['SHOW_PREVIEWS']
43+
config.action_mailer.show_previews = (ENV['SHOW_PREVIEWS'] == 'true')
44+
end
45+
end
46+
end
47+
48+
I18n.enforce_available_locales = true if I18n.respond_to?(:enforce_available_locales)
49+
end
50+
51+
# Initialize the Rails application.
52+
Rails.application.initialize!
53+
end
54+
55+
exit if ENV['NO_ACTION_MAILER']
56+
if ENV['DEFAULT_URL']
57+
puts ActionMailer::Base.default_url_options[:host]
58+
elsif defined?(::ActionMailer::Preview)
59+
puts Rails.application.config.action_mailer.preview_path
60+
end
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
require 'rails_helper'
2+
require 'rspec/rails/feature_check'
3+
4+
RSpec.describe 'Action Mailer railtie hook' do
5+
CaptureExec = Struct.new(:io, :exit_status) do
6+
def ==(str)
7+
io == str
8+
end
9+
end
10+
11+
def capture_exec(*ops)
12+
io = if RUBY_VERSION.to_f < 1.9
13+
IO.popen(ops.join(' '))
14+
else
15+
ops << { :err => [:child, :out] }
16+
IO.popen(ops)
17+
end
18+
# Necessary to ignore warnings from Rails code base
19+
out = io.readlines.reject { |line|
20+
line =~ /warning: circular argument reference/
21+
}.join.chomp
22+
CaptureExec.new(out, $?.exitstatus)
23+
end
24+
25+
def have_no_preview
26+
have_attributes(:io => be_blank, :exit_status => 0)
27+
end
28+
29+
let(:exec_script) {
30+
File.expand_path(File.join(__FILE__, '../support/default_preview_path'))
31+
}
32+
33+
if RSpec::Rails::FeatureCheck.has_action_mailer_show_preview?
34+
context 'in the development environment' do
35+
let(:custom_env) { { 'RAILS_ENV' => rails_env } }
36+
let(:rails_env) { 'development' }
37+
38+
it 'sets the preview path to the default rspec path' do
39+
expect(capture_exec(custom_env, exec_script)).to eq(
40+
"#{::Rails.root}/spec/mailers/previews"
41+
)
42+
end
43+
44+
it 'respects the setting from `show_previews`' do
45+
expect(
46+
capture_exec(
47+
custom_env.merge('SHOW_PREVIEWS' => 'false'),
48+
exec_script
49+
)
50+
).to have_no_preview
51+
end
52+
53+
it 'respects a custom `preview_path`' do
54+
expect(
55+
capture_exec(
56+
custom_env.merge('CUSTOM_PREVIEW_PATH' => '/custom/path'),
57+
exec_script
58+
)
59+
).to eq('/custom/path')
60+
end
61+
62+
it 'allows initializers to set options' do
63+
expect(
64+
capture_exec(
65+
custom_env.merge('DEFAULT_URL' => 'test-host'),
66+
exec_script
67+
)
68+
).to eq('test-host')
69+
end
70+
71+
it 'handles action mailer not being available' do
72+
expect(
73+
capture_exec(
74+
custom_env.merge('NO_ACTION_MAILER' => 'true'),
75+
exec_script
76+
)
77+
).to have_no_preview
78+
end
79+
end
80+
81+
context 'in a non-development environment' do
82+
let(:custom_env) { { 'RAILS_ENV' => rails_env } }
83+
let(:rails_env) { 'test' }
84+
85+
it 'does not set the preview path by default' do
86+
expect(capture_exec(custom_env, exec_script)).to have_no_preview
87+
end
88+
89+
it 'respects the setting from `show_previews`' do
90+
expect(
91+
capture_exec(custom_env.merge('SHOW_PREVIEWS' => 'true'), exec_script)
92+
).to eq("#{::Rails.root}/spec/mailers/previews")
93+
end
94+
95+
it 'allows initializers to set options' do
96+
expect(
97+
capture_exec(
98+
custom_env.merge('DEFAULT_URL' => 'test-host'),
99+
exec_script
100+
)
101+
).to eq('test-host')
102+
end
103+
104+
it 'handles action mailer not being available' do
105+
expect(
106+
capture_exec(
107+
custom_env.merge('NO_ACTION_MAILER' => 'true'),
108+
exec_script
109+
)
110+
).to have_no_preview
111+
end
112+
end
113+
elsif RSpec::Rails::FeatureCheck.has_action_mailer_preview?
114+
context 'in the development environment', 'without `show_previews`' do
115+
let(:custom_env) { { 'RAILS_ENV' => rails_env } }
116+
let(:rails_env) { 'development' }
117+
118+
it 'sets the preview path to the default rspec path' do
119+
expect(capture_exec(custom_env, exec_script)).to eq(
120+
"#{::Rails.root}/spec/mailers/previews"
121+
)
122+
end
123+
124+
it 'respects a custom `preview_path`' do
125+
expect(
126+
capture_exec(
127+
custom_env.merge('CUSTOM_PREVIEW_PATH' => '/custom/path'),
128+
exec_script
129+
)
130+
).to eq('/custom/path')
131+
end
132+
133+
it 'allows initializers to set options' do
134+
expect(
135+
capture_exec(
136+
custom_env.merge('DEFAULT_URL' => 'test-host'),
137+
exec_script
138+
)
139+
).to eq('test-host')
140+
end
141+
142+
it 'handles action mailer not being available' do
143+
expect(
144+
capture_exec(
145+
custom_env.merge('NO_ACTION_MAILER' => 'true'),
146+
exec_script
147+
)
148+
).to have_no_preview
149+
end
150+
end
151+
152+
context 'in a non-development environment', 'without `show_previews`' do
153+
let(:custom_env) { { 'RAILS_ENV' => rails_env } }
154+
let(:rails_env) { 'test' }
155+
156+
it 'does not set the preview path by default' do
157+
expect(capture_exec(custom_env, exec_script)).to have_no_preview
158+
end
159+
160+
it 'respects a custom `preview_path`' do
161+
expect(
162+
capture_exec(
163+
custom_env.merge('CUSTOM_PREVIEW_PATH' => '/custom/path'),
164+
exec_script
165+
)
166+
).to eq('/custom/path')
167+
end
168+
169+
it 'handles action mailer not being available' do
170+
expect(
171+
capture_exec(
172+
custom_env.merge('NO_ACTION_MAILER' => 'true'),
173+
exec_script
174+
)
175+
).to have_no_preview
176+
end
177+
end
178+
else
179+
it 'handles no action mailer preview' do
180+
expect(capture_exec(exec_script)).to have_no_preview
181+
end
182+
end
183+
end

0 commit comments

Comments
 (0)