简体   繁体   中英

Rspec for mailers with I18n

I don't understand how to test with rspec and internationalization. For example, in requests tests I do

I18n.available_locales.each do |locale|
  visit users_path(locale: locale)
  #...
end

and it works just fine: every locale tests correct.

But in mailers this trick doesn't work.

user_mailer_spec.rb

require "spec_helper"

describe UserMailer do
  I18n.available_locales.each do |locale|
    let(:user) { FactoryGirl.build(:user, locale: locale.to_s) }
    let(:mail_registration) { UserMailer.registration_confirmation(user) }

    it "should send registration confirmation" do
      puts locale.to_yaml
      mail_registration.body.encoded.should include("test") # it will return error with text which allow me to ensure that for each locale the test call only :en locale email template
    end
  end
end

It runs few times (as many as many locales I have), but every time it generate html for the default locale only.

When I call UserMailer.registration_confirmation(@user).deliver from controller, it works fine.

user_mailer.rb

...
def registration_confirmation(user)
  @user = user
  mail(to: user.email, subject: t('user_mailer.registration_confirmation.subject')) do |format|
      format.html { render :layout => 'mailer'}
      format.text
  end
end
...

views/user_mailer/registration_confirmation.text.erb

<%=t '.thx' %>, <%= @user.name %>.
<%=t '.site_description' %>
<%=t '.credentials' %>:
<%=t '.email' %>: <%= @user.email %>
<%=t '.password' %>: <%= @user.password %>
<%=t '.sign_in_text' %>: <%= signin_url %>
---
<%=t 'unsubscribe' %>

I repeat - it works fine for all locales. I have the question only about rspec tests for it.

I think you may have to wrap your test in a describe/context block to allow the it block to see your let variables:

require "spec_helper"

describe UserMailer do
  I18n.available_locales.each do |locale|
    describe "registration" do
      let(:user) { FactoryGirl.build(:user, locale: locale.to_s) }
      let(:mail_registration) { UserMailer.registration_confirmation(user) }

      it "should send registration confirmation" do
        puts locale.to_yaml
        mail_registration.body.encoded.should include("test")
      end
    end
    # ...
  end
  # ...
end

As for why, perhaps this StackOverflow answer on let variable scoping may help.

Edit

Is the issue that you've assigned a locale to your user, but you don't pass it into the mail method anywhere? Perhaps this StackOverflow answer would be of reference. Hopefully one of the two answers there would be relevant in your situation. Here's my simple attempt at adapting the first answer there to your situation (untested obviously):

user_mailer.rb

...
def registration_confirmation(user)
  @user = user
  I18n.with_locale(user.locale) do
    mail(to: user.email, 
             subject: t('user_mailer.registration_confirmation.subject')) do |format|
      format.html { render :layout => 'mailer' }
      format.text
    end
  end
end
... 

You probably need to specify the locale, as in:

mail_subscribe.body.encoded.should include(t('user_mailer.subscribe_confirmation.stay', locale: locale))

You can also try adding I18n.locale = user.locale right before the mail call in the registration_confirmation method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM