Testowanie wieloczęściowych wiadomości e-mail ActionMailer za pomocą RSpec

Obecnie testuję moje mailery z RSpec, ale zacząłem konfigurować wieloczęściowe e-maile, jak opisano w przewodnikach Rails tutaj: http://guides.rubyonrails.org/action_mailer_basics.html#sending-multipart-emails

Mam zarówno szablony Mailera w formacie tekstowym, jak i html, ale wygląda na to, że moje testy sprawdzają tylko część HTML. Czy istnieje sposób na osobne sprawdzenie szablonu tekstowego?

Czy to tylko sprawdzanie widoku HTML bo jest pierwszy w domyślnym zamówienie?

Author: cmhobbs, 2011-06-27

4 answers

Aby uzupełnić doskonałą odpowiedź nilmethod, możesz wyczyścić swoje specyfikacje, testując zarówno wersje tekstowe, jak i html za pomocą udostępnionej grupy przykładowej:

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
 32
Author: Lachlan Cotter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-03 22:48:00

Można to przetestować za pomocą wyrażeń regularnych.

Znajdowanie rzeczy w części HTML (użyj #should po tym, aby dopasować):

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

Znajdowanie rzeczy w części zwykłego tekstu (użyj #should po tym, aby dopasować):

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

Sprawdzanie, czy rzeczywiście generuje wieloczęściową wiadomość:

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 
 26
Author: cmhobbs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-05 20:43:41

Aby wszystko było jeszcze prostsze, możesz użyć

message.text_part    and
message.html_part

Aby znaleźć odpowiednie części. Działa to nawet w przypadku zorganizowanych wiadomości wieloczęściowych/alternatywnych z załącznikami. (Testowane na Ruby 1.9.3 z Rails 3.0.14.)

Te metody wykorzystują pewien rodzaj heurystyki, aby znaleźć odpowiednie części wiadomości, więc jeśli wiadomość ma wiele części tekstu (np. gdy tworzy je Apple Mail), może to nie zrobić "właściwej rzeczy".

To zmieni powyższą metodę na

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

Który działa zarówno dla wiadomości tekstowych (nie-wieloczęściowych), jak i wieloczęściowych i testuje wszystkie ciała wiadomości pod kątem określonego wyrażenia regularnego.

Jacyś ochotnicy do zrobienia z tego" prawdziwego " matchera RSpec? :) Coś jak
@mail.bodies_should_match /foobar/
Byłoby o wiele milej ...
 23
Author: Jens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-28 11:23:26

Jeśli twój e-mail zawiera załączniki, części tekstowe i html zostaną umieszczone w części multipart/alternative. Jest to odnotowane w sekcji wysyłanie wiadomości e-mail z załącznikami w Przewodniku Rails 3 .

Aby sobie z tym poradzić, najpierw uprościłem metodę get_message_part powyżej do:

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

Potem w moim teście:

multipart = get_message_part(email, /multipart/)

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

assert_match 'some string', html_body
 1
Author: mikeycgto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-27 16:38:21