Allow testing multipart emails in Action Mailbox

Allow passing a block to the create_inbound_email_from_mail and
receive_inbound_email_from_mail test helper methods.

When you wanted to test a multipart email -- for example, an email that
has both a plaintext part and an HTML part -- there wasn't a way to
easily build one without a pre-made fixture. By allowing you to pass a
block to these methods, we unlock the power of Mail.new to easily
create a variety of emails, from multi-part emails, to emails with
attachments, and beyond.
This commit is contained in:
Michael Herold 2019-08-07 09:12:13 -05:00 committed by George Claghorn
parent 6bc88355ea
commit ab34ed8acc
3 changed files with 99 additions and 7 deletions

View File

@ -1,3 +1,7 @@
* Allow easier creation of multi-part emails from the `create_inbound_email_from_mail` and `receive_inbound_email_from_mail` test helpers.
*Michael Herold*
* Fix Bcc header not being included with emails from `create_inbound_email_from` test helpers.
*jduff*

View File

@ -10,11 +10,58 @@ module ActionMailbox
create_inbound_email_from_source file_fixture(fixture_name).read, status: status
end
# Create an +InboundEmail+ by specifying it using +Mail.new+ options. Example:
# Creates an +InboundEmail+ by specifying through options or a block.
#
# ==== Options
#
# * <tt>:status</tt> - The +status+ to set for the created +InboundEmail+.
# For possible statuses, see {its documentation}[rdoc-ref:ActionMailbox::InboundEmail].
#
# ==== Creating a simple email
#
# When you only need to set basic fields like +from+, +to+, +subject+, and
# +body+, you can pass them directly as options.
#
# create_inbound_email_from_mail(from: "david@loudthinking.com", subject: "Hello!")
def create_inbound_email_from_mail(status: :processing, **mail_options)
mail = Mail.new(mail_options)
#
# ==== Creating a multi-part email
#
# When you need to create a more intricate email, like a multi-part email
# that contains both a plaintext version and an HTML version, you can pass a
# block.
#
# create_inbound_email_from_mail do
# to "David Heinemeier Hansson <david@loudthinking.com>"
# from "Bilbo Baggins <bilbo@bagend.com>"
# subject "Come down to the Shire!"
#
# text_part do
# body "Please join us for a party at Bag End"
# end
#
# html_part do
# body "<h1>Please join us for a party at Bag End</h1>"
# end
# end
#
# As with +Mail.new+, you can also use a block parameter to define the parts
# of the message:
#
# create_inbound_email_from_mail do |mail|
# mail.to "David Heinemeier Hansson <david@loudthinking.com>"
# mail.from "Bilbo Baggins <bilbo@bagend.com>"
# mail.subject "Come down to the Shire!"
#
# mail.text_part do |part|
# part.body "Please join us for a party at Bag End"
# end
#
# mail.html_part do |part|
# part.body "<h1>Please join us for a party at Bag End</h1>"
# end
# end
def create_inbound_email_from_mail(status: :processing, **mail_options, &block)
mail = Mail.new(mail_options, &block)
# Bcc header is not encoded by default
mail[:bcc].include_in_headers = true if mail[:bcc]
@ -33,10 +80,11 @@ module ActionMailbox
create_inbound_email_from_fixture(*args).tap(&:route)
end
# Create an +InboundEmail+ using the same arguments as +create_inbound_email_from_mail+ and immediately route it to
# processing.
def receive_inbound_email_from_mail(**kwargs)
create_inbound_email_from_mail(**kwargs).tap(&:route)
# Create an +InboundEmail+ using the same options or block as
# {create_inbound_email_from_mail}[rdoc-ref:#create_inbound_email_from_mail],
# then immediately route it for processing.
def receive_inbound_email_from_mail(**kwargs, &block)
create_inbound_email_from_mail(**kwargs, &block).tap(&:route)
end
# Create an +InboundEmail+ using the same arguments as +create_inbound_email_from_source+ and immediately route it

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
require_relative "../test_helper"
module ActionMailbox
class TestHelperTest < ActiveSupport::TestCase
test "multi-part mail can be built in tests using a block" do
inbound_email = create_inbound_email_from_mail do
to "test@example.com"
from "hello@example.com"
text_part do
body "Hello, world"
end
html_part do
body "<h1>Hello, world</h1>"
end
end
mail = inbound_email.mail
assert_equal mail.parts.length, 2
assert_equal mail.text_part.to_s, <<~TEXT.chomp
Content-Type: text/plain;\r
charset=UTF-8\r
Content-Transfer-Encoding: 7bit\r
\r
Hello, world
TEXT
assert_equal mail.html_part.to_s, <<~HTML.chomp
Content-Type: text/html;\r
charset=UTF-8\r
Content-Transfer-Encoding: 7bit\r
\r
<h1>Hello, world</h1>
HTML
end
end
end