Testing with Rspec, NiftyAuthentication
I'm using Ryan Bates's nifty:authentication
, and starting testing with Rspec. Fought with this for weeks, and still don't understand what's happening.
My controller simply calls
before_filter :login_required, :except => [:login]
Which is defined in lib/controller_authentication
def self.included(controller)
controller.send :helper_method, :current_account, :logged_in?, :redirect_to_target_or_default
end
def current_account
@current_account ||= Account.find(session[:account_id]) if session[:account_id]
end
def logged_in?
current_account
end
def login_required
unless logged_in?
store_target_location
redirect_to login_url, :alert => "You must first answer me these riddles three log in or sign up before accessing this page."
end
end
def redirect_to_target_or_default(default, *args)
redirect_to(session[:return_to] || default, *args)
session[:return_to] = nil
end
private
def store_target_location
session[:return_to] = request.url
end
end
The app works as intended, but the testing fails every time. No matter what I try, I get the redirect_to login_url, :alert => "You must first ...log in"
page.
Things I've tried:
controller.stub!( :login_required )
ControllerAuthentication.stub!(:current_account).and_return(Account.where(:username => 'ej0c').first)
#ControllerAuthentication.stub!(:logged_in?).and_return(Account.where(:username => 'ej0c').first)
ControllerAuthentication.stub!(:login_required).and_return(true)
MyDigisController.stub!( :login_required ).and_return(true)
Which I think means I'm missing the whole theory of the thing. How can I make my login work?
I tried as Punit suggests below: [pre]
require 'spec_helper'
describe "View event details" do
it "Should show a table of events" do
@account = Accou开发者_运维问答nt.where(:username => 'ej0c').first
puts @account.inspect
controller.stub!(:current_account).and_return(@account)
controller.stub!(:logged_in?).and_return(true)
session[:account_id] = @account.id
visit '/my_digis/66/custom_events'
page.should have_content('Events')
end
end
@account.inspect displayed nicely, but I also got
An expectation of :current_account was set on nil. Called from C:/Users/Ed/webapps/whendidji3/spec/con
.rb:8:in `block (2 levels) in <top (required)>'. Use allow_message_expectations_on_nil to disable warn
An expectation of :logged_in? was set on nil. Called from C:/Users/Ed/webapps/whendidji3/spec/controll
:in `block (2 levels) in <top (required)>'. Use allow_message_expectations_on_nil to disable warnings.
Thanks for any detailed explanations, as I've searched high an low to understand what's goin on.
You are using a vanilla spec rather than a controller spec, which means that the variable 'controller' is not being set.
To use a controller spec, you need to pass the controller class name to your describe block rather than a string.
describe MyController do
see http://rspec.info/rails/writing/controllers.html
Once you have that going, you should be able to use your original thought of stubbing login_required
You need to stub the "current_account" method. You could do it like this -
@account = create_account #function to create an account for your specs
controller.stub!(:current_account).and_return(@account)
controller.stub!(:logged_in?).and_return(true)
You should probably create a method out of the above lines to stub authentication wherever required.
OK, the answer was that I needed a request spec.
I'd begun with a request spec, but it wasn't in the requests
folder, and the questions I asked got it morphed into a half-request/half-controller spec, none of which works.
The strange thing about rspec is that it will complain if a capybara method is badly formed,...but it won't mention that the thing just plain doesn't work where you put it!
My working spec, located in specs/requests/my_digis_spec.rb
is
require 'spec_helper'
describe "MyDigis" do
before :each do
@account = Account.where(:username => 'me').first
visit login_path
fill_in 'Username or Email Address', :with => @account.email
fill_in 'Password', :with => 'password'
click_button('Log in')
end
it "Shows list of digis" do
visit my_digis_path
page.should have_content('Your Custom Event groups')
end
it "Lets you modify didji list" do
visit my_digis_path
click_button('Modify events')
page.should have_content('Events for my_digi')
end
end
As easy as advertised, just took me 5 weeks to get the login part. Thanks.
精彩评论