views:

485

answers:

3

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 the 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.

+1  A: 

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 = nil, flash = nil, http_method = 'GET')
  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.

John Duff
Thanks, John. That solved the specific case above and seems to work great!What it doesn't seem to solve is how TestCase interprets named routes, whether they're in the test itself, or used in the application. For example, if I have in a test:redirect_to homepage_urland homepath_url expects the locale (map.homepage '/:locale', :controller => 'home'), I get an error, when running the test, that the url requirements are not satisfield (missing "locale"). Again, the application runs fine as default_url_options takes care of adding the locale. Any way to fix that?
insane.dreamer
Let me add that if this was only a problem in the test themselves, it wouldn't be so bad. I can just add the locale whenever used a named route in a test. But the problem is that it also generates an error whenever a named route is used in my application (and I don't want to have to change all that or specify the locale each time just so my tests will run).
insane.dreamer
Ah, I didn't realize it was happening in your app as well. I just came across a lighthouse ticket that might help you out a little bit (seems to still be an issue but there are some work arounds) https://rails.lighthouseapp.com/projects/8994/tickets/1251-default_url_options-cant-be-used-with-named-routes
John Duff
Other than that it's beyond me, might be worthwhile to ask another question specifically about the named routes and default_url_options not working in the app and see if anyone has any ideas.
John Duff
A: 

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
Balint Erdi
A: 

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