diff options
Diffstat (limited to 'actionmailer')
23 files changed, 598 insertions, 224 deletions
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index dc8c6bdf74..4e3a9daf7d 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,14 +1,17 @@ -* Instrument the generation of Action Mailer messages. The time it takes to - generate a message is written to the log. +* Add `config.action_mailer.show_previews` configuration option. - *Daniel Schierbeck* + This config option can be used to enable the mail preview in environments + other than development (such as staging). -* Invoke mailer defaults as procs only if they are procs, do not convert with - `to_proc`. That an object is convertible to a proc does not mean it's meant - to be always used as a proc. + Defaults to `true` in development and false elsewhere. - Fixes #11533. + *Leonard Garvey* - *Alex Tsukernik* +* Allow preview interceptors to be registered through + `config.action_mailer.preview_interceptors`. -Please check [4-0-stable](https://github.com/rails/rails/blob/4-0-stable/actionmailer/CHANGELOG.md) for previous changes. + See #15739. + + *Yves Senn* + +Please check [4-1-stable](https://github.com/rails/rails/blob/4-1-stable/actionmailer/CHANGELOG.md) for previous changes. diff --git a/actionmailer/MIT-LICENSE b/actionmailer/MIT-LICENSE index 5c668d9624..d58dd9ed9b 100644 --- a/actionmailer/MIT-LICENSE +++ b/actionmailer/MIT-LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2013 David Heinemeier Hansson +Copyright (c) 2004-2014 David Heinemeier Hansson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/actionmailer/README.rdoc b/actionmailer/README.rdoc index 96dd0b1a2e..ceca912ada 100644 --- a/actionmailer/README.rdoc +++ b/actionmailer/README.rdoc @@ -74,7 +74,7 @@ Or you can just chain the methods together like: == Setting defaults -It is possible to set default values that will be used in every method in your Action Mailer class. To implement this functionality, you just call the public class method <tt>default</tt> which you get for free from ActionMailer::Base. This method accepts a Hash as the parameter. You can use any of the headers e-mail messages has, like <tt>:from</tt> as the key. You can also pass in a string as the key, like "Content-Type", but Action Mailer does this out of the box for you, so you won't need to worry about that. Finally, it is also possible to pass in a Proc that will get evaluated when it is needed. +It is possible to set default values that will be used in every method in your Action Mailer class. To implement this functionality, you just call the public class method <tt>default</tt> which you get for free from <tt>ActionMailer::Base</tt>. This method accepts a Hash as the parameter. You can use any of the headers email messages have, like <tt>:from</tt> as the key. You can also pass in a string as the key, like "Content-Type", but Action Mailer does this out of the box for you, so you won't need to worry about that. Finally, it is also possible to pass in a Proc that will get evaluated when it is needed. Note that every value you set with this method will get overwritten if you use the same key in your mailer method. @@ -102,7 +102,7 @@ Example: ) if email.has_attachments? - email.attachments.each do |attachment| + email.attachments.each do |attachment| page.attachments.create({ file: attachment, description: email.subject }) @@ -156,7 +156,11 @@ API documentation is at * http://api.rubyonrails.org -Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here: +Bug reports can be filed for the Ruby on Rails project here: * https://github.com/rails/rails/issues +Feature requests should be discussed on the rails-core mailing list here: + +* https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core + diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec index 9b25feaf75..01d97b7213 100644 --- a/actionmailer/actionmailer.gemspec +++ b/actionmailer/actionmailer.gemspec @@ -22,5 +22,5 @@ Gem::Specification.new do |s| s.add_dependency 'actionpack', version s.add_dependency 'actionview', version - s.add_dependency 'mail', '~> 2.5.4' + s.add_dependency 'mail', ['~> 2.5', '>= 2.5.4'] end diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 5b6960c8fc..83969d4074 100644 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -1,5 +1,5 @@ #-- -# Copyright (c) 2004-2013 David Heinemeier Hansson +# Copyright (c) 2004-2014 David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -41,6 +41,8 @@ module ActionMailer autoload :Base autoload :DeliveryMethods autoload :MailHelper + autoload :Preview + autoload :Previews, 'action_mailer/preview' autoload :TestCase autoload :TestHelper end diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 501fee55aa..135cf35ac0 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -50,8 +50,8 @@ module ActionMailer # # * <tt>mail</tt> - Allows you to specify email to be sent. # - # The hash passed to the mail method allows you to specify any header that a Mail::Message - # will accept (any valid Email header including optional fields). + # The hash passed to the mail method allows you to specify any header that a <tt>Mail::Message</tt> + # will accept (any valid email header including optional fields). # # The mail method, if not passed a block, will inspect your views and send all the views with # the same name as the method, so the above action would send the +welcome.text.erb+ view @@ -94,7 +94,7 @@ module ActionMailer # Hi <%= @account.name %>, # Thanks for joining our service! Please check back often. # - # You can even use Action Pack helpers in these views. For example: + # You can even use Action View helpers in these views. For example: # # You got a new note! # <%= truncate(@note.body, length: 25) %> @@ -154,7 +154,7 @@ module ActionMailer # * signup_notification.text.erb # * signup_notification.html.erb # * signup_notification.xml.builder - # * signup_notification.yaml.erb + # * signup_notification.yml.erb # # Each would be rendered and added as a separate part to the message, with the corresponding content # type. The content type for the entire message is automatically set to <tt>multipart/alternative</tt>, @@ -229,7 +229,7 @@ module ActionMailer # An interceptor class must implement the <tt>:delivering_email(message)</tt> method which will be # called before the email is sent, allowing you to make modifications to the email before it hits # the delivery agents. Your class should make any needed modifications directly to the passed - # in Mail::Message instance. + # in <tt>Mail::Message</tt> instance. # # = Default Hash # @@ -301,12 +301,50 @@ module ActionMailer # end # end # - # Callbacks in ActionMailer are implemented using AbstractController::Callbacks, so you - # can define and configure callbacks in the same manner that you would use callbacks in - # classes that inherit from ActionController::Base. + # Callbacks in Action Mailer are implemented using + # <tt>AbstractController::Callbacks</tt>, so you can define and configure + # callbacks in the same manner that you would use callbacks in classes that + # inherit from <tt>ActionController::Base</tt>. # # Note that unless you have a specific reason to do so, you should prefer using before_action - # rather than after_action in your ActionMailer classes so that headers are parsed properly. + # rather than after_action in your Action Mailer classes so that headers are parsed properly. + # + # = Previewing emails + # + # You can preview your email templates visually by adding a mailer preview file to the + # <tt>ActionMailer::Base.preview_path</tt>. Since most emails do something interesting + # with database data, you'll need to write some scenarios to load messages with fake data: + # + # class NotifierPreview < ActionMailer::Preview + # def welcome + # Notifier.welcome(User.first) + # end + # end + # + # Methods must return a <tt>Mail::Message</tt> object which can be generated by calling the mailer + # method without the additional <tt>deliver</tt>. The location of the mailer previews + # directory can be configured using the <tt>preview_path</tt> option which has a default + # of <tt>test/mailers/previews</tt>: + # + # config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews" + # + # An overview of all previews is accessible at <tt>http://localhost:3000/rails/mailers</tt> + # on a running development server instance. + # + # Previews can also be intercepted in a similar manner as deliveries can be by registering + # a preview interceptor that has a <tt>previewing_email</tt> method: + # + # class CssInlineStyler + # def self.previewing_email(message) + # # inline CSS styles + # end + # end + # + # config.action_mailer.preview_interceptors :css_inline_styler + # + # Note that interceptors need to be registered both with <tt>register_interceptor</tt> + # and <tt>register_preview_interceptor</tt> if they should operate on both sending and + # previewing emails. # # = Configuration options # @@ -317,7 +355,7 @@ module ActionMailer # per the above section. # # * <tt>logger</tt> - the logger is used for generating information on the mailing run if available. - # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. + # Can be set to +nil+ for no logging. Compatible with both Ruby's own +Logger+ and Log4r loggers. # # * <tt>smtp_settings</tt> - Allows detailed configuration for <tt>:smtp</tt> delivery method: # * <tt>:address</tt> - Allows you to use a remote mail server. Just change it from its default @@ -331,12 +369,13 @@ module ActionMailer # This is a symbol and one of <tt>:plain</tt> (will send the password in the clear), <tt>:login</tt> (will # send password Base64 encoded) or <tt>:cram_md5</tt> (combines a Challenge/Response mechanism to exchange # information and a cryptographic Message Digest 5 algorithm to hash important information) - # * <tt>:enable_starttls_auto</tt> - When set to true, detects if STARTTLS is enabled in your SMTP server - # and starts to use it. + # * <tt>:enable_starttls_auto</tt> - Detects if STARTTLS is enabled in your SMTP server and starts + # to use it. Defaults to <tt>true</tt>. # * <tt>:openssl_verify_mode</tt> - When using TLS, you can set how OpenSSL checks the certificate. This is # really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name - # of an OpenSSL verify constant ('none', 'peer', 'client_once', 'fail_if_no_peer_cert') or directly the - # constant (OpenSSL::SSL::VERIFY_NONE, OpenSSL::SSL::VERIFY_PEER, ...). + # of an OpenSSL verify constant (<tt>'none'</tt>, <tt>'peer'</tt>, <tt>'client_once'</tt>, + # <tt>'fail_if_no_peer_cert'</tt>) or directly the constant (<tt>OpenSSL::SSL::VERIFY_NONE</tt>, + # <tt>OpenSSL::SSL::VERIFY_PEER</tt>, ...). # # * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method. # * <tt>:location</tt> - The location of the sendmail executable. Defaults to <tt>/usr/sbin/sendmail</tt>. @@ -351,7 +390,7 @@ module ActionMailer # # * <tt>delivery_method</tt> - Defines a delivery method. Possible values are <tt>:smtp</tt> (default), # <tt>:sendmail</tt>, <tt>:test</tt>, and <tt>:file</tt>. Or you may provide a custom delivery method - # object e.g. MyOwnDeliveryMethodClass. See the Mail gem documentation on the interface you need to + # object e.g. +MyOwnDeliveryMethodClass+. See the Mail gem documentation on the interface you need to # implement for a custom delivery agent. # # * <tt>perform_deliveries</tt> - Determines whether emails are actually sent from Action Mailer when you @@ -362,6 +401,7 @@ module ActionMailer # <tt>delivery_method :test</tt>. Most useful for unit and functional testing. class Base < AbstractController::Base include DeliveryMethods + include Previews abstract! @@ -373,6 +413,8 @@ module ActionMailer include AbstractController::AssetPaths include AbstractController::Callbacks + include ActionView::Layouts + PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [:@_action_has_layout] def _protected_ivars # :nodoc: @@ -403,18 +445,30 @@ module ActionMailer end # Register an Observer which will be notified when mail is delivered. - # Either a class or a string can be passed in as the Observer. If a string is passed in - # it will be +constantize+d. + # Either a class, string or symbol can be passed in as the Observer. + # If a string or symbol is passed in it will be camelized and constantized. def register_observer(observer) - delivery_observer = (observer.is_a?(String) ? observer.constantize : observer) + delivery_observer = case observer + when String, Symbol + observer.to_s.camelize.constantize + else + observer + end + Mail.register_observer(delivery_observer) end # Register an Interceptor which will be called before mail is sent. - # Either a class or a string can be passed in as the Interceptor. If a string is passed in - # it will be <tt>constantize</tt>d. + # Either a class, string or symbol can be passed in as the Interceptor. + # If a string or symbol is passed in it will be camelized and constantized. def register_interceptor(interceptor) - delivery_interceptor = (interceptor.is_a?(String) ? interceptor.constantize : interceptor) + delivery_interceptor = case interceptor + when String, Symbol + interceptor.to_s.camelize.constantize + else + interceptor + end + Mail.register_interceptor(delivery_interceptor) end @@ -462,11 +516,11 @@ module ActionMailer end end - # Wraps an email delivery inside of ActiveSupport::Notifications instrumentation. + # Wraps an email delivery inside of <tt>ActiveSupport::Notifications</tt> instrumentation. # - # This method is actually called by the Mail::Message object itself - # through a callback when you call +:deliver+ on the Mail::Message, - # calling +deliver_mail+ directly and passing a Mail::Message will do + # This method is actually called by the <tt>Mail::Message</tt> object itself + # through a callback when you call <tt>:deliver</tt> on the <tt>Mail::Message</tt>, + # calling +deliver_mail+ directly and passing a <tt>Mail::Message</tt> will do # nothing except tell the logger you sent the email. def deliver_mail(mail) #:nodoc: ActiveSupport::Notifications.instrument("deliver.action_mailer") do |payload| @@ -542,18 +596,18 @@ module ActionMailer self.class.mailer_name end - # Allows you to pass random and unusual headers to the new Mail::Message + # Allows you to pass random and unusual headers to the new <tt>Mail::Message</tt> # object which will add them to itself. # # headers['X-Special-Domain-Specific-Header'] = "SecretValue" # # You can also pass a hash into headers of header field names and values, - # which will then be set on the Mail::Message object: + # which will then be set on the <tt>Mail::Message</tt> object: # # headers 'X-Special-Domain-Specific-Header' => "SecretValue", # 'In-Reply-To' => incoming.message_id # - # The resulting Mail::Message will have the following in its header: + # The resulting <tt>Mail::Message</tt> will have the following in its header: # # X-Special-Domain-Specific-Header: SecretValue def headers(args = nil) @@ -642,13 +696,13 @@ module ActionMailer # templates in the view paths using by default the mailer name and the # method name that it is being called from, it will then create parts for # each of these templates intelligently, making educated guesses on correct - # content type and sequence, and return a fully prepared Mail::Message - # ready to call +:deliver+ on to send. + # content type and sequence, and return a fully prepared <tt>Mail::Message</tt> + # ready to call <tt>:deliver</tt> on to send. # # For example: # # class Notifier < ActionMailer::Base - # default from: 'no-reply@test.lindsaar.net', + # default from: 'no-reply@test.lindsaar.net' # # def welcome # mail(to: 'mikel@test.lindsaar.net') @@ -671,11 +725,11 @@ module ActionMailer # format.html # end # - # You can even render text directly without using a template: + # You can even render plain text directly without using a template: # # mail(to: 'mikel@test.lindsaar.net') do |format| - # format.text { render text: "Hello Mikel!" } - # format.html { render text: "<h1>Hello Mikel!</h1>" } + # format.text { render plain: "Hello Mikel!" } + # format.html { render html: "<h1>Hello Mikel!</h1>".html_safe } # end # # Which will render a +multipart/alternative+ email with +text/plain+ and @@ -689,6 +743,8 @@ module ActionMailer # end # def mail(headers = {}, &block) + return @_message if @_mail_was_called && headers.blank? && !block + @_mail_was_called = true m = @_message @@ -709,7 +765,7 @@ module ActionMailer m.charset = charset = headers[:charset] # Set configure delivery behavior - wrap_delivery_behavior!(headers.delete(:delivery_method),headers.delete(:delivery_method_options)) + wrap_delivery_behavior!(headers.delete(:delivery_method), headers.delete(:delivery_method_options)) # Assign all headers except parts_order, content_type and body assignable = headers.except(:parts_order, :content_type, :body, :template_name, :template_path) diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb new file mode 100644 index 0000000000..b564813ccf --- /dev/null +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -0,0 +1,15 @@ +module ActionMailer + # Returns the version of the currently loaded ActionMailer as a <tt>Gem::Version</tt> + def self.gem_version + Gem::Version.new VERSION::STRING + end + + module VERSION + MAJOR = 4 + MINOR = 2 + TINY = 0 + PRE = "alpha" + + STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") + end +end diff --git a/actionmailer/lib/action_mailer/log_subscriber.rb b/actionmailer/lib/action_mailer/log_subscriber.rb index eb6fb11d81..e4aaab34b1 100644 --- a/actionmailer/lib/action_mailer/log_subscriber.rb +++ b/actionmailer/lib/action_mailer/log_subscriber.rb @@ -21,6 +21,7 @@ module ActionMailer # An email was generated. def process(event) + return unless logger.debug? mailer = event.payload[:mailer] action = event.payload[:action] debug("\n#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms") diff --git a/actionmailer/lib/action_mailer/mail_helper.rb b/actionmailer/lib/action_mailer/mail_helper.rb index 54ad9f066f..483277af04 100644 --- a/actionmailer/lib/action_mailer/mail_helper.rb +++ b/actionmailer/lib/action_mailer/mail_helper.rb @@ -11,8 +11,8 @@ module ActionMailer }.join("\n\n") # Make list points stand on their own line - formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" } - formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" } + formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { " #{$1} #{$2.strip}\n" } + formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { " #{$1} #{$2.strip}\n" } formatted end diff --git a/actionmailer/lib/action_mailer/preview.rb b/actionmailer/lib/action_mailer/preview.rb new file mode 100644 index 0000000000..33de1dc049 --- /dev/null +++ b/actionmailer/lib/action_mailer/preview.rb @@ -0,0 +1,116 @@ +require 'active_support/descendants_tracker' + +module ActionMailer + module Previews #:nodoc: + extend ActiveSupport::Concern + + included do + # Set the location of mailer previews through app configuration: + # + # config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews" + # + mattr_accessor :preview_path, instance_writer: false + + # Enable or disable mailer previews through app configuration: + # + # config.action_mailer.show_previews = true + # + # Defaults to true for development environment + # + mattr_accessor :show_previews, instance_writer: false + + # :nodoc: + mattr_accessor :preview_interceptors, instance_writer: false + self.preview_interceptors = [] + + # 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) } + end + + # Register an Interceptor which will be called before mail is previewed. + # Either a class or a string can be passed in as the Interceptor. If a + # string is passed in it will be <tt>constantize</tt>d. + def register_preview_interceptor(interceptor) + preview_interceptor = case interceptor + when String, Symbol + interceptor.to_s.camelize.constantize + else + interceptor + end + + unless preview_interceptors.include?(preview_interceptor) + preview_interceptors << preview_interceptor + end + end + end + end + + class Preview + extend ActiveSupport::DescendantsTracker + + class << self + # Returns all mailer preview classes + def all + load_previews if descendants.empty? + descendants + end + + # Returns the mail object for the given email name. The registered preview + # interceptors will be informed so that they can transform the message + # as they would if the mail was actually being delivered. + def call(email) + preview = self.new + message = preview.public_send(email) + inform_preview_interceptors(message) + message + end + + # Returns all of the available email previews + def emails + public_instance_methods(false).map(&:to_s).sort + end + + # Returns true if the email exists + def email_exists?(email) + emails.include?(email) + end + + # Returns true if the preview exists + def exists?(preview) + all.any?{ |p| p.preview_name == preview } + end + + # Find a mailer preview by its underscored class name + def find(preview) + all.find{ |p| p.preview_name == preview } + end + + # Returns the underscored name of the mailer preview without the suffix + def preview_name + name.sub(/Preview$/, '').underscore + end + + protected + def load_previews #:nodoc: + if preview_path + Dir["#{preview_path}/**/*_preview.rb"].each{ |file| require_dependency file } + end + end + + def preview_path #:nodoc: + Base.preview_path + end + + def show_previews #:nodoc: + Base.show_previews + end + + def inform_preview_interceptors(message) #:nodoc: + Base.preview_interceptors.each do |interceptor| + interceptor.previewing_email(message) + end + end + end + end +end diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index 7677ff3a7c..6f760732e2 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -18,6 +18,11 @@ module ActionMailer options.assets_dir ||= paths["public"].first options.javascripts_dir ||= paths["public/javascripts"].first options.stylesheets_dir ||= paths["public/stylesheets"].first + options.show_previews = Rails.env.development? if options.show_previews.nil? + + if options.show_previews + options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/mailers/previews" : nil + end # make sure readers methods get compiled options.asset_host ||= app.config.asset_host @@ -29,9 +34,17 @@ module ActionMailer include app.routes.mounted_helpers register_interceptors(options.delete(:interceptors)) + register_preview_interceptors(options.delete(:preview_interceptors)) register_observers(options.delete(:observers)) options.each { |k,v| send("#{k}=", v) } + + if options.show_previews + app.routes.append do + get '/rails/mailers' => "rails/mailers#index" + get '/rails/mailers/*path' => "rails/mailers#preview" + end + end end end @@ -40,5 +53,11 @@ module ActionMailer config.compile_methods! if config.respond_to?(:compile_methods!) end end + + config.after_initialize do + if ActionMailer::Base.preview_path + ActiveSupport::Dependencies.autoload_paths << ActionMailer::Base.preview_path + end + end end end diff --git a/actionmailer/lib/action_mailer/test_case.rb b/actionmailer/lib/action_mailer/test_case.rb index 207f949fe2..a5442c0316 100644 --- a/actionmailer/lib/action_mailer/test_case.rb +++ b/actionmailer/lib/action_mailer/test_case.rb @@ -20,6 +20,7 @@ module ActionMailer class_attribute :_mailer_class setup :initialize_test_deliveries setup :set_expected_mail + teardown :restore_test_deliveries end module ClassMethods @@ -54,8 +55,15 @@ module ActionMailer 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 diff --git a/actionmailer/lib/action_mailer/test_helper.rb b/actionmailer/lib/action_mailer/test_helper.rb index 6452bf616c..06da0dd27e 100644 --- a/actionmailer/lib/action_mailer/test_helper.rb +++ b/actionmailer/lib/action_mailer/test_helper.rb @@ -1,4 +1,6 @@ module ActionMailer + # Provides helper methods for testing Action Mailer, including #assert_emails + # and #assert_no_emails module TestHelper # Asserts that the number of emails sent matches the given number. # diff --git a/actionmailer/lib/action_mailer/version.rb b/actionmailer/lib/action_mailer/version.rb index 9d00091972..06f80a8fdc 100644 --- a/actionmailer/lib/action_mailer/version.rb +++ b/actionmailer/lib/action_mailer/version.rb @@ -1,11 +1,9 @@ +require_relative 'gem_version' + module ActionMailer - # Returns the version of the currently loaded ActionMailer as a Gem::Version + # Returns the version of the currently loaded Action Mailer as a + # <tt>Gem::Version</tt>. def self.version - Gem::Version.new "4.1.0.beta" - end - - module VERSION #:nodoc: - MAJOR, MINOR, TINY, PRE = ActionMailer.version.segments - STRING = ActionMailer.version.to_s + gem_version end end diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index aa18c512c7..93aae2807e 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -20,34 +20,15 @@ ActionMailer::Base.send(:include, ActionView::Layouts) # Show backtraces for deprecated behavior for quicker cleanup. ActiveSupport::Deprecation.debug = true -# Bogus template processors -ActionView::Template.register_template_handler :haml, lambda { |template| "Look its HAML!".inspect } -ActionView::Template.register_template_handler :bak, lambda { |template| "Lame backup".inspect } +# Disable available locale checks to avoid warnings running the test suite. +I18n.enforce_available_locales = false FIXTURE_LOAD_PATH = File.expand_path('fixtures', File.dirname(__FILE__)) ActionMailer::Base.view_paths = FIXTURE_LOAD_PATH -class MockSMTP - def self.deliveries - @@deliveries - end - - def initialize - @@deliveries = [] - end - - def sendmail(mail, from, to) - @@deliveries << [mail, from, to] - end - - def start(*args) - yield self - end -end - -class Net::SMTP - def self.new(*args) - MockSMTP.new +class Rails + def self.root + File.expand_path('../', File.dirname(__FILE__)) end end @@ -59,3 +40,12 @@ end def restore_delivery_method ActionMailer::Base.delivery_method = @old_delivery_method end + +# Skips the current run on Rubinius using Minitest::Assertions#skip +def rubinius_skip(message = '') + skip message if RUBY_ENGINE == 'rbx' +end +# Skips the current run on JRuby using Minitest::Assertions#skip +def jruby_skip(message = '') + skip message if defined?(JRUBY_VERSION) +end diff --git a/actionmailer/test/asset_host_test.rb b/actionmailer/test/asset_host_test.rb index 00f1348a53..9ba67c2842 100644 --- a/actionmailer/test/asset_host_test.rb +++ b/actionmailer/test/asset_host_test.rb @@ -31,25 +31,10 @@ class AssetHostTest < ActiveSupport::TestCase def test_asset_host_as_one_argument_proc AssetHostMailer.config.asset_host = Proc.new { |source| if source.starts_with?('/images') - "http://images.example.com" - else - "http://assets.example.com" + 'http://images.example.com' end } mail = AssetHostMailer.email_with_asset assert_equal %Q{<img alt="Somelogo" src="http://images.example.com/images/somelogo.png" />}, mail.body.to_s.strip end - - def test_asset_host_as_two_argument_proc - ActionController::Base.config.asset_host = Proc.new {|source,request| - if request && request.ssl? - "https://www.example.com" - else - "http://www.example.com" - end - } - mail = nil - assert_nothing_raised { mail = AssetHostMailer.email_with_asset } - assert_equal %Q{<img alt="Somelogo" src="http://www.example.com/images/somelogo.png" />}, mail.body.to_s.strip - end end diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index b74728ae34..229ded8e04 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -10,9 +10,15 @@ require 'mailers/proc_mailer' require 'mailers/asset_mailer' class BaseTest < ActiveSupport::TestCase - def teardown - ActionMailer::Base.asset_host = nil - ActionMailer::Base.assets_dir = nil + setup do + @original_asset_host = ActionMailer::Base.asset_host + @original_assets_dir = ActionMailer::Base.assets_dir + end + + teardown do + ActionMailer::Base.asset_host = @original_asset_host + ActionMailer::Base.assets_dir = @original_assets_dir + BaseMailer.deliveries.clear end test "method call to mail does not raise error" do @@ -103,6 +109,7 @@ class BaseTest < ActiveSupport::TestCase test "attachment gets content type from filename" do email = BaseMailer.attachment_with_content assert_equal('invoice.pdf', email.attachments[0].filename) + assert_equal('application/pdf', email.attachments[0].mime_type) end test "attachment with hash" do @@ -200,25 +207,29 @@ class BaseTest < ActiveSupport::TestCase end test "subject gets default from I18n" do - BaseMailer.default subject: nil - email = BaseMailer.welcome(subject: nil) - assert_equal "Welcome", email.subject + with_default BaseMailer, subject: nil do + email = BaseMailer.welcome(subject: nil) + assert_equal "Welcome", email.subject - I18n.backend.store_translations('en', base_mailer: {welcome: {subject: "New Subject!"}}) - email = BaseMailer.welcome(subject: nil) - assert_equal "New Subject!", email.subject + with_translation 'en', base_mailer: {welcome: {subject: "New Subject!"}} do + email = BaseMailer.welcome(subject: nil) + assert_equal "New Subject!", email.subject + end + end end test 'default subject can have interpolations' do - I18n.backend.store_translations('en', base_mailer: {with_subject_interpolations: {subject: 'Will the real %{rapper_or_impersonator} please stand up?'}}) - email = BaseMailer.with_subject_interpolations - assert_equal 'Will the real Slim Shady please stand up?', email.subject + with_translation 'en', base_mailer: {with_subject_interpolations: {subject: 'Will the real %{rapper_or_impersonator} please stand up?'}} do + email = BaseMailer.with_subject_interpolations + assert_equal 'Will the real Slim Shady please stand up?', email.subject + end end test "translations are scoped properly" do - I18n.backend.store_translations('en', base_mailer: {email_with_translations: {greet_user: "Hello %{name}!"}}) - email = BaseMailer.email_with_translations - assert_equal 'Hello lifo!', email.body.encoded + with_translation 'en', base_mailer: {email_with_translations: {greet_user: "Hello %{name}!"}} do + email = BaseMailer.email_with_translations + assert_equal 'Hello lifo!', email.body.encoded + end end # Implicit multipart @@ -406,14 +417,12 @@ class BaseTest < ActiveSupport::TestCase end test "calling just the action should return the generated mail object" do - BaseMailer.deliveries.clear email = BaseMailer.welcome assert_equal(0, BaseMailer.deliveries.length) assert_equal('The first email on new API!', email.subject) end test "calling deliver on the action should deliver the mail object" do - BaseMailer.deliveries.clear BaseMailer.expects(:deliver_mail).once mail = BaseMailer.welcome.deliver assert_equal 'The first email on new API!', mail.subject @@ -421,7 +430,6 @@ class BaseTest < ActiveSupport::TestCase test "calling deliver on the action should increment the deliveries collection if using the test mailer" do BaseMailer.delivery_method = :test - BaseMailer.deliveries.clear BaseMailer.welcome.deliver assert_equal(1, BaseMailer.deliveries.length) end @@ -441,7 +449,6 @@ class BaseTest < ActiveSupport::TestCase end test "should raise if missing template in implicit render" do - BaseMailer.deliveries.clear assert_raises ActionView::MissingTemplate do BaseMailer.implicit_different_template('missing_template').deliver end @@ -478,18 +485,17 @@ class BaseTest < ActiveSupport::TestCase end test "assets tags should use a Mailer's asset_host settings when available" do - begin - ActionMailer::Base.config.asset_host = "http://global.com" - ActionMailer::Base.config.assets_dir = "global/" + ActionMailer::Base.config.asset_host = "http://global.com" + ActionMailer::Base.config.assets_dir = "global/" - AssetMailer.asset_host = "http://local.com" + TempAssetMailer = Class.new(AssetMailer) do + self.mailer_name = "asset_mailer" + self.asset_host = "http://local.com" + end - mail = AssetMailer.welcome + mail = TempAssetMailer.welcome - assert_equal(%{<img alt="Dummy" src="http://local.com/images/dummy.png" />}, mail.body.to_s.strip) - ensure - AssetMailer.asset_host = ActionMailer::Base.config.asset_host - end + assert_equal(%{<img alt="Dummy" src="http://local.com/images/dummy.png" />}, mail.body.to_s.strip) end test 'the view is not rendered when mail was never called' do @@ -517,57 +523,87 @@ class BaseTest < ActiveSupport::TestCase end test "you can register an observer to the mail object that gets informed on email delivery" do - ActionMailer::Base.register_observer(MyObserver) - mail = BaseMailer.welcome - MyObserver.expects(:delivered_email).with(mail) - mail.deliver + mail_side_effects do + ActionMailer::Base.register_observer(MyObserver) + mail = BaseMailer.welcome + MyObserver.expects(:delivered_email).with(mail) + mail.deliver + end end test "you can register an observer using its stringified name to the mail object that gets informed on email delivery" do - ActionMailer::Base.register_observer("BaseTest::MyObserver") - mail = BaseMailer.welcome - MyObserver.expects(:delivered_email).with(mail) - mail.deliver + mail_side_effects do + ActionMailer::Base.register_observer("BaseTest::MyObserver") + mail = BaseMailer.welcome + MyObserver.expects(:delivered_email).with(mail) + mail.deliver + end + end + + test "you can register an observer using its symbolized underscored name to the mail object that gets informed on email delivery" do + mail_side_effects do + ActionMailer::Base.register_observer(:"base_test/my_observer") + mail = BaseMailer.welcome + MyObserver.expects(:delivered_email).with(mail) + mail.deliver + end end test "you can register multiple observers to the mail object that both get informed on email delivery" do - ActionMailer::Base.register_observers("BaseTest::MyObserver", MySecondObserver) - mail = BaseMailer.welcome - MyObserver.expects(:delivered_email).with(mail) - MySecondObserver.expects(:delivered_email).with(mail) - mail.deliver + mail_side_effects do + ActionMailer::Base.register_observers("BaseTest::MyObserver", MySecondObserver) + mail = BaseMailer.welcome + MyObserver.expects(:delivered_email).with(mail) + MySecondObserver.expects(:delivered_email).with(mail) + mail.deliver + end end class MyInterceptor - def self.delivering_email(mail) - end + def self.delivering_email(mail); end + def self.previewing_email(mail); end end class MySecondInterceptor - def self.delivering_email(mail) - end + def self.delivering_email(mail); end + def self.previewing_email(mail); end end test "you can register an interceptor to the mail object that gets passed the mail object before delivery" do - ActionMailer::Base.register_interceptor(MyInterceptor) - mail = BaseMailer.welcome - MyInterceptor.expects(:delivering_email).with(mail) - mail.deliver + mail_side_effects do + ActionMailer::Base.register_interceptor(MyInterceptor) + mail = BaseMailer.welcome + MyInterceptor.expects(:delivering_email).with(mail) + mail.deliver + end end test "you can register an interceptor using its stringified name to the mail object that gets passed the mail object before delivery" do - ActionMailer::Base.register_interceptor("BaseTest::MyInterceptor") - mail = BaseMailer.welcome - MyInterceptor.expects(:delivering_email).with(mail) - mail.deliver + mail_side_effects do + ActionMailer::Base.register_interceptor("BaseTest::MyInterceptor") + mail = BaseMailer.welcome + MyInterceptor.expects(:delivering_email).with(mail) + mail.deliver + end + end + + test "you can register an interceptor using its symbolized underscored name to the mail object that gets passed the mail object before delivery" do + mail_side_effects do + ActionMailer::Base.register_interceptor(:"base_test/my_interceptor") + mail = BaseMailer.welcome + MyInterceptor.expects(:delivering_email).with(mail) + mail.deliver + end end test "you can register multiple interceptors to the mail object that both get passed the mail object before delivery" do - ActionMailer::Base.register_interceptors("BaseTest::MyInterceptor", MySecondInterceptor) - mail = BaseMailer.welcome - MyInterceptor.expects(:delivering_email).with(mail) - MySecondInterceptor.expects(:delivering_email).with(mail) - mail.deliver + mail_side_effects do + ActionMailer::Base.register_interceptors("BaseTest::MyInterceptor", MySecondInterceptor) + mail = BaseMailer.welcome + MyInterceptor.expects(:delivering_email).with(mail) + MySecondInterceptor.expects(:delivering_email).with(mail) + mail.deliver + end end test "being able to put proc's into the defaults hash and they get evaluated on mail sending" do @@ -671,6 +707,27 @@ class BaseTest < ActiveSupport::TestCase assert_equal ["robert.pankowecki@gmail.com"], DefaultFromMailer.welcome.from end + test "mail() without arguments serves as getter for the current mail message" do + class MailerWithCallback < ActionMailer::Base + after_action :a_callback + + def welcome + headers('X-Special-Header' => 'special indeed!') + mail subject: "subject", body: "hello world", to: ["joe@example.com"] + end + + def a_callback + mail.to << "jane@example.com" + end + end + + mail = MailerWithCallback.welcome + assert_equal "subject", mail.subject + assert_equal ["joe@example.com", "jane@example.com"], mail.to + assert_equal "hello world", mail.body.encoded.strip + assert_equal "special indeed!", mail["X-Special-Header"].to_s + end + protected # Execute the block setting the given values and restoring old values after @@ -695,4 +752,77 @@ class BaseTest < ActiveSupport::TestCase ensure klass.default_params = old end + + # A simple hack to restore the observers and interceptors for Mail, as it + # does not have an unregister API yet. + def mail_side_effects + old_observers = Mail.class_variable_get(:@@delivery_notification_observers) + old_delivery_interceptors = Mail.class_variable_get(:@@delivery_interceptors) + yield + ensure + Mail.class_variable_set(:@@delivery_notification_observers, old_observers) + Mail.class_variable_set(:@@delivery_interceptors, old_delivery_interceptors) + end + + def with_translation(locale, data) + I18n.backend.store_translations(locale, data) + yield + ensure + I18n.backend.reload! + end +end + +class BasePreviewInterceptorsTest < ActiveSupport::TestCase + teardown do + ActionMailer::Base.preview_interceptors.clear + end + + class BaseMailerPreview < ActionMailer::Preview + def welcome + BaseMailer.welcome + end + end + + class MyInterceptor + def self.delivering_email(mail); end + def self.previewing_email(mail); end + end + + class MySecondInterceptor + def self.delivering_email(mail); end + def self.previewing_email(mail); end + end + + test "you can register a preview interceptor to the mail object that gets passed the mail object before previewing" do + ActionMailer::Base.register_preview_interceptor(MyInterceptor) + mail = BaseMailer.welcome + BaseMailerPreview.any_instance.stubs(:welcome).returns(mail) + MyInterceptor.expects(:previewing_email).with(mail) + BaseMailerPreview.call(:welcome) + end + + test "you can register a preview interceptor using its stringified name to the mail object that gets passed the mail object before previewing" do + ActionMailer::Base.register_preview_interceptor("BasePreviewInterceptorsTest::MyInterceptor") + mail = BaseMailer.welcome + BaseMailerPreview.any_instance.stubs(:welcome).returns(mail) + MyInterceptor.expects(:previewing_email).with(mail) + BaseMailerPreview.call(:welcome) + end + + test "you can register an interceptor using its symbolized underscored name to the mail object that gets passed the mail object before previewing" do + ActionMailer::Base.register_preview_interceptor(:"base_preview_interceptors_test/my_interceptor") + mail = BaseMailer.welcome + BaseMailerPreview.any_instance.stubs(:welcome).returns(mail) + MyInterceptor.expects(:previewing_email).with(mail) + BaseMailerPreview.call(:welcome) + end + + test "you can register multiple preview interceptors to the mail object that both get passed the mail object before previewing" do + ActionMailer::Base.register_preview_interceptors("BasePreviewInterceptorsTest::MyInterceptor", MySecondInterceptor) + mail = BaseMailer.welcome + BaseMailerPreview.any_instance.stubs(:welcome).returns(mail) + MyInterceptor.expects(:previewing_email).with(mail) + MySecondInterceptor.expects(:previewing_email).with(mail) + BaseMailerPreview.call(:welcome) + end end diff --git a/actionmailer/test/delivery_methods_test.rb b/actionmailer/test/delivery_methods_test.rb index 20412c7bb2..a76ac6d295 100644 --- a/actionmailer/test/delivery_methods_test.rb +++ b/actionmailer/test/delivery_methods_test.rb @@ -38,19 +38,21 @@ class DefaultsDeliveryMethodsTest < ActiveSupport::TestCase end test "default sendmail settings" do - settings = {location: '/usr/sbin/sendmail', - arguments: '-i -t'} + settings = { + location: '/usr/sbin/sendmail', + arguments: '-i -t' + } assert_equal settings, ActionMailer::Base.sendmail_settings end end class CustomDeliveryMethodsTest < ActiveSupport::TestCase - def setup + setup do @old_delivery_method = ActionMailer::Base.delivery_method ActionMailer::Base.add_delivery_method :custom, MyCustomDelivery end - def teardown + teardown do ActionMailer::Base.delivery_method = @old_delivery_method new = ActionMailer::Base.delivery_methods.dup new.delete(:custom) @@ -91,23 +93,22 @@ class MailDeliveryTest < ActiveSupport::TestCase end end - def setup - ActionMailer::Base.delivery_method = :smtp + setup do + @old_delivery_method = DeliveryMailer.delivery_method end - def teardown - DeliveryMailer.delivery_method = :smtp - DeliveryMailer.perform_deliveries = true - DeliveryMailer.raise_delivery_errors = true + teardown do + DeliveryMailer.delivery_method = @old_delivery_method + DeliveryMailer.deliveries.clear end test "ActionMailer should be told when Mail gets delivered" do - DeliveryMailer.deliveries.clear DeliveryMailer.expects(:deliver_mail).once DeliveryMailer.welcome.deliver end test "delivery method can be customized per instance" do + Mail::SMTP.any_instance.expects(:deliver!) email = DeliveryMailer.welcome.deliver assert_instance_of Mail::SMTP, email.delivery_method email = DeliveryMailer.welcome(delivery_method: :test).deliver @@ -117,7 +118,6 @@ class MailDeliveryTest < ActiveSupport::TestCase test "delivery method can be customized in subclasses not changing the parent" do DeliveryMailer.delivery_method = :test assert_equal :smtp, ActionMailer::Base.delivery_method - $BREAK = true email = DeliveryMailer.welcome.deliver assert_instance_of Mail::TestMailer, email.delivery_method end @@ -138,13 +138,15 @@ class MailDeliveryTest < ActiveSupport::TestCase end test "default delivery options can be overridden per mail instance" do - settings = { address: "localhost", - port: 25, - domain: 'localhost.localdomain', - user_name: nil, - password: nil, - authentication: nil, - enable_starttls_auto: true } + settings = { + address: "localhost", + port: 25, + domain: 'localhost.localdomain', + user_name: nil, + password: nil, + authentication: nil, + enable_starttls_auto: true + } assert_equal settings, ActionMailer::Base.smtp_settings overridden_options = {user_name: "overridden", password: "somethingobtuse"} mail_instance = DeliveryMailer.welcome(delivery_method_options: overridden_options) @@ -164,23 +166,37 @@ class MailDeliveryTest < ActiveSupport::TestCase end end + test "undefined delivery methods raises errors" do + DeliveryMailer.delivery_method = nil + assert_raise RuntimeError do + DeliveryMailer.welcome.deliver + end + end + test "does not perform deliveries if requested" do - DeliveryMailer.perform_deliveries = false - DeliveryMailer.deliveries.clear - Mail::Message.any_instance.expects(:deliver!).never - DeliveryMailer.welcome.deliver + old_perform_deliveries = DeliveryMailer.perform_deliveries + begin + DeliveryMailer.perform_deliveries = false + Mail::Message.any_instance.expects(:deliver!).never + DeliveryMailer.welcome.deliver + ensure + DeliveryMailer.perform_deliveries = old_perform_deliveries + end end test "does not append the deliveries collection if told not to perform the delivery" do - DeliveryMailer.perform_deliveries = false - DeliveryMailer.deliveries.clear - DeliveryMailer.welcome.deliver - assert_equal(0, DeliveryMailer.deliveries.length) + old_perform_deliveries = DeliveryMailer.perform_deliveries + begin + DeliveryMailer.perform_deliveries = false + DeliveryMailer.welcome.deliver + assert_equal [], DeliveryMailer.deliveries + ensure + DeliveryMailer.perform_deliveries = old_perform_deliveries + end end test "raise errors on bogus deliveries" do DeliveryMailer.delivery_method = BogusDelivery - DeliveryMailer.deliveries.clear assert_raise RuntimeError do DeliveryMailer.welcome.deliver end @@ -188,27 +204,34 @@ class MailDeliveryTest < ActiveSupport::TestCase test "does not increment the deliveries collection on error" do DeliveryMailer.delivery_method = BogusDelivery - DeliveryMailer.deliveries.clear assert_raise RuntimeError do DeliveryMailer.welcome.deliver end - assert_equal(0, DeliveryMailer.deliveries.length) + assert_equal [], DeliveryMailer.deliveries end test "does not raise errors on bogus deliveries if set" do - DeliveryMailer.delivery_method = BogusDelivery - DeliveryMailer.raise_delivery_errors = false - assert_nothing_raised do - DeliveryMailer.welcome.deliver + old_raise_delivery_errors = DeliveryMailer.raise_delivery_errors + begin + DeliveryMailer.delivery_method = BogusDelivery + DeliveryMailer.raise_delivery_errors = false + assert_nothing_raised do + DeliveryMailer.welcome.deliver + end + ensure + DeliveryMailer.raise_delivery_errors = old_raise_delivery_errors end end test "does not increment the deliveries collection on bogus deliveries" do - DeliveryMailer.delivery_method = BogusDelivery - DeliveryMailer.raise_delivery_errors = false - DeliveryMailer.deliveries.clear - DeliveryMailer.welcome.deliver - assert_equal(0, DeliveryMailer.deliveries.length) + old_raise_delivery_errors = DeliveryMailer.raise_delivery_errors + begin + DeliveryMailer.delivery_method = BogusDelivery + DeliveryMailer.raise_delivery_errors = false + DeliveryMailer.welcome.deliver + assert_equal [], DeliveryMailer.deliveries + ensure + DeliveryMailer.raise_delivery_errors = old_raise_delivery_errors + end end - end diff --git a/actionmailer/test/fixtures/test_helper_mailer/welcome b/actionmailer/test/fixtures/test_helper_mailer/welcome new file mode 100644 index 0000000000..61ce70d578 --- /dev/null +++ b/actionmailer/test/fixtures/test_helper_mailer/welcome @@ -0,0 +1 @@ +Welcome!
\ No newline at end of file diff --git a/actionmailer/test/i18n_with_controller_test.rb b/actionmailer/test/i18n_with_controller_test.rb index ab5eaaa9d5..ee36b89dd6 100644 --- a/actionmailer/test/i18n_with_controller_test.rb +++ b/actionmailer/test/i18n_with_controller_test.rb @@ -10,18 +10,15 @@ class I18nTestMailer < ActionMailer::Base def mail_with_i18n_subject(recipient) @recipient = recipient I18n.locale = :de - mail(to: recipient, subject: "#{I18n.t :email_subject} #{recipient}", + mail(to: recipient, subject: I18n.t(:email_subject), from: "system@loudthinking.com", date: Time.local(2004, 12, 12)) end end -# Emulate AV railtie -ActionController::Base.superclass.send(:include, ActionView::Layouts) - class TestController < ActionController::Base def send_mail - I18nTestMailer.mail_with_i18n_subject("test@localhost").deliver - render text: 'Mail sent' + email = I18nTestMailer.mail_with_i18n_subject("test@localhost").deliver + render text: "Mail sent - Subject: #{email.subject}" end end @@ -31,20 +28,43 @@ class ActionMailerI18nWithControllerTest < ActionDispatch::IntegrationTest get ':controller(/:action(/:id))' end - def app - Routes + class RoutedRackApp + attr_reader :routes + + def initialize(routes, &blk) + @routes = routes + @stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes) + end + + def call(env) + @stack.call(env) + end end - def setup - I18n.backend.store_translations('de', email_subject: '[Signed up] Welcome') + APP = RoutedRackApp.new(Routes) + + def app + APP end - def teardown - I18n.locale = :en + teardown do + I18n.locale = I18n.default_locale end def test_send_mail - get '/test/send_mail' - assert_equal "Mail sent", @response.body + Mail::SMTP.any_instance.expects(:deliver!) + with_translation 'de', email_subject: '[Anmeldung] Willkommen' do + get '/test/send_mail' + assert_equal "Mail sent - Subject: [Anmeldung] Willkommen", @response.body + end + end + + protected + + def with_translation(locale, data) + I18n.backend.store_translations(locale, data) + yield + ensure + I18n.backend.reload! end end diff --git a/actionmailer/test/log_subscriber_test.rb b/actionmailer/test/log_subscriber_test.rb index 5f0bee88fd..e7a73d6c8e 100644 --- a/actionmailer/test/log_subscriber_test.rb +++ b/actionmailer/test/log_subscriber_test.rb @@ -1,7 +1,7 @@ -require "abstract_unit" +require 'abstract_unit' require 'mailers/base_mailer' -require "active_support/log_subscriber/test_helper" -require "action_mailer/log_subscriber" +require 'active_support/log_subscriber/test_helper' +require 'action_mailer/log_subscriber' class AMLogSubscriberTest < ActionMailer::TestCase include ActiveSupport::LogSubscriber::TestHelper @@ -31,6 +31,8 @@ class AMLogSubscriberTest < ActionMailer::TestCase assert_equal(2, @logger.logged(:debug).size) assert_match(/BaseMailer#welcome: processed outbound mail in [\d.]+ms/, @logger.logged(:debug).first) assert_match(/Welcome/, @logger.logged(:debug).second) + ensure + BaseMailer.deliveries.clear end def test_receive_is_notified diff --git a/actionmailer/test/mail_layout_test.rb b/actionmailer/test/mail_layout_test.rb index 7f959282cb..166dd096d4 100644 --- a/actionmailer/test/mail_layout_test.rb +++ b/actionmailer/test/mail_layout_test.rb @@ -44,16 +44,6 @@ class ExplicitLayoutMailer < ActionMailer::Base end class LayoutMailerTest < ActiveSupport::TestCase - def setup - set_delivery_method :test - ActionMailer::Base.perform_deliveries = true - ActionMailer::Base.deliveries.clear - end - - def teardown - restore_delivery_method - end - def test_should_pickup_default_layout mail = AutoLayoutMailer.hello assert_equal "Hello from layout Inside", mail.body.to_s.strip diff --git a/actionmailer/test/test_helper_test.rb b/actionmailer/test/test_helper_test.rb index 7c7f0b6fdc..1ff08a3b6e 100644 --- a/actionmailer/test/test_helper_test.rb +++ b/actionmailer/test/test_helper_test.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 require 'abstract_unit' class TestHelperMailer < ActionMailer::Base @@ -36,6 +37,14 @@ class TestHelperMailerTest < ActionMailer::TestCase assert_equal "UTF-8", charset end + def test_encode + assert_equal '=?UTF-8?Q?This_is_=E3=81=82_string?=', encode('This is あ string') + end + + def test_read_fixture + assert_equal ['Welcome!'], read_fixture('welcome') + end + def test_assert_emails assert_nothing_raised do assert_emails 1 do |