Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Delete request in capybara, bug or my mistake?

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
like image 388
ardiyu07 Avatar asked May 08 '13 14:05

ardiyu07


2 Answers

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".

like image 155
nowk Avatar answered Oct 21 '22 09:10

nowk


You can try following:

page.driver.submit :delete, '/users/sign_out', {}
like image 41
Alexey Poimtsev Avatar answered Oct 21 '22 09:10

Alexey Poimtsev