tutorial tests test run rails how ruby-on-rails rspec devise cancan

ruby on rails - tests - ¿Cómo hacer pruebas de integración con RSpec y Devise/CanCan?



rspec rails tutorial (6)

Si tengo un usuario modelo de 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?

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

Esto fue pseudo-sugerido en la respuesta a esta pregunta: Autenticación de anotación en especificación de solicitud , pero no puedo por mi vida hacer que funcione con el dispositivo. 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 forma actual de hacerlo es aquí: http://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara


A mediados de 2017, tenemos una oportunidad más, en mi opinión, de integrar el dispositivo en nuestras Rspecs. Podemos utilizar autenticación de stub con el método de sign in ayuda 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 debe agregar 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

Luego, en el método, simplemente coloque al comienzo del método body 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 aquí


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



La propia respuesta de @ pschuegr me llevó al otro lado de la línea. Para completar, esto es lo que hice que me permite configurar fácilmente tanto las especificaciones de solicitud como las especificaciones del controlador (usando FactoryGirl para crear 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

Luego, en especificación de solicitud:

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, use ''signed_in_as_valid_user'' en las especificaciones del controlador (que ajusta el método Devise :: TestHelpers sign_in con un usuario de FactoryGirl)


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 atributo CanCan que desee. Entonces, en tu especificación:

describe YourController do login_user it "should ..." do end


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

En mi spec / support / macros.rb agregué:

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 incluyó eso 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 solicitud en sí:

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 me permite usar current_user en before_filters, por ejemplo.