Тестирование многострочных писем ActionMailer с помощью RSpec

в настоящее время я тестирую свои почтовые программы с помощью RSpec, но я начал настраивать составные электронные письма, как описано в руководствах Rails здесь: http://guides.rubyonrails.org/action_mailer_basics.html#sending-multipart-emails

У меня есть шаблоны почтовых отправителей в текстовом и html-форматах, но похоже, что мои тесты проверяют только часть HTML. Есть ли способ проверить текстовый шаблон отдельно?

Это только проверка представления HTML, потому что это первый в порядке по умолчанию?

4 ответов


чтобы дополнить отличный ответ nilmethod, вы можете очистить свои спецификации, Протестировав как текстовые, так и html-версии, используя общую группу примеров:

spec_helper.rb

def get_message_part (mail, content_type)
  mail.body.parts.find { |p| p.content_type.match content_type }.body.raw_source
end

shared_examples_for "multipart email" do
  it "generates a multipart message (plain text and html)" do
    mail.body.parts.length.should eq(2)
    mail.body.parts.collect(&:content_type).should == ["text/plain; charset=UTF-8", "text/html; charset=UTF-8"]
  end
end

your_email_spec.rb

let(:mail) { YourMailer.action }

shared_examples_for "your email content" do
  it "has some content" do
    part.should include("the content")
  end
end

it_behaves_like "multipart email"

describe "text version" do
  it_behaves_like "your email content" do
    let(:part) { get_message_part(mail, /plain/) }
  end
end

describe "html version" do
  it_behaves_like "your email content" do
    let(:part) { get_message_part(mail, /html/) }
  end
end

Это можно проверить с помощью регулярных выражений.

поиск вещей в HTML-части (используйте #после этого, чтобы соответствовать):

mail.body.parts.find {|p| p.content_type.match /html/}.body.raw_source

поиск вещей в текстовой части (используйте #после этого, чтобы соответствовать):

mail.body.parts.find {|p| p.content_type.match /plain/}.body.raw_source

проверка того, что он действительно генерирует составное сообщение:

it "generates a multipart message (plain text and html)" do
  mail.body.parts.length.should == 2
  mail.body.parts.collect(&:content_type).should == ["text/html; charset=UTF-8", "text/plain; charset=UTF-8"]
end 

чтобы сделать вещи еще проще, вы можете использовать

message.text_part    and
message.html_part

, чтобы найти соответствующие части. Это работает даже для структурированных составных / альтернативных сообщений с вложениями. (Протестировано на Ruby 1.9.3 с Rails 3.0.14.)

эти методы используют некоторую эвристику, чтобы найти соответствующие части сообщения, поэтому, если ваше сообщение имеет несколько текстовых частей (например, как Apple Mail создает их), это может не сделать "правильную вещь".

это изменило бы вышеуказанный метод к

def body_should_match_regex(mail, regex)
 if mail.multipart?
  ["text", "html"].each do |part|
   mail.send("#{part}_part").body.raw_source.should match(regex)
  end
 else
  mail.body.raw_source.should match(regex)
 end
end

который работает как для текстовых (не-составных) сообщений, так и для составных сообщений и проверяет все тела сообщений на определенное регулярное выражение.

Теперь, есть добровольцы, чтобы сделать "настоящий" RSpec matcher из этого? :) Что-то вроде

@mail.bodies_should_match /foobar/

было бы намного лучше ...


если ваша электронная почта имеет вложения, текст и html-части будут помещены в multipart/alternative часть. Это отмечается в разделе отправка писем с вложениями в руководство Rails 3.

чтобы справиться с этим, я сначала упростил get_message_part способ выше:

def get_message_part(mail, content_type)
  mail.body.parts.find { |p| p.content_type.match content_type }
end

тогда в моем тесте:

multipart = get_message_part(email, /multipart/)

html = get_message_part(multipart, /html/)
html_body = html.body.raw_source

assert_match 'some string', html_body