Подтвердить что ты не робот

Тестирование многопользовательских писем ActionMailer с RSpec

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

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

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

4b9b3361

Ответ 1

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

Поиск вещей в части 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 

Ответ 2

В дополнение к отличному ответу 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

Ответ 3

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

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

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

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

@mail.bodies_should_match /foobar/

было бы намного приятнее...

Ответ 4

Если в вашем письме есть вложения, текст и детали 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