rails/actionmailer/lib/action_mailer/test_case.rb
Zuhao Wan c4f4123ef4 Restore test deliveries properly in ActionMailer.
`ActionMailer::Base.delivery_method` and
`ActionMailer::Base.perform_deliveries` have leaked states.

"delivery method can be customized per instance" and "delivery method
can be customized in subclasses not changing the parent" in
delivery_methods_test.rb will fail if test_helper_test.rb (in which
TestHelperMailerTest is inherited from ActionMailer::TestCase) runs
before it.
2014-06-07 00:11:24 +08:00

94 lines
2.5 KiB
Ruby

require 'active_support/test_case'
module ActionMailer
class NonInferrableMailerError < ::StandardError
def initialize(name)
super "Unable to determine the mailer to test from #{name}. " +
"You'll need to specify it using tests YourMailer in your " +
"test case definition"
end
end
class TestCase < ActiveSupport::TestCase
module Behavior
extend ActiveSupport::Concern
include ActiveSupport::Testing::ConstantLookup
include TestHelper
included do
class_attribute :_mailer_class
setup :initialize_test_deliveries
setup :set_expected_mail
teardown :restore_test_deliveries
end
module ClassMethods
def tests(mailer)
case mailer
when String, Symbol
self._mailer_class = mailer.to_s.camelize.constantize
when Module
self._mailer_class = mailer
else
raise NonInferrableMailerError.new(mailer)
end
end
def mailer_class
if mailer = self._mailer_class
mailer
else
tests determine_default_mailer(name)
end
end
def determine_default_mailer(name)
mailer = determine_constant_from_test_name(name) do |constant|
Class === constant && constant < ActionMailer::Base
end
raise NonInferrableMailerError.new(name) if mailer.nil?
mailer
end
end
protected
def initialize_test_deliveries
@old_delivery_method = ActionMailer::Base.delivery_method
@old_perform_deliveries = ActionMailer::Base.perform_deliveries
ActionMailer::Base.delivery_method = :test
ActionMailer::Base.perform_deliveries = true
end
def restore_test_deliveries
ActionMailer::Base.delivery_method = @old_delivery_method
ActionMailer::Base.perform_deliveries = @old_perform_deliveries
ActionMailer::Base.deliveries.clear
end
def set_expected_mail
@expected = Mail.new
@expected.content_type ["text", "plain", { "charset" => charset }]
@expected.mime_version = '1.0'
end
private
def charset
"UTF-8"
end
def encode(subject)
Mail::Encodings.q_value_encode(subject, charset)
end
def read_fixture(action)
IO.readlines(File.join(Rails.root, 'test', 'fixtures', self.class.mailer_class.name.underscore, action))
end
end
include Behavior
end
end