In Michael Hartl's Rails Tutorial (Rails 3.2), in Listing 9.52:
describe "when signing in again" do
before do
delete signout_path
print page.html <---- Insert this here
visit signin_path
print page.html <---- Insert here again
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
it "should render the default (profile) page" do
page.should have_selector('title', text: user.name)
end
end
I inserted those two prints. And, surprisingly I got the printout of the same page (which shouldn't be, It was supposed to bring you back to the root url after sending the DELETE
request). After this happens, since visit signin_path
takes me back to the sign in page, the sign in procedure succeeds and so does the test case. However, the second print page.html
gave me the header of a user whom is still signed in.
When I changed delete signout_path
to click_link "Sign out"
, it worked.
Did I miss something in my code or it's a Capybara bug? (Cause I'm pretty sure I followed everything just right..)
UPDATE:
If I change delete signout_path
to Capybara.current_session.driver.delete signout_path
it also works just fine. (Meaning capybara signs out the user correctly)
UPDATE
These are the files (sessions controller and helper):
sessions_controller.rb
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
sign_in user
redirect_back_or user
else
flash.now[:error] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
sign_out
redirect_to root_url
end
end
sessions_helper.rb
module SessionsHelper
def sign_in(user)
cookies.permanent[:remember_token] = user.remember_token
self.current_user = user
end
def signed_in?
!current_user.nil?
end
def current_user=(user)
@current_user = user
end
def current_user?(user)
user == current_user
end
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def current_user
@current_user ||= User.find_by_remember_token(cookies[:remember_token])
end
def sign_out
self.current_user = nil
cookies.delete(:remember_token)
end
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
session.delete(:return_to)
end
def store_location
session[:return_to] = request.url
end
end
routes.rb
DemoApp::Application.routes.draw do
...
root to: 'static_pages#home'
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
resources :sessions, only: [:new, :create, :destroy]
...
end
delete signout_path
does not work on Capybara feature specs. get
, post
, put
, delete
are Controller spec specific methods and are not available in feature specs.
You also want to be making actual requests (via click, submit, etc...) in Capybara specs since that is generally what you are trying to test.
If you want to ensure a session is clear as a "setup" it's best to do it via the model.
As an aside, if you look at what you are describing "when signing in again", you probably want to actually "log out" so you can actually "sign in again".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With