简体   繁体   中英

rspec test redirect failing

A Ghost is created once, upon User sign-up and creation. A User has_one Ghost. The following spec tests for a signed-in User trying to access the new Ghost action, which he should never be able to do.

describe "Ghost pages" do
  subject { page }
  let(:user) { FactoryGirl.create(:user) }
  describe "for signed-in user" do
    before do
      sign_in user
    end
    describe "in the Ghosts controller" do
      describe "submitting a GET request to the Ghosts#new action" do
        before { get new_ghost_path }
        specify { expect(response).to redirect_to(root_url) }
      end
    end
  end
end

The test fails with the following error:

Failure/Error: specify { expect(response).to redirect_to(root_url) }

Expected response to be a redirect to http://www.example.com/ but was a redirect to http://www.example.com/signin .

Expected " http://www.example.com/ " to be === " http://www.example.com/signin ".

I cannot fathom why it's redirecting to the signin url when it should redirect to the root url - the user is signed in in the spec.

Here is the GhostsController:

class GhostsController < ApplicationController
  before_action :signed_in_user
  before_action :correct_ghost, only: [:show]
  before_action :correct_destroyer, only: [:destroy]
  before_action :go_away, only: [:new, :index, :edit, :update]

  def index
  end

  def edit
  end

  def update
  end

  def new
  end

  def show
    @ghost = Ghost.find(params[:id])
  end

  def create
    @ghost = current_user.build_ghost(ghost_params)
    if @ghost.save
      flash[:success] = "Ghost successfully created"
    else
      flash[:error] = "Ghost creation failed"
    end
  end

  def destroy
    @ghost = Ghost.find(params[:id])
    @ghost.destroy
    flash[:success] = "Ghost deleted."
    redirect_to current_user
  end

  private

    def ghost_params
      params.require(:ghost).permit()
    end

    def correct_ghost
      @ghost = Ghost.find(params[:id])
      redirect_to(root_url) unless (current_user.id == @ghost.user_id)
    end

    def correct_destroyer
      redirect_to(root_url) unless current_user.admin?
    end

    def go_away
      redirect_to(root_url)
    end
end

Here are the relevant bits of my sessions_helper.rb file:

module SessionsHelper

  def sign_in(user)
    remember_token = User.new_remember_token
    cookies.permanent[:remember_token] = remember_token
    user.update_attribute(:remember_token, User.digest(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
    remember_token = User.digest(cookies[:remember_token])
    @current_user ||= User.find_by(remember_token: remember_token)
  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 redirect_back_or(default)
    redirect_to(session[:return_to] || default)
    session.delete(:return_to)
  end

  def store_location
    session[:return_to] = request.url if request.get?
  end

end

User class:

class User < ActiveRecord::Base

  has_one  :ghost,    dependent: :destroy

  before_create :create_remember_token
  before_save do
    email.downcase!
    callsign.downcase!
  end
  after_save do
    self.create_ghost unless ghost
  end

  validates :name, presence: true,
                   length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
  validates :email, presence:   true,
                    format:     { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  VALID_CALLSIGN_REGEX = /\A[a-z\d\-.\_]+\z/i
  validates :callsign, presence:   true,
                       length:     { maximum: 20 },
                       format:     { with: VALID_CALLSIGN_REGEX },
                       uniqueness: { case_sensitive: false }
  validates :password, length: { minimum: 6 }

  has_secure_password

  def User.new_remember_token
    SecureRandom.urlsafe_base64
  end

  def User.digest(token)
    Digest::SHA1.hexdigest(token.to_s)
  end

  private

    def create_remember_token
      self.remember_token = User.digest(User.new_remember_token)
    end

end

Fixed it. In the spec, added no_capybara: true, as follows:

before do
  sign_in user, no_capybara: true
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM