I am following Lesson 9 for sign-in, yet the signin test just won't pass! I followed the code to the letter and it still wont pass.
when testing with the browser - the sign in works with no errors..
Failures:
1) SessionsController POST 'create' with valid email and password should sign the user in Failure/Error: controller.current_user.should == @user expected: # got: nil (using ==) # ./spec/controllers/sessions_controller_spec.rb:55:in `block (4 levels) in '
2) SessionsController POST 'create' with valid email and password should redirect to the user show page Failure/Error: response.should redirect_to(user_path(@user)) Expected block to return true value. # ./spec/controllers/sessions_controller_spec.rb:61:in `block (4 levels) in '
Finished in 5.12 seconds 7 examples, 2 failures
Failed examples:
rspec ./spec/controllers/sessions_controller_spec.rb:53 # SessionsController POST 'create' with valid email and password should sign the user in
rspec ./spec/controllers/sessions_controller_spec.rb:59 # SessionsController POST 'create' with valid email and password should redirect to the user show page
As you can see, the test controller.current_user.should == @user
returns nil for some reason.
Please help me understand this..
Thank you
SessionHelper
module SessionsHelper
def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
self.current_user= user
end
def signed_in?
!self.current_user.nil?
end
def current_user=(user)
@current_user = user
end
def current_user
@current_user ||= user_from_remember_token
end
private
def user_from_remember_token
User.authenticate_with_salt(*remember_token)
end
def remember_token
cookies.signed[:remember_token] || [nil, nil]
end
end
Session controller
class SessionsController < ApplicationController
def new
@title = "Sign In"
end
def create
user = User.authenticate(params[:session][:email], params[:session][:password])
if user.nil?
flash.now[:error] = "Invalid email/password"
@title = "Sign In (right this time)"
render 'new'
else
#sign in the user
sign_in @user
redirect_to user
end
end
def destroy
end
end
User Model
require 'digest'
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation
email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true,
:length => {:minimum => 2, :maximum => 50}
validates :email, :presence => true, :format => {:with => email_regex}, :uniqueness => {:case_sensitive => false }
#Automatically creates the virtual password confimration attribute
validates :password, :presence => true,
:confirmation => true,
:length => {:within => 6..40}
before_save :encrypt_password
def has_password?(submitted_password)
self.salt = make_salt if new_record?
encrypted_password == encrypt(submitted_password)
end
def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return nil if user.has_password?(submitted_password)
end
def self.authenticate_with_salt(id, cookie_salt)
user = find_by_id(id)
(user && user.salt == cookie_salt) ? user : nil
end
private
def encrypt_password
self.salt = make_salt unless has_password?(password)
self.encrypted_password = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
end
session controller spec
require 'spec_helper'
describe SessionsController do
render_views
describe "GET 'new'" do
it "should be successful" do
get 'new'
response.should be_success
end
it "should have the right title" do
get :new
response.should have_selector("title", :content => "Sign In")
end
end
describe "POST 'create'" do
describe "invalid login" do
before(:each) do
@attr = {:email => "[email protected]", :password => "invalid"}
end
it "should re-render the new page" do
post :create, :session => @attr
response.should render_template('new')
end
it "should have the right title" do
post :create, :session => @attr
response.should have_selector("title", :content => "Sign In (right this time)")
end
it "should have flash.now message" do
post :create, :session => @attr
flash.now[:error].should =~ /invalid/i
end
end
describe "success" do
before(:each) do
@user = Factory(:user)
@attr = { :email => @user.email, :password => @user.password }
end
it "should sign the user in" do
post :create, :session => @attr
controller.current_user.should == @user
controller.should be_signed_in
end
it "should redirect to the user show page" do
post :create, :session => @attr
response.should redirect_to(user_path(@user))
end
end
end
end