简体   繁体   English

如何为功能测试(Rails)设置语言环境 default_url_options

[英]How to set locale default_url_options for functional tests (Rails)

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.但是当涉及到我的功能测试时, :locale 没有与生成的 url 一起传递,因此它们都失败了。 I can get around it by adding the locale to the url in my tests, like so:我可以通过在我的测试中将语言环境添加到 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.谢谢。

For Rails 5, I found this simple solution In test_helper.rb based on action_dispatch/testing/integration.rb对于 Rails 5,我在基于action_dispatch/testing/integration.rb 的test_helper.rb找到了这个简单的解决方案

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

In the Rails 3.1-stable branch, the process method is now within a Behavior module.在 Rails 3.1-stable 分支中, process 方法现在位于Behavior模块中。 So here is the code which worked for me (slightly different from John Duff's answer):所以这是对我有用的代码(与约翰达夫的回答略有不同):

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.放置它的好地方是 test_helper 类。

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.希望能帮助任何陷入这个问题的人。

I tried a lot of examples, but only this one helped me.我尝试了很多例子,但只有这个对我有帮助。 It is concise and simple.它简洁明了。 Add this code snippet to the test.rb:将此代码片段添加到 test.rb:

Rails.application.configure do
  # ... other config ...

  routes.default_url_options[:locale] = :en
end

Works on Rails 5.1.4适用于 Rails 5.1.4

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.查看控制器测试用例如何生成 url 似乎没有直接的方法让它使用 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 创建的主要块(在测试中)如下所示( 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.这由 process 方法调用,而 process 方法又由 get、post、head 或 put 方法调用。 One way to maybe get what you are looking for might be to alias_chain the process method.一种可能获得您正在寻找的内容的方法可能是 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.你会想把它放在你的测试助手中,在我认为的 TestCase 类之外。 Let me know how it works for you, I haven't really tested it out so we'll see.让我知道它是如何为你工作的,我还没有真正测试过它,所以我们会看到。

alias_method_chain is deprecated in Rails 5 , and it seems the Behavior process method has changed. 在 Rails 5 中不推荐使用alias_method_chain ,似乎 Behavior 过程方法已更改。

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 的专家,所以如果这个答案有什么可以改进的地方,请告诉我,我会改变它。

I ran into this problem with a failing cucumber test.我在黄瓜测试失败时遇到了这个问题。 I use locales as parameters in the url, ie http://mysite.com/home?locale=he我在 url 中使用 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 来从 url 中删除所有与语言环境相关的内容:

  # 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

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.该解决方案的优势在于,它意味着您只能将默认语言环境参数应用于某些测试用例,因此您可以测试例如重定向策略本身。

Things changed again with Ruby 5.1. Ruby 5.1 再次发生了变化。 Here's what worked for me:以下是对我有用的内容:

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

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

default_url_options are not used when processing functional tests and it doesn't seem there is a way to define defaults without monkey patching ( master branch from October 15th 2021 ).处理功能测试时不使用default_url_options并且似乎没有办法在没有猴子补丁的情况下定义默认值( 2021 年 10 月 15 日的 master 分支)。

So I managed to get it working by overwriting the ActionController::TestCase#process method within the test/test_helper.rb file as follows:所以我设法通过覆盖test/test_helper.rb文件中的ActionController::TestCase#process方法来让它工作,如下所示:

class ActionController::TestCase
  module DefaultParameters
    def process(action, params: {}, **args)
      params[:locale] ||= 'en'
      super(action, params: params, **args)
    end
  end
  prepend DefaultParameters
end

The above code works with Rails 6.1.4 but might need some adjustments for earlier or future Rails versions.上述代码适用于 Rails 6.1.4,但可能需要对较早或未来的 Rails 版本进行一些调整。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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