Capybara,Devise,CanCan和RSpec集成测试:有效登录302重定向到example.com [英] Capybara, Devise, CanCan and RSpec integration tests: valid sign in 302 redirects to example.com

查看:254
本文介绍了Capybara,Devise,CanCan和RSpec集成测试:有效登录302重定向到example.com的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:有关规范现在的工作原理,请参阅我们的规范/ spec,而不是spec / controllers。仍然想知道如何获得一个有效的登录用户进行集成测试与我的控制器。



我正在与Devise和CanCan第一次工作,最基本的集成测试,我正在验证一个登录的用户... ...登录。我已经阅读了无数的处理Devise和RSpec集成测试的帖子和答案(即通过直接访问会话加速它们)通过 https://github.com/plataformatec/devise/ wiki / How-To%3a-Test-with-Capybara http://schneems.com/post/15948562424/speed-up-capybara-tests-with-devise Capybara,RSpec和Devise:任何方式使集成t可以通过避免缓慢的登录和直接设置会话来加快收益?,但是我一直无法按期望得到一个标准的职位,我感到困惑:


  1. 开发环境工作正常(可以登录并重定向到正确的页面,导航登录链接更改为注销等)。

  2. test.log表示没有任何问题,直到302重定向到 http://www.example.com ,而不是我的root_path。

由于具有不同解决方案的类似问题的用户众多,我显然不是唯一一个有这个问题的人,因为各方面会话等在不同的情况下不可用。



剥离测试:

  subject {page} 

描述'应该能够登录'do
之前
访问'/ users / sign_in'
user = FactoryGirl。 create(:admin)
#user.add_role:a dmin
fill_in'Username',with:user.username
fill_in'Password',with:user.password
click_on'登录'
end
it {should has_link'Logout'}
end
...

相关log.test输出:

 启动POST/ users / sign_in为127.0.0.1在2012-11-06 17:31:10  - 0800 
Devise :: SessionsController#创建为HTML
参数:{utf8=>✓,user=> {username=>username1,密码=>[FILTERED],remember_me=>0},commit=>登录}
[1m [36mUser Load(0.1ms)[0m [1mSELECT users。* FROMusersWHEREusers。username='username1'LIMIT 1 [0m
[1m [35m(0.0ms)[0m SAVEPOINT active_record_1
[1m [36m 0.0m)[0m [1mRELEASE SAVEPOINT active_record_1 [0m
[1m [35m(0.0ms)] [0m SAVEPOINT active_record_1
[1m [36m(0.1ms)[0m [1mUPDATEusersSETlast_sign_in_at ='2012-11-07 01:31:10.722712', current_sign_in_at='2012-11-07 01:31:10.722712',last_sign_in_ip='127.0.0.1',current_sign_in_ip='127.0.0.1',sign_in_count= 1,updated_at=' 11- 07 01:31:10.723051'WHEREusers。id= 1 [0m
[1m [35m(0.0ms)] [0m RELEASE SAVEPOINT active_record_1
重定向到http: example.com/
完成302找到12ms(ActiveRecord:0.0ms)

routes.rb:

  authenticated:user do 
root:to => 'home#index'
end
root:to => home#index
devise_for:users
resources:users

能力:



class能力
包含CanCan ::能力

  def initialize(user)
user || = User.new#guest用户(未登录)
如果user.has_role? :admin
可以:管理,全部
结束
...

要彻底,现在的Gemfile:

 源'https://rubygems.org'

gem'rails','3.2.8'
gembootstrap-sass,〜> 2.1.0.1
gem'faker','1.1.2'
gem'will_paginate','〜> 3.0.3'
gem'bootstrap-will_paginate','〜> 0.0.9'
gem'jquery-rails'
gem'client_side_validations'
gem'thin'
gemdevise,〜> 2.1.2
gemcancan,〜> 1.6.8
gemrolify,〜> 3.2.0
gemsimple_form,〜> 2.0.4

group:assets do
gem'sass-rails','〜> 3.2.3'
gem'coffee-rails','〜> 3.2.1'
gem'uglifier','> = 1.0.3'
end

组:开发,:test do
gem'sqlite3' '1.3.5'
gemrspec-rails,〜> 2.11.4
gem'guard-rspec','1.2.1'
#gem'listen' github:'guard / listen',branch:'polling / double'
gem'guard-spork'
gem'guard-cucumber'
gem'spork','0.9.2'
gemfactory_girl_rails,> = 4.1.0
end

group:development do
gem'annotate','2.5.0'
gemquiet_assets,> = 1.0.1
end

group:test do
gem'capybara',> = 1.1.2
gememail_spec,> = 1.2.1
gemcucumber-rails,> = 1.3.0,:require => false
gemdatabase_cleaner,> = 0.9.1
gemlaunchy,> = 2.1.2
gem'rb-fsevent','0.9.1 ',:require => false
gem'growl','1.0.3'
gem'terminal-notifier-guard'
end

group:production do
gem' pg','0.12.2'
end

还有另一个用户有这个问题基本的任务,但事实证明它只是一个语法错误(请参阅使用rspec登录集成测试/ devise ),所以我确定我只是错过了一些非常明显的东西。



更新:



你必须在开玩笑吧。离开它几个小时后,原来我在spec / controller中有一些原因,当简单的切换到spec /请求使一切都是绿色的。



我引用:


如果您使用Rails,请将您的Capybara规格在规范/请求或
规范/集成中。


https://github.com/jnicklas/capybara#readme



然而,我是仍然想知道如何为将来的要求,我可以在我的控制器上进行集成测试,需要有一个登录用户....对于其他非Devise应用程序过去,这已经像以下一样简单: p>

 描述SomeController do 

let(:user){FactoryGirl.create(:user)}

之前{valid_sign_in user}

...

我的帮手只是简单的

  def valid_sign_in(user)
访问signin_path
fill_in电子邮件 :user.email
fill_inPassword,带:user.password
uncheck( :remember_me)
click_button登录

#当不使用Capybara时登录。
cookies [:remember_token] = user.remember_token
end


解决方案

有两个问题:



1。 rspec / controller vs rspec / requests



我试图在spec / controller下进行集成测试。根据 https://github.com/jnicklas/capybara#readme ,您需要将Capybara规范/请求或规范/集成规范。根据 http://stackoverflow.com/a/5803121/9344


请求规范是围绕
ActionDispatch :: IntegrationTest的薄包装,它不像控制器
规范(其中包含ActionController :: TestCase)。即使有一个
会话方法可用,我不认为它是支持的(即它是
可能是因为一个包含其他实用程序
的模块也包括该方法) / p>

最初这可以通过帮助方法解决Devise,如:

 #file:spec / requests_helper.rb 
def login(user)
post_via_redirect user_session_path,'user [email]'=> user.email,'user [password]'=> user.password
end

但是我已经实现的官方/最新解决方案但是请看下面第二点为什么没有解决我的问题),可以在 https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara



<强> 2。 Devise :: HelperTests是用于控制器/查看测试,而不是集成测试。



如果我想对控制器,我可以使用Devise :: TestHelpers(通过spec_helper.rb引用),但即使这样我也不会获得Capybara集成测试的功能,因为Devise :: TestHelpers专门用于控制器/视图测试,而不是集成测试。请参阅 rspec&设计测试助手



总而言之,我想在控制器测试中做的事情是无法做到的,因为它实际上是一个集成测试,会话等不可用在规格/控制器。但是,有一些Devise测试助手可以用来帮助执行控制器/视图测试。



更新



我稍后重新审视,现在已经有了Warden帮助者在我的集成测试中运作。欢呼!这在448次测试中已经取消了8-10秒。诀窍是 https://github.com上的新条目/ plataformatec /色器件/维基/操作方法: - 测试与 - 水豚。具体来说:


Capybara-Webkit



如果您在使用Warden的login_as方法时遇到问题
与capybara-webkit驱动程序,尝试在
中将run_callbacks设置为false login_as选项结构




  user = Factory.create(:user)
login_as(user,:scope =>:user,
:run_callbacks => false)
login_as(user,:scope =>:user,:run_callbacks => false)
(当然,重构为辅助方法)


Update: see end of post for how the specs now work now that I have my specs in spec/requests instead of spec/controllers. Still wondering how to get a valid signed in user for integration tests with my controllers.

I'm working with Devise and CanCan for the first time and am having difficulty doing the most basic of integration tests whereby I'm verifying that a logged in user is...well...logged in. I have read countless posts and answers dealing with Devise and RSpec integration tests (i.e. speeding them up by accessing the session directly via https://github.com/plataformatec/devise/wiki/How-To%3a-Test-with-Capybara, http://schneems.com/post/15948562424/speed-up-capybara-tests-with-devise, and Capybara, RSpec and Devise: any way to make integration tests faster by circumventing slow login and setting session directly?, but I have been unable to even get a standard post working as expected and I'm baffled:

  1. Development environment works fine (can log in and get redirected to proper page, with navigation login link changed to logout, etc.).
  2. test.log indicates no problems until it does a 302 redirect to http://www.example.com instead of my root_path.

By the plethora of users with similar issues with varying solutions, I'm obviously not the only one who has had this problem as various aspects of the session etc. are unavailable in different scenarios.

Stripped down test:

subject { page }

describe 'should be able to log in' do
  before do
    visit '/users/sign_in'
    user = FactoryGirl.create(:admin)
    #user.add_role :admin
    fill_in 'Username', with: user.username
    fill_in 'Password', with: user.password
    click_on 'Sign in'
  end
  it { should have_link 'Logout' }
end
...

Relevant log.test output:

 Started POST "/users/sign_in" for 127.0.0.1 at 2012-11-06 17:31:10 -0800
 Processing by Devise::SessionsController#create as HTML
 Parameters: {"utf8"=>"✓", "user"=>{"username"=>"username1", "password"=>"[FILTERED]",        "remember_me"=>"0"}, "commit"=>"Sign in"}
 [1m[36mUser Load (0.1ms)[0m  [1mSELECT "users".* FROM "users" WHERE "users"."username" =   'username1' LIMIT 1[0m
 [1m[35m (0.0ms)[0m  SAVEPOINT active_record_1
    [1m[36m (0.0ms)[0m  [1mRELEASE SAVEPOINT active_record_1[0m
 [1m[35m (0.0ms)[0m  SAVEPOINT active_record_1
 [1m[36m (0.1ms)[0m  [1mUPDATE "users" SET "last_sign_in_at" = '2012-11-07   01:31:10.722712', "current_sign_in_at" = '2012-11-07 01:31:10.722712', "last_sign_in_ip" =   '127.0.0.1', "current_sign_in_ip" = '127.0.0.1', "sign_in_count" = 1, "updated_at" = '2012-11-  07 01:31:10.723051' WHERE "users"."id" = 1[0m
 [1m[35m (0.0ms)[0m  RELEASE SAVEPOINT active_record_1
 Redirected to http://www.example.com/
 Completed 302 Found in 12ms (ActiveRecord: 0.0ms)

Stripped down routes.rb:

authenticated :user do
  root :to => 'home#index'
end
root :to => "home#index"
devise_for :users
resources :users

Stripped down Ability:

class Ability include CanCan::Ability

 def initialize(user)
  user ||= User.new # guest user (not logged in)
  if user.has_role? :admin
    can :manage, :all
  end
  ...

And to be thorough, the current Gemfile:

source 'https://rubygems.org'

gem 'rails', '3.2.8'
gem "bootstrap-sass", "~> 2.1.0.1"
gem 'faker', '1.1.2'
gem 'will_paginate', '~> 3.0.3'
gem 'bootstrap-will_paginate', '~> 0.0.9'
gem 'jquery-rails'
gem 'client_side_validations'
gem 'thin'
gem "devise", "~> 2.1.2"
gem "cancan", "~> 1.6.8"
gem "rolify", "~> 3.2.0"
gem "simple_form", "~> 2.0.4"

group :assets do
   gem 'sass-rails',   '~> 3.2.3'
   gem 'coffee-rails', '~> 3.2.1'
   gem 'uglifier', '>= 1.0.3'
end

group :development, :test do
 gem 'sqlite3', '1.3.5'
 gem "rspec-rails", "~> 2.11.4"
 gem 'guard-rspec', '1.2.1'
 #gem 'listen', github: 'guard/listen', branch: 'polling/double'
 gem 'guard-spork'
 gem 'guard-cucumber'
 gem 'spork', '0.9.2'
 gem "factory_girl_rails", ">= 4.1.0"
end

group :development do
  gem 'annotate', '2.5.0'
  gem "quiet_assets", ">= 1.0.1"
end

 group :test do
  gem 'capybara', ">= 1.1.2"
 gem "email_spec", ">= 1.2.1"
 gem "cucumber-rails", ">= 1.3.0", :require => false
 gem "database_cleaner", ">= 0.9.1"
 gem "launchy", ">= 2.1.2"
 gem 'rb-fsevent', '0.9.1', :require => false
 gem 'growl', '1.0.3'
 gem 'terminal-notifier-guard'
end

group :production do
    gem 'pg', '0.12.2'
 end

There's another user who had issues with this basic task, but it turned out it was simply a syntax error (see Login integration test with rspec/devise) so I'm sure I'm just missing something very obvious.

Update:

You have got to be kidding me. After leaving it for a couple hours, it turns out I had this spec for some reason in spec/controllers, when simply switching it over to spec/requests made everything green.

I quote:

If you are using Rails, put your Capybara specs in spec/requests or spec/integration.

Found at https://github.com/jnicklas/capybara#readme

However, I'm still wondering how for future requirements I can do integration tests on my controllers that will need to have a logged in user.... for other non-Devise apps in the past, this has been as simple as something like the following:

describe SomeController do

  let(:user) { FactoryGirl.create(:user) }

  before { valid_sign_in user }

...

where my helper is simply

  def valid_sign_in(user)
    visit signin_path
    fill_in "Email", with: user.email
    fill_in "Password", with: user.password
    uncheck(:remember_me)
    click_button "Sign In"

    # Sign in when not using Capybara as well.
    cookies[:remember_token] = user.remember_token
  end

解决方案

There are two issues at play:

1. rspec/controller vs rspec/requests

I was attempting to do an integration test under spec/controller. As per https://github.com/jnicklas/capybara#readme, you need to put Capybara specs in spec/requests or spec/integration. As per http://stackoverflow.com/a/5803121/9344:

A request spec is a thin wrapper around ActionDispatch::IntegrationTest, which doesn't work like controller specs (which wrap ActionController::TestCase). Even though there is a session method available, I don't think it is supported (i.e. it's probably there because a module that gets included for other utilities also includes that method).

Originally this could be solved with Devise via a helper method something like:

# file: spec/requests_helper.rb
def login(user)
  post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
end

But the official/latest solution, which I had implemented already (but see point two below for why it didn't solve my issue), can be found at https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara

2. Devise::HelperTests are for controller/view tests, not integration tests.

If I want to do some tests on a controller, I can use the Devise::TestHelpers (referenced via spec_helper.rb) but even then I don't get functionality for Capybara integration tests as the Devise::TestHelpers are specifically written for controller/view tests, not integration tests. See rspec & devise test helpers.

In summary, what I wanted to do in a controller test can't be done because it was really an integration test and the session etc. isn't available for use in spec/controllers. However, there are some Devise test helpers that can be used to help do controller/view tests.

UPDATE

I revisited this much later, and have now got the Warden helpers functioning on my integration tests. Hurrah! This has taken off 8-10 seconds on my 448 tests. The trick was a new entry on https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara. Specifically:

Capybara-Webkit

If you have trouble using Warden's login_as method with the capybara-webkit driver, try setting run_callbacks to false in the login_as options struct

user = Factory.create(:user) 
login_as(user, :scope => :user,
:run_callbacks => false)

In summary, instead of having to do an actual form fill and post for each time I needed an authenticated user for an integration test, now I just need login_as(user, :scope => :user, :run_callbacks => false) (of course refactored out into a helper method).

这篇关于Capybara,Devise,CanCan和RSpec集成测试:有效登录302重定向到example.com的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆