Тестирование сессий в Rails 3 с помощью Rspec и Capybara

Я пытаюсь написать интеграционные тесты с помощью rspec, factory_girl и capybara. У меня тоже установлен огурец, но я им не пользуюсь (насколько мне известно).

Я в основном хочу предварительно заполнить базу данных моим пользователем, а затем перейти на мою домашнюю страницу и попытаться войти в систему. Он должен перенаправить на user_path (@user).

Однако сеансы, похоже, не сохраняются в моих / rspec / requests / интеграционных тестах.

Моя спецификация: /rspec/requests/users_spec.rb

require 'spec_helper'

describe "User flow" do

  before(:each) do
    @user = Factory(:user)
  end

  it "should login user" do

    visit("/index")

    fill_in :email, :with => @user.email
    fill_in :password, :with => @user.password
    click_button "Login"
    assert current_path == user_path(@user)
  end
end

Возврат:

Failures:

  1) User flow should login user
     Failure/Error: assert current_path == user_path(@user)
     <false> is not true.
     # (eval):2:in `send'
     # (eval):2:in `assert'
     # ./spec/requests/users_spec.rb:16

Вместо этого он перенаправляется на мой please_login_path - что должно произойти, если логин не удался по какой-либо причине (или если сессия [: user_id] не установлена).

Если я попытаюсь установить session.inspect, он потерпит неудачу как объект nil.

Если я попытаюсь сделать это в тестах контроллера (/rspec/controllers/sessions_spec.rb), я смогу получить доступ к сеансу без проблем и могу вызвать сеанс [: user_id]


person Tom Blomfield    schedule 08.03.2011    source источник
comment
Я не знаю, связано ли это, но вы не сможете получить пароль пользователя, набрав @ user.password. Это уязвимость в системе безопасности вашего приложения. Вы храните пароли в виде простого текста?   -  person Pan Thomakos    schedule 08.03.2011
comment
Это не связано и, вероятно, не является уязвимостью системы безопасности. Вызов #password возвращает только пароль, потому что он установлен Factory в переменной экземпляра. Скорее всего, он использует Devise или что-то подобное, что не сохраняет атрибут пароля для базы данных в виде открытого текста, и поэтому он не был бы доступен, если бы эта переменная экземпляра исчезла.   -  person Benjamin Curtis    schedule 16.03.2011


Ответы (3)


Если вы используете Devise, вам необходимо включить Warden :: Test :: Helpers (подходящее место сразу после запроса spec_helper), как указано в wiki надзирателя.

Вызов session возвращает nil, потому что capybara не предоставляет к нему доступа при запуске в качестве интеграционного теста.

person Benjamin Curtis    schedule 16.03.2011

У меня те же проблемы, и хотя заполнение формы может быть вариантом для некоторых, мне пришлось свернуть свой собственный рубин аутентификации, потому что я использовал стороннюю систему аутентификации (точнее, Janrain) .... в моих тестах я закончил используя что-то вроде этого:

Вот что у меня в spec / support / test_helpers_and_stuff.rb

module AuthTestHelper

  class SessionBackdoorController < ::ApplicationController
    def create
      sign_in User.find(params[:user_id])
      head :ok
    end
  end

  begin
    _routes = Rails.application.routes
    _routes.disable_clear_and_finalize = true
    _routes.clear!
    Rails.application.routes_reloader.paths.each{ |path| load(path) }
    _routes.draw do
      # here you can add any route you want
      match "/test_login_backdoor", to: "session_backdoor#create"
    end
    ActiveSupport.on_load(:action_controller) { _routes.finalize! }
  ensure
    _routes.disable_clear_and_finalize = false
  end

  def request_signin_as(user)
    visit "/test_login_backdoor?user_id=#{user.id}"
  end

  def signin_as(user)
    session[:session_user] = user.id
  end

end

Затем в моей спецификации запроса с капибарой и селеном я сделал следующее:

describe "Giveaway Promotion" do
  context "Story: A fan participates in a giveaway", js: :selenium do
    context "as a signed in user" do

      before :each do
        @user = Factory(:user)
        request_signin_as @user
      end

      it "should be able to participate as an already signed in user" do
        visit giveaway_path
        ....
      end
    end
  end
end

Кстати, я придумал решения после того, как попробовал предлагаемые решения для этот пост и этот пост, и ни один из них не помог мне. (но они определенно вдохновили мое решение)

Удачи!

person PeppyHeppy    schedule 03.12.2011

Вы, наверное, отошли от этого, но я просто боролся с тем же вопросом. Оказывается, дело в синтаксисе. Я использовал символы для :email и :password, и мне следовало использовать вместо них строки ("email" и "password").

Другими словами, попробуйте изменить это:

fill_in :email, :with => @user.email
fill_in :password, :with => @user.password

к этому:

fill_in "email", :with => @user.email
fill_in "password", :with => @user.password
person Ben Coppock    schedule 23.09.2011