Это спецификация для очень типичного контроллера с before_filter
, который перенаправляет на страницу входа, когда незарегистрированный пользователь (он же гость) пытается получить доступ к /projects/new
.
describe ProjectsController do
(...)
describe "GET new" do
context 'when not logged in' do
before { sign_in_nobody }
context 'creating project' do
before { get :new }
it 'denies access' do
expect(response).to be_redirect
end
end
end
end
end
Я указал все возможные результаты доступа к :index
, :show
и :new
для гостей, пользователей, администраторов и суперадминистраторов. У меня не было никаких проблем с использованием ни зарегистрированных, ни гостевых пользователей, администраторов или нет, но на самом деле это первый раз, когда эта спецификация коснулась действия, которое включает before_filter :autheticate_user!
Devise, и это с треском проваливается.
Как вы, наверное, уже подозреваете, спецификация даже не достигает expect(response).to be_redirect
, а до этого шипит:
Failures:
1) ProjectsController GET new when not logged in creating project denies access
Failure/Error: get :new
ArgumentError:
uncaught throw :warden
# ./spec/controllers/projects_controller_spec.rb:344:in `block (5 levels) in <top (required)>'
Я искал ответ на вопрос: "как правильно протестировать неаутентифицированных (гостей) пользователей с помощью rspec и devise", но все говорят только о проблемах с фактической регистрацией пользователей в devise для RSpec для использовать. Проблема, которую я решил таким образом:
#spec/support/devise_authenticators.rb
include Devise::TestHelpers
def sign_in_nobody
@request.env["devise.mapping"] = Devise.mappings[:user]
sign_in User.new
end
def sign_in_user
@request.env["devise.mapping"] = Devise.mappings[:user]
sign_in FactoryGirl.create(:user)
end
Однако здесь не удается войти в систему, а «не войти в систему». Пока я не получил абсолютно ничего, и я знаю, что люди ДОЛЖНЫ каким-то образом протестировать эти сценарии.
Сейчас я использую обходной путь:
before { sign_in_nobody }
context 'creating project' do
it 'denies access' do
expect{ get :new }.to raise_exception("uncaught throw :warden")
end
end
Но даже несмотря на то, что это практически правильно (uncaught throw :warden
происходит только тогда, когда authenticate_user!
терпит неудачу, поэтому его можно использовать как ожидание), в теории это кажется действительно грязным.
Любые идеи, как это сделать правильно?
(...Может быть, мне вообще не следует это проверять, учитывая, что правильность before_filter authenticate_user!
является ответственностью Devise, а не моей?)