如何为功能测试设置locale default_url_options(Rails)

时间:2021-02-20 03:52:53

In my application_controller, I have the following set to include the locale with all paths generated by url_for:

在我的application_controller中,我有以下设置来包含具有url_for生成的所有路径的语言环境:

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

My resource routes then have a :path_prefix = "/:locale"

我的资源路由有一个:path_prefix =“/:locale”

Works fine on the site.

在网站上正常工作。

But when it comes to my functional tests, the :locale is not passed with the generated urls, and therefore they all fail. I can get around it by adding the locale to the url in my tests, like so:

但是当涉及到我的功能测试时,:locale不会与生成的url一起传递,因此它们都会失败。我可以通过在我的测试中将语言环境添加到url来解决它,如下所示:

  get :new, :locale => 'en'

But I don't want to have to manually add the locale to every functional test.

但我不想手动将语言环境添加到每个功能测试中。

I tried adding the default_url_options def above to test_helper, but it seems to have no effect.

我尝试将default_url_options def添加到test_helper上面,但似乎没有效果。

Is there any way I can change the default_url_options to include the locale for all my tests?

有什么办法可以更改default_url_options以包含我所有测试的语言环境?

Thanks.

9 个解决方案

#1


2  

Looking through how the controller test case generates the url there doesn't seem to be a direct way to have it use the defualt_url_options. The main block that actually does the url creationg (in the tests) looks like this (http://github.com/rails/rails/blob/master/actionpack/lib/action_controller/test_case.rb):

通过查看控制器测试用例如何生成URL,似乎没有直接的方法让它使用defualt_url_options。实际执行url creationg的主要块(在测试中)看起来像这样(http://github.com/rails/rails/blob/master/actionpack/lib/action_controller/test_case.rb):

private
  def build_request_uri(action, parameters)
    unless @request.env['REQUEST_URI']
      options = @controller.__send__(:rewrite_options, parameters)
      options.update(:only_path => true, :action => action)

      url = ActionController::UrlRewriter.new(@request, parameters)
      @request.request_uri = url.rewrite(options)
    end
  end

This gets called by the process method which is in turn called by the get, post, head, or put methods. One way to maybe get what you are looking for might be to alias_chain the process method.

这由进程方法调用,而进程方法又由get,post,head或put方法调用。可能获得您正在寻找的内容的一种方法可能是alias_chain过程方法。

class ActionController::TestCase
  def process_with_default_locale(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
    parameters = {:locale=>'en'}.merge(parameters||{})
    process_without_default_locale(action, parameters, session, flash, http_method)
  end
  alias_method_chain :process, :default_locale
end

You'll want to put that into your test helper, outside of the TestCase class I think. Let me know how it works for you, I haven't really tested it out so we'll see.

你想把它放在我认为的TestCase类之外的测试帮助器中。让我知道它是如何为你工作的,我还没有真正测试过,所以我们会看到。

#2


7  

In the Rails 3.1-stable branch, the process method is now within a Behavior module. So here is the code which worked for me (slightly different from John Duff's answer):

在Rails 3.1-stable分支中,流程方法现在位于Behavior模块中。所以这里的代码对我有用(与John Duff的答案略有不同):

class ActionController::TestCase

  module Behavior
    def process_with_default_locale(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
      parameters = { :locale => I18n.default_locale }.merge( parameters || {} )
      process_without_default_locale(action, parameters, session, flash, http_method)
    end 
    alias_method_chain :process, :default_locale
  end 
end

And I made sure this code gets called before running the specs/tests. A good place to put it is in the test_helper class.

我确保在运行specs / tests之前调用此代码。放在test_helper类中的好地方。

#3


4  

For Rails 5, I found this simple solution In test_helper.rb based on action_dispatch/testing/integration.rb

对于Rails 5,我在test_helper.rb中找到了这个简单的解决方案,基于action_dispatch / testing / integration.rb

module ActionDispatch::Integration
  class Session
    def default_url_options
      { locale: I18n.locale }
    end
  end
end

#4


3  

In case anyone is using this with Rails 4.0, the order of arguments in the process method has changed, so you'll need to use this updated patch (based on @martin-carel's answer, just with the http_method argument moved to the second argument):

如果有人在Rails 4.0中使用它,那么process方法中的参数顺序已经改变,所以你需要使用这个更新的补丁(基于@ martin-carel的答案,只需将http_method参数移到第二个参数) ):

class ActionController::TestCase
  module Behavior
    def process_with_default_locale(action, http_method = 'GET', parameters = nil, session = nil, flash = nil)
      parameters = { :locale => I18n.locale }.merge( parameters || {} ) unless I18n.locale.nil?
      process_without_default_locale(action, http_method, parameters, session, flash)
    end
    alias_method_chain :process, :default_locale
  end
end

Hope that helps anyone stuck on this problem.

希望能帮助任何人解决这个问题。

#5


2  

alias_method_chain is deprecated in Rails 5, and it seems the Behavior process method has changed.

在Rails 5中不推荐使用alias_method_chain,似乎行为处理方法已经改变。

Here's my modification of Martin Carel's answer above, adapted to Rails 5.

这是我对Martin Carel上面的答案的修改,适用于Rails 5。

RSpec.configure do |config|
  module ActionController
    class TestCase
      module Behavior
        module LocaleParameter
          def process(action, parameters = {params: {}})
            unless I18n.locale.nil?
              parameters[:params][:locale] = I18n.locale
            end

            super(action, parameters)
          end
        end

        prepend Behavior::LocaleParameter

      end
    end
  end
end

I'm by no means an expert in Rails or Ruby, so if something can be improved in this answer, let me know and I'll change it.

我不是Rails或Ruby的专家,所以如果在这个答案中可以改进一些东西,请告诉我,我会改变它。

#6


1  

I ran into this problem with a failing cucumber test. I use locales as parameters in the url, i.e. http://mysite.com/home?locale=he

我遇到了一个失败的黄瓜测试问题。我在网址中使用locales作为参数,即http://mysite.com/home?locale=he

What I do to cope with this is to drop all locale related stuff from the url during testing by defining default_url_options depending on the environment I use:

我要做的是通过根据我使用的环境定义default_url_options来在测试期间从网址中删除所有与语言环境相关的内容:

  # app/controllers/application_controller.rb
  def default_url_options(options={})
    logger.debug "default_url_options is passed options: #{options.inspect}\n"
    ENV["RAILS_ENV"] != "cucumber" ? { :locale => I18n.locale } : {}
  end

#7


1  

I've come up with a bit less invasive solution to this problem.

我想出了一个针对这个问题的侵入性较小的解决方案。

setup :set_default_locale 

def set_default_locale
  def @request.query_parameters
    {:locale => "en"}.merge(@query_parameters)
  end
end

The advantage of this solution is that it means you can only apply the default locale parameter to certain test cases, so you can test, for example, the redirection strategy itself.

此解决方案的优点是,它意味着您只能将默认语言环境参数应用于某些测试用例,因此您可以测试,例如,重定向策略本身。

#8


1  

Things changed again with Ruby 5.1. Here's what worked for me:

Ruby 5.1再次改变了一切。这对我有用:

class ActionController::TestCase
  module Behavior
    module LocaleParameter
      def process(action, params: {}, **args)
        # Locale parameter must be a string
        params[:locale] = I18n.locale.to_s
        super(action, params: params, **args)
      end
    end
  end
  prepend Behavior::LocaleParameter
end

#9


0  

With integration testing, I found that the above monkey patch needs to be different, this is what worked for me (Rails 2.3.4):

通过集成测试,我发现上面的猴子补丁需要不同,这对我有用(Rails 2.3.4):

class ActionController::Integration::Session
  def url_for_with_default_locale(options)
    options = { :locale => 'en' }.merge(options)
    url_for_without_default_locale(options)
  end
  alias_method_chain :url_for, :default_locale
end

#1


2  

Looking through how the controller test case generates the url there doesn't seem to be a direct way to have it use the defualt_url_options. The main block that actually does the url creationg (in the tests) looks like this (http://github.com/rails/rails/blob/master/actionpack/lib/action_controller/test_case.rb):

通过查看控制器测试用例如何生成URL,似乎没有直接的方法让它使用defualt_url_options。实际执行url creationg的主要块(在测试中)看起来像这样(http://github.com/rails/rails/blob/master/actionpack/lib/action_controller/test_case.rb):

private
  def build_request_uri(action, parameters)
    unless @request.env['REQUEST_URI']
      options = @controller.__send__(:rewrite_options, parameters)
      options.update(:only_path => true, :action => action)

      url = ActionController::UrlRewriter.new(@request, parameters)
      @request.request_uri = url.rewrite(options)
    end
  end

This gets called by the process method which is in turn called by the get, post, head, or put methods. One way to maybe get what you are looking for might be to alias_chain the process method.

这由进程方法调用,而进程方法又由get,post,head或put方法调用。可能获得您正在寻找的内容的一种方法可能是alias_chain过程方法。

class ActionController::TestCase
  def process_with_default_locale(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
    parameters = {:locale=>'en'}.merge(parameters||{})
    process_without_default_locale(action, parameters, session, flash, http_method)
  end
  alias_method_chain :process, :default_locale
end

You'll want to put that into your test helper, outside of the TestCase class I think. Let me know how it works for you, I haven't really tested it out so we'll see.

你想把它放在我认为的TestCase类之外的测试帮助器中。让我知道它是如何为你工作的,我还没有真正测试过,所以我们会看到。

#2


7  

In the Rails 3.1-stable branch, the process method is now within a Behavior module. So here is the code which worked for me (slightly different from John Duff's answer):

在Rails 3.1-stable分支中,流程方法现在位于Behavior模块中。所以这里的代码对我有用(与John Duff的答案略有不同):

class ActionController::TestCase

  module Behavior
    def process_with_default_locale(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
      parameters = { :locale => I18n.default_locale }.merge( parameters || {} )
      process_without_default_locale(action, parameters, session, flash, http_method)
    end 
    alias_method_chain :process, :default_locale
  end 
end

And I made sure this code gets called before running the specs/tests. A good place to put it is in the test_helper class.

我确保在运行specs / tests之前调用此代码。放在test_helper类中的好地方。

#3


4  

For Rails 5, I found this simple solution In test_helper.rb based on action_dispatch/testing/integration.rb

对于Rails 5,我在test_helper.rb中找到了这个简单的解决方案,基于action_dispatch / testing / integration.rb

module ActionDispatch::Integration
  class Session
    def default_url_options
      { locale: I18n.locale }
    end
  end
end

#4


3  

In case anyone is using this with Rails 4.0, the order of arguments in the process method has changed, so you'll need to use this updated patch (based on @martin-carel's answer, just with the http_method argument moved to the second argument):

如果有人在Rails 4.0中使用它,那么process方法中的参数顺序已经改变,所以你需要使用这个更新的补丁(基于@ martin-carel的答案,只需将http_method参数移到第二个参数) ):

class ActionController::TestCase
  module Behavior
    def process_with_default_locale(action, http_method = 'GET', parameters = nil, session = nil, flash = nil)
      parameters = { :locale => I18n.locale }.merge( parameters || {} ) unless I18n.locale.nil?
      process_without_default_locale(action, http_method, parameters, session, flash)
    end
    alias_method_chain :process, :default_locale
  end
end

Hope that helps anyone stuck on this problem.

希望能帮助任何人解决这个问题。

#5


2  

alias_method_chain is deprecated in Rails 5, and it seems the Behavior process method has changed.

在Rails 5中不推荐使用alias_method_chain,似乎行为处理方法已经改变。

Here's my modification of Martin Carel's answer above, adapted to Rails 5.

这是我对Martin Carel上面的答案的修改,适用于Rails 5。

RSpec.configure do |config|
  module ActionController
    class TestCase
      module Behavior
        module LocaleParameter
          def process(action, parameters = {params: {}})
            unless I18n.locale.nil?
              parameters[:params][:locale] = I18n.locale
            end

            super(action, parameters)
          end
        end

        prepend Behavior::LocaleParameter

      end
    end
  end
end

I'm by no means an expert in Rails or Ruby, so if something can be improved in this answer, let me know and I'll change it.

我不是Rails或Ruby的专家,所以如果在这个答案中可以改进一些东西,请告诉我,我会改变它。

#6


1  

I ran into this problem with a failing cucumber test. I use locales as parameters in the url, i.e. http://mysite.com/home?locale=he

我遇到了一个失败的黄瓜测试问题。我在网址中使用locales作为参数,即http://mysite.com/home?locale=he

What I do to cope with this is to drop all locale related stuff from the url during testing by defining default_url_options depending on the environment I use:

我要做的是通过根据我使用的环境定义default_url_options来在测试期间从网址中删除所有与语言环境相关的内容:

  # app/controllers/application_controller.rb
  def default_url_options(options={})
    logger.debug "default_url_options is passed options: #{options.inspect}\n"
    ENV["RAILS_ENV"] != "cucumber" ? { :locale => I18n.locale } : {}
  end

#7


1  

I've come up with a bit less invasive solution to this problem.

我想出了一个针对这个问题的侵入性较小的解决方案。

setup :set_default_locale 

def set_default_locale
  def @request.query_parameters
    {:locale => "en"}.merge(@query_parameters)
  end
end

The advantage of this solution is that it means you can only apply the default locale parameter to certain test cases, so you can test, for example, the redirection strategy itself.

此解决方案的优点是,它意味着您只能将默认语言环境参数应用于某些测试用例,因此您可以测试,例如,重定向策略本身。

#8


1  

Things changed again with Ruby 5.1. Here's what worked for me:

Ruby 5.1再次改变了一切。这对我有用:

class ActionController::TestCase
  module Behavior
    module LocaleParameter
      def process(action, params: {}, **args)
        # Locale parameter must be a string
        params[:locale] = I18n.locale.to_s
        super(action, params: params, **args)
      end
    end
  end
  prepend Behavior::LocaleParameter
end

#9


0  

With integration testing, I found that the above monkey patch needs to be different, this is what worked for me (Rails 2.3.4):

通过集成测试,我发现上面的猴子补丁需要不同,这对我有用(Rails 2.3.4):

class ActionController::Integration::Session
  def url_for_with_default_locale(options)
    options = { :locale => 'en' }.merge(options)
    url_for_without_default_locale(options)
  end
  alias_method_chain :url_for, :default_locale
end