2011-05-03 11 views
35

Si tengo un usuario del modelo Devise, del cual solo aquellos usuarios con la función: admin pueden ver una determinada URL, ¿cómo puedo escribir una prueba de integración RSpec para verificar que el estado arroje 200 para esa url?¿Cómo hacer pruebas de integración con RSpec y Devise/CanCan?

def login(user) 
    post user_session_path, :email => user.email, :password => 'password' 
end 

Ésta era pseudo-se sugiere en la respuesta a esta pregunta: Stubbing authentication in request spec, pero no puedo por la vida de mí conseguir que funcione con el legado. CanCan recibe un usuario nulo cuando verifica la habilidad, que no tiene los permisos correctos, naturalmente.

No hay acceso al controlador en las especificaciones de integración, por lo que no puedo anotar el actual_user, pero me gustaría hacer algo como esto.

describe "GET /users" do 
    it "should be able to get" do 
    clear_users_and_add_admin #does what it says... 
    login(admin) 
    get users_path 
    response.status.should be(200) 
    end 
end 

NOTA !!!: todo esto ha cambiado desde que se hizo la pregunta. La mejor manera actual de hacer esto es aquí: http://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara

+2

Nota: todo esto ha cambiado desde que se hizo la pregunta. La mejor forma actual de hacerlo es aquí: http://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara Solo para reiterar a los primeros lectores suspiro como yo –

Respuesta

47

La propia respuesta de pschuegr me hizo cruzar la línea. Para completar, esto es lo que hice que me consigue fácilmente configurado para ambas especificaciones de petición y las especificaciones del controlador (utilizando factorygirl para la creación de la instancia de usuario):

en /spec/support/sign_in_support.rb:

#module for helping controller specs 
module ValidUserHelper 
    def signed_in_as_a_valid_user 
    @user ||= FactoryGirl.create :user 
    sign_in @user # method from devise:TestHelpers 
    end 
end 

# module for helping request specs 
module ValidUserRequestHelper 

    # for use in request specs 
    def sign_in_as_a_valid_user 
    @user ||= FactoryGirl.create :user 
    post_via_redirect user_session_path, 'user[email]' => @user.email, 'user[password]' => @user.password 
    end 
end 

RSpec.configure do |config| 
    config.include ValidUserHelper, :type => :controller 
    config.include ValidUserRequestHelper, :type => :request 
end 

Entonces en la solicitud de especificaciones:

describe "GET /things" do 
    it "test access to things, works with a signed in user" do 
    sign_in_as_a_valid_user 
    get things_path 
    response.status.should be(200) 
    end 
end 

describe "GET /things" do 
    it "test access to things, does not work without a signed in user" do 
    get things_path 
    response.status.should be(302) # redirect to sign in page 
    end 
end 

y de manera similar, utilizar 'signed_in_as_valid_user' en especificaciones del controlador (que envuelve Idear :: TestHelpers sign_in método con un usuario de factorygirl)

+0

He definido los mismos módulos que mencionó, pero obtengo este error 'variable local indefinida o método' sign_in_as_a_valid_user 'para # (NameError) '. ¿Dónde estoy cometiendo un error? – rohitmishra

+0

Esto está en una especificación de solicitud, ¿verdad? ¿Se está ejecutando el código 'Rspec.configure'? –

+0

Sí, esto está en una especificación de solicitud. ¿Cómo puedo verificar si el código 'Rspec.configure' se ejecuta? – rohitmishra

0

Puede crear una macro (/spec/support/controller_macros.rb) y escribir algo como:

module ControllerMacros 
    def login_user 
    before(:each) do 
     @request.env["devise.mapping"] = :user 
     @user = Factory(:user) 
     sign_in @user 
    end 
    end 
end 

También puede incluir cualquier CanCan le atribuye querer. Entonces, en su especificación:

describe YourController do 
    login_user 

    it "should ..." do 

    end 
+3

Gracias por su comentario Spyros, pero funciona bien en el controlador usando Devise :: TestHelpers. Está solo en las especificaciones de solicitud, no funciona (@request es nil). – pschuegr

+0

Menciona que recibe un usuario nulo. Esto significa que la especificación no inicia sesión en el usuario. ¿Estás seguro de que usas ayudantes e inicias sesión correctamente? Puedes probar eso dentro de tu especificación para asegurarte. Si no, puedes probar el código de arriba. Creo que todo proviene del hecho de que su especificación no inicia sesión en un usuario. – Spyros

+2

Esta respuesta es para pruebas de controlador, no pruebas de integración, como la pregunta fue para - los comentarios sobre el usuario nulo submitidos por el solicitante es porque la respuesta es para la situación incorrecta – Houen

28

Ah, tan cerca. Esto funciona: me faltaba la forma de parámetro adecuada y el redireccionamiento.

post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password 
+0

Justo lo que estaba buscando. Gracias! F – John

+4

Tuve que usar 'page.driver.post' en lugar de' post_via_redirect' (solicitud de especificaciones) –

+2

hey cómo puedo user_usuario_actual en casos de prueba de especificación de solicitud como la que usamos en casos de pruebas de especificaciones de controlador – sharath

20

Utilicé un enfoque ligeramente diferente, usando Warden :: Test :: Helpers.

En mi spec/support/macros.rb añadí:

module RequestMacros 
    include Warden::Test::Helpers 

    # for use in request specs 
    def sign_in_as_a_user 
    @user ||= FactoryGirl.create :confirmed_user 
    login_as @user 
    end 
end 

Y luego que se incluye en la configuración de RSpec en spec_helper.rb:

RSpec.configure do |config| 
    config.include RequestMacros, :type => :request 
end 

Y luego en las especificaciones de petición a sí mismos:

describe "index" do 
    it "redirects to home page" do 
    sign_in_as_a_user 
    visit "/url" 
    page.should_not have_content 'content' 
    end 
end 

En contraste con el método post_via_redirect user_session_path, esto realmente funciona y todos me permite usar current_user en before_filters, por ejemplo.

+0

Artículo de Wiki: https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara –

0

A mediados de 2017, tenemos una más, en mi opinión es mejor opprotunity integrar legado en nuestros Rspecs. Somos capaces de utilizar authentization talón con método de ayuda sign in definido como se describe a continuación:

module ControllerHelpers 
    def sign_in(user = double('user')) 
     if user.nil? 
     allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, {:scope => :user}) 
     allow(controller).to receive(:current_user).and_return(nil) 
     else 
     allow(request.env['warden']).to receive(:authenticate!).and_return(user) 
     allow(controller).to receive(:current_user).and_return(user) 
     end 
    end 
    end 

También debería añadir en spec_helper.rb o rails_helper.rb referencia al archivo recién creado:

require 'support/controller_helpers' 
    ... 
    RSpec.configure do |config| 
    ... 
    config.include Devise::TestHelpers, :type => :controller 
    config.include ControllerHelpers, :type => :controller 
    ... 
    end 

A continuación, en el método Sólo tiene que colocar en el el comienzo del cuerpo del método sign_in para el contexto del usuario autenticado y ya está todo listo. Los detalles actualizados se pueden encontrar en los documentos de diseño here

Cuestiones relacionadas