2009-12-31 19 views
9

En mi application_controller, tengo el siguiente conjunto de incluir la configuración regional con todos los caminos generados por url_for:Cómo establecer default_url_options de localización para las pruebas funcionales (rieles)

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

Mis rutas de recursos a continuación tienen una: path_prefix = "/: locale"

Funciona bien en el sitio.

Pero cuando se trata de mis pruebas funcionales, el: locale no se pasa con las URL generadas, y por lo tanto todas fallan. Puedo conseguir alrededor de él mediante la adición de la configuración regional de la url en mis pruebas, así:

get :new, :locale => 'en' 

Pero yo no quiero tener que añadir manualmente la configuración regional de cada prueba funcional.

Intenté agregar la opción default_url_options def arriba para test_helper, pero parece no tener ningún efecto.

¿Hay alguna manera de que pueda cambiar las opciones_de_url predeterminadas para incluir la configuración regional para todas mis pruebas?

Gracias.

Respuesta

2

Mirando a través de cómo el caso de prueba del controlador genera la url no parece haber una manera directa de que use las opciones defualt_url_options. El bloque principal que realmente hace la creationg url (en las pruebas) se parece a esto (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 

Esto es llamado por el método de proceso que es a su vez llamado por el GET, POST, HEAD, o poner métodos. Una forma de obtener tal vez lo que está buscando podría ser alias_chain el método de proceso.

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 

Usted querrá poner esto en su ayudante de prueba, fuera de la clase TestCase creo. Déjame saber cómo funciona para ti, realmente no lo he probado, así que ya veremos.

+0

Gracias, John. ¡Eso resolvió el caso específico anterior y parece funcionar muy bien! Lo que no parece resolver es cómo TestCase interpreta las rutas con nombre, ya sea que estén en la prueba en sí o que se utilicen en la aplicación. Por ejemplo, si tengo una prueba: redirect_to homepage_url y homepath_url espera la configuración regional (map.homepage '/: locale',: controller => 'home'), me sale un error al ejecutar la prueba, que los requisitos de url no son satisfactorios (falta "locale"). De nuevo, la aplicación funciona bien ya que default_url_options se encarga de agregar la configuración regional. ¿Alguna manera de arreglar eso? –

+0

Permítanme agregar que si esto fuera solo un problema en la prueba, no sería tan malo. Puedo agregar la configuración regional siempre que use una ruta con nombre en una prueba. Pero el problema es que también genera un error cada vez que se usa una ruta con nombre en mi aplicación (y no quiero tener que cambiar todo eso o especificar la configuración regional cada vez para que se ejecuten mis pruebas). –

+0

Ah, no me di cuenta de que estaba sucediendo en tu aplicación también. Acabo de encontrar un boleto de faro que podría ayudarlo un poco (parece que todavía hay un problema, pero hay algunos problemas) https://rails.lighthouseapp.com/projects/8994/tickets/1251-default_url_options-cant -be-used-with-named-routes –

0

Con las pruebas de integración, he encontrado que el parche mono encima tiene que ser diferente, esto es lo que funcionó para mí (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

me encontré con este problema con una prueba de pepino en su defecto . utilizo lugares como parámetros en la URL, es decir http://mysite.com/home?locale=he

Lo que hago para hacer frente a esto es dejar caer todas las cosas relacionadas con la configuración regional de la url durante la prueba por default_url_options definen en función del entorno de uso:

# 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 
+0

No estoy seguro de si esto expone ciertos casos extremos, pero parece ser una solución elegante para mí. – Jaryl

1

He encontrado una solución menos invasiva para este problema.

setup :set_default_locale 

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

La ventaja de esta solución es que significa que sólo se puede aplicar el parámetro de configuración regional predeterminada para ciertos casos de prueba, para que pueda probar, por ejemplo, la estrategia de cambio de dirección en sí.

7

En la rama Estable de Rails 3.1, el process method se encuentra ahora en un módulo Behavior.Así que aquí está el código que funcionó para mí (un poco diferente de la respuesta de 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 

Y se aseguró de este código es llamado antes de ejecutar las especificaciones/pruebas. Un buen lugar para ponerlo es en la clase test_helper.

+0

Martin Carel presenta este método en http://www.ruby-forum.com/topic/3448797 y agrega otro método: 'módulo ActionDispatch :: Assertions :: RoutingAssertions def assert_recognizes_with_default_locale (expected_options, path, extras = { }, message = nil) expected_options = {: locale => I18n.default_locale.to_s }.fusionar (expected_options || {}) assert_recognizes_without_default_locale (expected_options, ruta, extras, mensaje) final alias_method_chain: assert_recognizes,: default_locale end' – wintersolutions

+1

También dijo que la modificación del método 'assert_recognizes' era una trampa ** ** . De hecho, no creo que sea una buena idea piratear sus herramientas de prueba de esa manera, en lugar de burlarse del código que está tratando de probar (como es el caso de agregar un método al módulo 'Comportamiento'). –

3

En caso de que alguien está usando esto con Rails 4.0, el orden de los argumentos en el método process ha cambiado, por lo que tendrá que utilizar este parche actualizado (basado en la respuesta de @ Martin-Carel, sólo con el argumento http_method trasladó al segundo argumento):

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 

la esperanza de que ayude a cualquiera atascado en este problema.

2

alias_method_chain es deprecated in Rails 5, y parece que el método de proceso de Comportamiento ha cambiado.

Aquí es mi modificación de la respuesta de Martin Carel anterior, adaptado a 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 

Estoy de ninguna manera un experto en rieles o Ruby, así que si algo se puede mejorar de esta respuesta, me dejó Sé y lo cambiaré.

+0

¡Sí! esta es la solución, y añadiendo a cada prueba quiero definir una configuración regional diferente 'antes: context do I18n.locale =: ca end' Puedo probar cualquier locale que necesite para cada circunstancia. Usando rieles 5.1.4.rc1 –

+0

Agregué 'if parameters [: params] .nil? parameters [: params] = {} end' before 'a menos que I18n.locale.nil? ....' para evitar crash para solicitud sin parámetros –

3

para los carriles 5, encontré esta solución simple En test_helper.rb

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

Gracias por esta respuesta, funcionó para mí. Aunque me preguntaba si hay alguna forma de utilizar un personalizar default_url_options desde ApplicationController, porque no tiene sentido escribir dos veces la misma configuración. – afaundez

+0

Esto funcionó para mí en Rails '5.1.4'. – taylorthurlow

1

cosas cambiaron de nuevo con Ruby 5.1. Esto es lo que funcionó para mí:

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 
Cuestiones relacionadas