Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to test which layout an Action Mailer email is rendered with?

I have some Action Mailer email messages and I would like to test which layout will be used to render the email. I found this example on the web, but it's from 2008 and doesn't work with Rails 3.2 and presumably later versions.

My motivation for this is that I'd like to write a unit test that asserts that the mailer was rendered with a particular layout so if that is changed, the test will break.

like image 445
Luke Francl Avatar asked Apr 25 '15 00:04

Luke Francl


2 Answers

ActionController::TestCase has a method assert_template, so something like this should work:

class MailerTest < ActionController::TestCase
    ...
    def test_layout
      assert_template layout: "layout/something"
    end
    ...
 end
like image 167
Fred Willmore Avatar answered Oct 20 '22 08:10

Fred Willmore


Testing the layout rendered while sending emails can be done as part of the controller tests using assert_template.

Given the following mailer class and method,

class Notifier < ActionMailer::Base
  def password_reset_instructions(user)
    @user = user
    @reset_password_link = ...

    mail(to: ..., from: ...., subject: "Password Reset Instructions") do |format|
      format.html {render layout: 'my_layout'}
      format.text
    end
  end
end

the password reset email will be rendered using my_layout.html.erb layout.

This mailer method is likely to be invoked in a UsersController method, e.g.:

class UsersController < ApplicationController


  def forgot_password
     user = ...
     Notifier.password_reset_instructions(user).deliver_now
  end

end

The assert_template layout: "my_layout" statement in the following controller test for users_controller#forgot_password would verify the layout used:

class UsersControllerTest < ActionController::TestCase
  test "forgot password" do
    assert_difference 'ActionMailer::Base.deliveries.size', +1 do
      post :forgot_password, email: @user.email
    end 

    assert_response :redirect
    assert_template layout: "my_layout"
    assert_template "password_reset_instructions"

    password_reset_email = ActionMailer::Base.deliveries.last
    assert_equal "Password Reset Instructions", password_reset_email.subject
  end
end

The relevant parts from the log:

Started POST "/users/forgot_password"
Processing by UsersController#forgot_password as HTML
...
  Rendered notifier/password_reset_instructions.html.erb within layouts/my_layout (1.1ms)

References:

  1. Action Mailer Basics
  2. Testing Your Mailers - Functional Testing
  3. assert_template method
like image 26
Prakash Murthy Avatar answered Oct 20 '22 10:10

Prakash Murthy