Спецификации представления Rspec нарушены default_locale

Я недавно локализовал свое приложение Rails и добавил локаль по умолчанию 'en' (я следовал инструкциям здесь, чтобы добавить локали в мои URL). Это сломало большинство моих спецификаций; Мне удалось найти решения / обходные пути для всех из них, кроме моих спецификаций View.

Вот пример спецификации базового представления, которая нарушена, моя спецификация представления статьи:

RSpec.describe 'articles/index', type: :view do
  before(:each) do
    assign(:articles, [
      FactoryGirl.create(:article, number: '11.22.33'),
      FactoryGirl.create(:article, number: '22.33.44')
    ])
  end

  it 'renders a list of articles' do
    render
  end
end

Эта спецификация приводит к следующей ошибке:

 1) articles/index renders a list of articles
     Failure/Error: render
     ActionView::Template::Error:
       No route matches {:action=>"show", :controller=>"articles", :id=>nil, :locale=>#<Article id: 2, number: "11.22.33", criminal_code_id: 3, description: nil, created_at: "2015-05-25 08:58:56", updated_at: "2015-05-25 08:58:56">} missing required keys: [:id, :locale]

Похоже, есть три проблемы:

  1. Rspec должен использовать действие "index" вместо "show"
  2. Не должно быть обязательного: ключ идентификатора для действия "index"
  3. Локаль должна быть "en" вместо одной из статей, которые я создал.

Вот мои соответствующие маршруты:

Rails.application.routes.draw do
  scope ':locale', locale: /#{I18n.available_locales.join("|")}/ do
    resources :articles do
      collection do
        get 'custom_json', constraints: { format: :json }, defaults: { format: :json }
      end
    end

    get "*path", to: redirect("/#{I18n.default_locale}") # handles /en/fake/path/whatever
  end

  get '', to: redirect("/#{I18n.default_locale}") # handles /
  get '*path', to: redirect("/#{I18n.default_locale}/%{path}") # handles /not-a-locale/anything
end

Вот соответствующая часть моего контроллера приложений:

before_action :set_locale

def set_locale
  I18n.locale = params[:locale] || I18n.default_locale
end

def default_url_options(options = {})
  { locale: I18n.locale }.merge options
end

И мой вид статьи находится в app/views/article /index.html.erb (в этом нет ничего необычного).

У кого-нибудь есть идеи о том, как получить спецификации View, чтобы они хорошо играли с локалями?

2 ответа

Следующее может помочь вам:

# Set locale for view specs, see https://github.com/rspec/rspec-rails/issues/255#issuecomment-2865917
class ActionView::TestCase::TestController
  def default_url_options(options = {})
    {locale: I18n.default_locale}
  end
end

# Set locale for feature specs, see https://github.com/rspec/rspec-rails/issues/255#issuecomment-24698753
RSpec.configure do |config|
  config.before(:each, type: :feature) do
    default_url_options[:locale] = I18n.default_locale
  end
end

Это помогло в моем случае. Тем не менее, я нахожу довольно неловким, что после стольких лет Rails I18n все еще приходится заботиться о таких вещах самостоятельно.

Вот потенциальный обходной путь, пока вы ждете, чтобы кто-то опубликовал лучший ответ:

Похоже, вы делаете link_to на своей странице индекса для каждой из ваших статей. Вызов помощника url в link_to, например article_path, где ваша спецификация может нарушаться. У меня была похожая проблема, и я не мог ее решить. Методы url_helper не работали для меня в тестовой среде так же, как в dev или prod env. В частности, в тестовой среде они не работали, если я не объявил локаль в вызове url_helper явно, используя локаль: 'en'.

Я долго оглядывался и не мог понять почему.

Поэтому я решил просто заглушить вызовы url_helpers в моей спецификации вида, как это

allow(view).to receive(:conversation_transmission_path).and_return("/")
allow(view).to receive(:edit_conversation_transmission_path).and_return("/")

это синтаксис rspec 3.2

Другие вопросы по тегам