diff options
Diffstat (limited to 'actionmailer')
-rw-r--r-- | actionmailer/CHANGELOG.md | 13 | ||||
-rw-r--r-- | actionmailer/actionmailer.gemspec | 1 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer.rb | 2 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/base.rb | 8 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/delivery_job.rb | 11 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/message_delivery.rb | 45 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/preview.rb | 2 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/test_case.rb | 7 | ||||
-rw-r--r-- | actionmailer/test/abstract_unit.rb | 7 | ||||
-rw-r--r-- | actionmailer/test/assert_select_email_test.rb | 47 | ||||
-rw-r--r-- | actionmailer/test/base_test.rb | 8 | ||||
-rw-r--r-- | actionmailer/test/mailers/delayed_mailer.rb | 6 | ||||
-rw-r--r-- | actionmailer/test/message_delivery_test.rb | 82 |
13 files changed, 225 insertions, 14 deletions
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index ab93745f60..e6952a4b3b 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,16 @@ +* Added #deliver_later in addition to #deliver, which will enqueue a job to render and + deliver the mail instead of delivering it right at that moment. The job is enqueued + using the new Active Job framework in Rails, and will use whatever queue is configured for Rails. + + *DHH/Abdelkader Boudih/Cristian Bica* + + +* Make ActionMailer::Previews methods class methods. Previously they were + instance methods and ActionMailer tries to render a message when they + are called. + + *Cristian Bica* + * Deprecate `*_path` helpers in email views. When used they generate non-working links and are not the intention of most developers. Instead we recommend to use `*_url` helper. diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index 01d97b7213..8452348e11 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -23,4 +23,5 @@ Gem::Specification.new do |s| s.add_dependency 'actionview', version s.add_dependency 'mail', ['~> 2.5', '>= 2.5.4'] + s.add_dependency 'rails-dom-testing' end diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 83969d4074..b994ef3182 100644 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -45,4 +45,6 @@ module ActionMailer autoload :Previews, 'action_mailer/preview' autoload :TestCase autoload :TestHelper + autoload :MessageDelivery + autoload :DeliveryJob end diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index bc540aece0..9aae14ec8c 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -548,8 +548,8 @@ module ActionMailer end def method_missing(method_name, *args) # :nodoc: - if respond_to?(method_name) - new(method_name, *args).message + if action_methods.include?(method_name.to_s) + MessageDelivery.new(self, method_name, *args) else super end @@ -586,6 +586,10 @@ module ActionMailer class NullMail #:nodoc: def body; '' end + def respond_to?(string, include_all=false) + true + end + def method_missing(*args) nil end diff --git a/actionmailer/lib/action_mailer/delivery_job.rb b/actionmailer/lib/action_mailer/delivery_job.rb new file mode 100644 index 0000000000..b2cfa245fd --- /dev/null +++ b/actionmailer/lib/action_mailer/delivery_job.rb @@ -0,0 +1,11 @@ +require 'active_job' + +module ActionMailer + class DeliveryJob < ActiveJob::Base + queue_as :mailers + + def perform(mailer, mail_method, delivery_method, *args) + mailer.constantize.public_send(mail_method, *args).send(delivery_method) + end + end +end diff --git a/actionmailer/lib/action_mailer/message_delivery.rb b/actionmailer/lib/action_mailer/message_delivery.rb new file mode 100644 index 0000000000..80a0517bff --- /dev/null +++ b/actionmailer/lib/action_mailer/message_delivery.rb @@ -0,0 +1,45 @@ +require 'delegate' + +module ActionMailer + class MessageDelivery < Delegator + def initialize(mailer, mail_method, *args) + @mailer = mailer + @mail_method = mail_method + @args = args + end + + def __getobj__ + @obj ||= @mailer.send(:new, @mail_method, *@args).message + end + + def __setobj__(obj) + @obj = obj + end + + def message #:nodoc: + __getobj__ + end + + def deliver_later!(options={}) + enqueue_delivery :deliver!, options + end + + def deliver_later(options={}) + enqueue_delivery :deliver, options + end + + private + def enqueue_delivery(delivery_method, options={}) + args = @mailer.name, @mail_method.to_s, delivery_method.to_s, *@args + enqueue_method = :enqueue + if options[:at] + enqueue_method = :enqueue_at + args.unshift options[:at] + elsif options[:in] + enqueue_method = :enqueue_in + args.unshift options[:in] + end + ActionMailer::DeliveryJob.send enqueue_method, *args + end + end +end diff --git a/actionmailer/lib/action_mailer/preview.rb b/actionmailer/lib/action_mailer/preview.rb index 33de1dc049..44cf6665ba 100644 --- a/actionmailer/lib/action_mailer/preview.rb +++ b/actionmailer/lib/action_mailer/preview.rb @@ -22,7 +22,9 @@ module ActionMailer # :nodoc: mattr_accessor :preview_interceptors, instance_writer: false self.preview_interceptors = [] + end + module ClassMethods # Register one or more Interceptors which will be called before mail is previewed. def register_preview_interceptors(*interceptors) interceptors.flatten.compact.each { |interceptor| register_preview_interceptor(interceptor) } diff --git a/actionmailer/lib/action_mailer/test_case.rb b/actionmailer/lib/action_mailer/test_case.rb index a5442c0316..d507032838 100644 --- a/actionmailer/lib/action_mailer/test_case.rb +++ b/actionmailer/lib/action_mailer/test_case.rb @@ -1,4 +1,5 @@ require 'active_support/test_case' +require 'rails-dom-testing' module ActionMailer class NonInferrableMailerError < ::StandardError @@ -15,6 +16,7 @@ module ActionMailer include ActiveSupport::Testing::ConstantLookup include TestHelper + include Rails::Dom::Testing::Assertions::SelectorAssertions included do class_attribute :_mailer_class @@ -55,14 +57,13 @@ module ActionMailer protected def initialize_test_deliveries - @old_delivery_method = ActionMailer::Base.delivery_method + set_delivery_method :test @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 + restore_delivery_method ActionMailer::Base.perform_deliveries = @old_perform_deliveries ActionMailer::Base.deliveries.clear end diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index 1281b1bcfc..c549545674 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -26,7 +26,7 @@ I18n.enforce_available_locales = false FIXTURE_LOAD_PATH = File.expand_path('fixtures', File.dirname(__FILE__)) ActionMailer::Base.view_paths = FIXTURE_LOAD_PATH -class Rails +module Rails def self.root File.expand_path('../', File.dirname(__FILE__)) end @@ -51,8 +51,3 @@ def jruby_skip(message = '') end require 'mocha/setup' # FIXME: stop using mocha - -# FIXME: we have tests that depend on run order, we should fix that and -# remove this method call. -require 'active_support/test_case' -ActiveSupport::TestCase.my_tests_are_order_dependent! diff --git a/actionmailer/test/assert_select_email_test.rb b/actionmailer/test/assert_select_email_test.rb new file mode 100644 index 0000000000..57ae3436e1 --- /dev/null +++ b/actionmailer/test/assert_select_email_test.rb @@ -0,0 +1,47 @@ +require 'abstract_unit' + +class AssertSelectEmailTest < ActionMailer::TestCase + class AssertSelectMailer < ActionMailer::Base + def test(html) + mail body: html, content_type: "text/html", + subject: "Test e-mail", from: "test@test.host", to: "test <test@test.host>" + end + end + + class AssertMultipartSelectMailer < ActionMailer::Base + def test(options) + mail subject: "Test e-mail", from: "test@test.host", to: "test <test@test.host>" do |format| + format.text { render text: options[:text] } + format.html { render text: options[:html] } + end + end + end + + # + # Test assert_select_email + # + + def test_assert_select_email + assert_raise ActiveSupport::TestCase::Assertion do + assert_select_email {} + end + + AssertSelectMailer.test("<div><p>foo</p><p>bar</p></div>").deliver + assert_select_email do + assert_select "div:root" do + assert_select "p:first-child", "foo" + assert_select "p:last-child", "bar" + end + end + end + + def test_assert_select_email_multipart + AssertMultipartSelectMailer.test(html: "<div><p>foo</p><p>bar</p></div>", text: 'foo bar').deliver + assert_select_email do + assert_select "div:root" do + assert_select "p:first-child", "foo" + assert_select "p:last-child", "bar" + end + end + end +end diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index 6116d1e29f..fc24639bf4 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -11,6 +11,8 @@ require 'mailers/asset_mailer' class BaseTest < ActiveSupport::TestCase setup do + @original_delivery_method = ActionMailer::Base.delivery_method + ActionMailer::Base.delivery_method = :test @original_asset_host = ActionMailer::Base.asset_host @original_assets_dir = ActionMailer::Base.assets_dir end @@ -19,6 +21,7 @@ class BaseTest < ActiveSupport::TestCase ActionMailer::Base.asset_host = @original_asset_host ActionMailer::Base.assets_dir = @original_assets_dir BaseMailer.deliveries.clear + ActionMailer::Base.delivery_method = @original_delivery_method end test "method call to mail does not raise error" do @@ -240,7 +243,7 @@ class BaseTest < ActiveSupport::TestCase end end - e = assert_raises(RuntimeError) { LateAttachmentMailer.welcome } + e = assert_raises(RuntimeError) { LateAttachmentMailer.welcome.message } assert_match(/Can't add attachments after `mail` was called./, e.message) end @@ -252,7 +255,7 @@ class BaseTest < ActiveSupport::TestCase end end - e = assert_raises(RuntimeError) { LateInlineAttachmentMailer.welcome } + e = assert_raises(RuntimeError) { LateInlineAttachmentMailer.welcome.message } assert_match(/Can't add attachments after `mail` was called./, e.message) end @@ -468,7 +471,6 @@ class BaseTest < ActiveSupport::TestCase end test "calling deliver on the action should increment the deliveries collection if using the test mailer" do - BaseMailer.delivery_method = :test BaseMailer.welcome.deliver assert_equal(1, BaseMailer.deliveries.length) end diff --git a/actionmailer/test/mailers/delayed_mailer.rb b/actionmailer/test/mailers/delayed_mailer.rb new file mode 100644 index 0000000000..62d4baa434 --- /dev/null +++ b/actionmailer/test/mailers/delayed_mailer.rb @@ -0,0 +1,6 @@ +class DelayedMailer < ActionMailer::Base + + def test_message(*) + mail(from: 'test-sender@test.com', to: 'test-receiver@test.com', subject: 'Test Subject', body: 'Test Body') + end +end diff --git a/actionmailer/test/message_delivery_test.rb b/actionmailer/test/message_delivery_test.rb new file mode 100644 index 0000000000..a097d0e84d --- /dev/null +++ b/actionmailer/test/message_delivery_test.rb @@ -0,0 +1,82 @@ +# encoding: utf-8 +gem 'activejob' +require 'active_job' +require 'abstract_unit' +require 'minitest/mock' +require_relative 'mailers/delayed_mailer' + +class MessageDeliveryTest < ActiveSupport::TestCase + + setup do + @previous_logger = ActiveJob::Base.logger + @previous_delivery_method = ActionMailer::Base.delivery_method + ActionMailer::Base.delivery_method = :test + ActiveJob::Base.logger = Logger.new(nil) + @mail = DelayedMailer.test_message(1, 2, 3) + ActionMailer::Base.deliveries.clear + end + + teardown do + ActiveJob::Base.logger = @previous_logger + ActionMailer::Base.delivery_method = @previous_delivery_method + end + + test 'should have a message' do + assert @mail.message + end + + test 'its message should be a Mail::Message' do + assert_equal Mail::Message , @mail.message.class + end + + test 'should respond to .deliver' do + assert_respond_to @mail, :deliver + end + + test 'should respond to .deliver!' do + assert_respond_to @mail, :deliver! + end + + test 'should respond to .deliver_later' do + assert_respond_to @mail, :deliver_later + end + + test 'should respond to .deliver_later!' do + assert_respond_to @mail, :deliver_later! + end + + test 'should enqueue and run correctly in activejob' do + @mail.deliver_later! + assert_equal 1 , ActionMailer::Base.deliveries.size + end + + test 'should enqueue the email with :deliver delivery method' do + ret = ActionMailer::DeliveryJob.stub :enqueue, ->(*args){ args } do + @mail.deliver_later + end + assert_equal ['DelayedMailer', 'test_message', 'deliver', 1, 2, 3], ret + end + + test 'should enqueue the email with :deliver! delivery method' do + ret = ActionMailer::DeliveryJob.stub :enqueue, ->(*args){ args } do + @mail.deliver_later! + end + assert_equal ['DelayedMailer', 'test_message', 'deliver!', 1, 2, 3], ret + end + + test 'should enqueue a delivery with a delay' do + ret = ActionMailer::DeliveryJob.stub :enqueue_in, ->(*args){ args } do + @mail.deliver_later in: 600 + end + assert_equal [600, 'DelayedMailer', 'test_message', 'deliver', 1, 2, 3], ret + end + + test 'should enqueue a delivery at a specific time' do + later_time = Time.now.to_i + 3600 + ret = ActionMailer::DeliveryJob.stub :enqueue_at, ->(*args){ args } do + @mail.deliver_later at: later_time + end + assert_equal [later_time, 'DelayedMailer', 'test_message', 'deliver', 1, 2, 3], ret + end + +end |