In my application_controller, I have the following set to include the locale with all paths generated by url_for:
def default_url_options(options={})
{ :locale => I18n.locale }
end
My resource routes then have a :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 t开发者_运维技巧he url in my tests, like so:
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.
Is there any way I can change the default_url_options to include the locale for all my tests?
Thanks.
For Rails 5, I found this simple solution
In test_helper.rb
based on action_dispatch/testing/integration.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. 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.
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):
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:
Rails.application.configure do
# ... other config ...
routes.default_url_options[:locale] = :en
end
Works on 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. 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):
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.
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.
alias_method_chain
is deprecated in Rails 5, and it seems the Behavior process method has changed.
Here's my modification of Martin Carel's answer above, adapted to 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.
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
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:
# 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. 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):
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).
So I managed to get it working by overwriting the ActionController::TestCase#process
method within the test/test_helper.rb
file as follows:
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.
精彩评论