如何对Rails邮件程序生成的html内容进行单元测试?

如何对Rails邮件程序生成的html内容进行单元测试?,html,ruby-on-rails,unit-testing,capybara,actionmailer,Html,Ruby On Rails,Unit Testing,Capybara,Actionmailer,我曾经遇到过一些工具,它们使测试Rails应用程序中生成的电子邮件变得更容易,但它们是为集成测试而设计的(例如)。然而,我正在编写一个单元测试,它直接与mailer一起工作 我目前有一个邮件测试,看起来像这样: RSpec.describe DigestMailer do describe "#daily_digest" do let(:mail) { DigestMailer.daily_digest(user.id) } let(:user) { create(:user

我曾经遇到过一些工具,它们使测试Rails应用程序中生成的电子邮件变得更容易,但它们是为集成测试而设计的(例如)。然而,我正在编写一个单元测试,它直接与mailer一起工作

我目前有一个邮件测试,看起来像这样:

RSpec.describe DigestMailer do
  describe "#daily_digest" do
    let(:mail) { DigestMailer.daily_digest(user.id) }
    let(:user) { create(:user) }

    it "sends from the correct email" do
      expect(mail.from).to eql ["support@example.com"]
    end

    it "renders the subject" do
      expect(mail.subject).to eql "Your Daily Digest"
    end

    it "renders the receiver email" do
      expect(mail.to).to eql [user.email]
    end

    it "renders the number of new posts" do
      expect(mail.body.raw_source).to match "5 New Posts"
    end
  end
end
within ".posts-section" do
  expect(html_body).to have_content "5 New Posts"
  expect(html_body).to have_link "View More"
  expect(find_link("View More").to link_to posts_url
end
但是,我希望能够比简单地使用正则表达式更容易地测试html内容

我真正希望能够做到的是:

RSpec.describe DigestMailer do
  describe "#daily_digest" do
    let(:mail) { DigestMailer.daily_digest(user.id) }
    let(:user) { create(:user) }

    it "sends from the correct email" do
      expect(mail.from).to eql ["support@example.com"]
    end

    it "renders the subject" do
      expect(mail.subject).to eql "Your Daily Digest"
    end

    it "renders the receiver email" do
      expect(mail.to).to eql [user.email]
    end

    it "renders the number of new posts" do
      expect(mail.body.raw_source).to match "5 New Posts"
    end
  end
end
within ".posts-section" do
  expect(html_body).to have_content "5 New Posts"
  expect(html_body).to have_link "View More"
  expect(find_link("View More").to link_to posts_url
end

我不知道是否有一种方法可以直接使用水豚来达到这样的效果。也许有一些替代方案可以提供类似的功能?

未经测试,但您应该能够通过添加

RSpec.configure do |config|
  config.include Capybara::RSpecMatchers, :type => :mailer
end
然后在你的测试中

expect(mail.html_part.body.to_s).to have_content('blah blah')
expect(mail.html_part.body.to_s).to have_link('View More', href: posts_url)
注意-这会添加匹配器,而不是查找器,因此您可以使用选项来创建链接,而不是使用查找链接。根据,您可以将字符串转换为
Capybara::Node::Simple
实例。这允许您使用水豚匹配器对其进行匹配

我创建了一个助手方法,该方法使用以下内容:

def email_html
  Capybara.string(mail.html_part.body.to_s)
end
然后我可以按如下方式使用:

expect(email_html).to have_content "5 New Posts"

嗯……不幸的是,这不起作用,因为
mail.html\u部分
不响应
has\u内容?
ummm--它不应该调用has\u内容?在它上面,除非html_部分不返回字符串——我必须检查——更新以访问作为html_部分主体的字符串