使用 RSpec 测试 ActionMailer 多部分电子邮件(文本和 html 版本)

发布于 2024-11-17 04:24:44 字数 354 浏览 3 评论 0原文

我目前正在使用 RSpec 测试我的邮件程序,但我已经开始设置多部分电子邮件,如 Rails 指南中所述:http://guides.rubyonrails.org/action_mailer_basics.html#sending-multipart-emails

我有两个邮件模板文本和 html 格式,但看起来我的测试只检查 HTML 部分。有没有办法单独检查文本模板?

它是否只检查 HTML 视图,因为它是默认顺序中的第一个?

I'm currently testing my mailers with RSpec, but I've started setting up multipart emails as described in the Rails Guides here: http://guides.rubyonrails.org/action_mailer_basics.html#sending-multipart-emails

I have both mailer templates in text and html formats, but it looks like my tests are only checking the HTML portion. Is there a way to check the text template separately?

Is it only checking the HTML view because it's first in the default order?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

夜血缘 2024-11-24 04:24:44

为了补充 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

To supplement, nilmethod's excellent answer, you can clean up your specs by testing both text and html versions using a shared example group:

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
各自安好 2024-11-24 04:24:44

这可以使用正则表达式进行测试。

在 HTML 部分中查找内容(在此之后使用 #should 进行匹配):

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

在纯文本部分中查找内容(在此之后使用 #should 进行匹配):

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 

This can be tested with regular expressions.

Finding things in the HTML portion (use #should after this to match):

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

Finding things in the plain text portion (use #should after this to match):

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

Checking that it is, indeed, generating a multipart message:

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 
热血少△年 2024-11-24 04:24:44

为了让事情变得更简单,您可以使用

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 匹配器吗? :)类似的东西

@mail.bodies_should_match /foobar/

会好很多......

To make things even simpler, you can use

message.text_part    and
message.html_part

to find the respective parts. This works even for structured multipart/alternative messages with attachments. (Tested on Ruby 1.9.3 with Rails 3.0.14.)

These methods employ some kind of heuristic to find the respective message parts, so if your message has multiple text parts (e.g. as Apple Mail creates them) it might fail to do the "right thing".

This would change the above method to

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

which works for both plaintext (non-multipart) messages and multipart messages and tests all message bodies against a specific regular expression.

Now, any volunteers to make a "real" RSpec matcher out of this? :) Something like

@mail.bodies_should_match /foobar/

would be a lot nicer ...

三生殊途 2024-11-24 04:24:44

如果您的电子邮件有附件,则文本和 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

If your email has attachments the text and html parts will end be placed in a multipart/alternative part. This is noted on under Sending Emails with Attachments in the Rails 3 Guide.

To handle this, I first simplified the get_message_part method above to:

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

Then in my test:

multipart = get_message_part(email, /multipart/)

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

assert_match 'some string', html_body
季末如歌 2024-11-24 04:24:44

我已经这样做了,我发现它更简单,因为除了样式和标记之外,两封电子邮件的内容都是相似的。

context 'When there are no devices' do
  it 'makes sure both HTML and text version emails are sent' do
    expect(mail.body.parts.count).to eq(2)
    # You can even make sure the types of the part are `html` and `text`
  end

  it 'does not list any lockboxes to be removed in both types emails' do
    mail.body.parts.each do |part|
      expect(part.body).to include('No devices to remove')
    end
  end
end

I have done this way, I found it simpler since the content of both emails is gonna be similar except styles and markup.

context 'When there are no devices' do
  it 'makes sure both HTML and text version emails are sent' do
    expect(mail.body.parts.count).to eq(2)
    # You can even make sure the types of the part are `html` and `text`
  end

  it 'does not list any lockboxes to be removed in both types emails' do
    mail.body.parts.each do |part|
      expect(part.body).to include('No devices to remove')
    end
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文