【问题标题】:Rspec view test with optional locale path带有可选语言环境路径的 Rspec 视图测试
【发布时间】:2021-04-27 14:20:00
【问题描述】:

我的路由中有一个可选的语言环境参数。

# config/routes.rb
  scope '(:locale)' do
    resources :orders
    resources :line_items
    resources :carts
    root 'store#index', as: 'store_index', via: :all
  end
# config/initializers/i18n.rb
#encoding: utf-8
I18n.default_locale = :en

LANGUAGES = [
  ['English',                  'en'],
  ["Español".html_safe, 'es']
]

如果我想这样测试我的观点,

# /spec/views/carts/edit.html.erb_spec.rb
require 'rails_helper'

RSpec.describe "carts/edit", type: :view do
  let(:cart) { create(:cart) }

  before(:each) do
    assign(:cart, cart)
  end

  it "renders the edit cart form" do
    render

    assert_select "form[action=?][method=?]", cart_path(cart), "post" do
    end
  end
end

我收到一个错误

/Users/burak/.rvm/rubies/ruby-2.7.3/bin/ruby -I/Users/burak/.rvm/gems/ruby-2.7.3/gems/rspec-core-3.10.1/lib:/Users/burak/.rvm/gems/ruby-2.7.3/gems/rspec-support-3.10.2/lib /Users/burak/.rvm/gems/ruby-2.7.3/gems/rspec-core-3.10.1/exe/rspec spec/views/carts/edit.html.erb_spec.rb
F

Failures:

  1) carts/edit renders the edit cart form
     Failure/Error: <%= form_with(model: cart) do |form| %>

     ActionView::Template::Error:
       No route matches {:action=>"show", :controller=>"carts", :format=>nil, :locale=>#<Cart id: 1252, created_at: "2021-04-27 13:45:09.842106000 +0000", updated_at: "2021-04-27 13:45:09.842106000 +0000">}, missing required keys: [:id]
       Did you mean?  cart_url
                      carts_url
                      carts_path
                      new_cart_url
     # ./app/views/carts/_form.html.erb:1:in `_app_views_carts__form_html_erb__2203507052991398875_16560'
     # ./app/views/carts/edit.html.erb:3:in `_app_views_carts_edit_html_erb___4312857554407673387_16540'
     # ./spec/views/carts/edit.html.erb_spec.rb:11:in `block (2 levels) in <top (required)>'
     # ------------------
     # --- Caused by: ---
     # ActionController::UrlGenerationError:
     #   No route matches {:action=>"show", :controller=>"carts", :format=>nil, :locale=>#<Cart id: 1252, created_at: "2021-04-27 13:45:09.842106000 +0000", updated_at: "2021-04-27 13:45:09.842106000 +0000">}, missing required keys: [:id]
     #   Did you mean?  cart_url
     #                  carts_url
     #                  carts_path
     #                  new_cart_url
     #   ./app/views/carts/_form.html.erb:1:in `_app_views_carts__form_html_erb__2203507052991398875_16560'

Finished in 0.02277 seconds (files took 0.60597 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/views/carts/edit.html.erb_spec.rb:10 # carts/edit renders the edit cart form

据我了解,那是因为我的购物车对象正在通过 :locale 关键字传递到某个地方。如果我在我的_form 部分中明确地将 URL 传递给form_with,那么错误就会消失,但这会破坏其他一些测试。我该如何解决这个问题?

这里是必要的部分和视图。

# app/views/carts/edit.html.erb
<h1>Editing Cart</h1>

<%= render 'form', cart: @cart %>

<%= link_to 'Show', @cart %> |
<%= link_to 'Back', carts_path %>
# app/views/carts/_form.html.erb
<%= form_with(model: cart) do |form| %>
  <% if cart.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(cart.errors.count, "error") %> prohibited this cart from being saved:</h2>

      <ul>
        <% cart.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

【问题讨论】:

    标签: ruby-on-rails rspec ruby-on-rails-6


    【解决方案1】:

    因此,您的表单要指向的 URL 的路由是(采用您将在 rails routes 中看到的格式):

    (/:locale)/carts/:id(.:format)
    

    看起来正在发生的事情是,当您的视图规范呈现时,它会调用cart_path(cart) 来构建表单的action 属性。正在发生的事情是辅助方法cart_path 尝试从左到右填充路径的参数化部分,它使用cart 尝试填充:locale 段而不是:id 段。

    您不会在rails server 中的控制器操作呈现的上下文中看到这种情况,因为控制器具有locale 具有默认值的概念,因此它理解cart 代表第二个,:id 路径的一部分。

    如果你想确保你的视图在单独测试时表现相似,那么你可以在你的路由文件中添加一个默认值:

    scope '(:locale)', defaults: { locale: 'en' } do
      ...
    

    在您的config/environments/test.rb 中,添加一个进一步的默认值:

    Rails.application.configure do
     # ...
     routes.default_url_options[:locale] = 'en'
    end
    

    routes.rb 中设置默认值将允许您的视图文件正确生成有效路径;添加default_url_options 意味着您可以在视图规范中编写cart_path(cart),并且默认情况下它会知道使用“en”作为语言环境。没有它,您必须断言操作路径是cart_path(cart, locale: 'en')

    【讨论】:

    • 太棒了!最后一个问题。 :) 我已经尝试将Rails.application.routes.default_url_options[:locale]= I18n.default_locale 添加到我的config/environments/test.rb 中,但它没有起作用,因为我的routes.rb 中没有defaults: { locale: 'en' }。为什么不在路由中添加默认值就不能工作?
    • 据我了解(我没有深入研究代码),ActionController(和所有控制器子类)根据您在环境中的设置管理默认语言环境 - 两者config/appplication.rb 和您的 config/environments/* 文件。因此,您在路由中没有可选区域设置的默认值并不重要,因为控制器为您管理了默认值。但是当你在视图规范中加载视图时,没有控制器,所以路由能够提供它更重要。
    • 现在完全清楚了,非常感谢! :)
    • 我只是想这会为我的路由文件中的任何路径添加语言环境以进行测试,即使我不需要任何语言环境,所以我的一些测试失败了。如何仅为我在语言环境范围内的路径指定默认语言环境?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    相关资源
    最近更新 更多