I'm having trouble debugging my Rspec code for the Rails Tutorial. When I run my rspec code, I get this error:
1) Authentication authorization as non-admin user submitting a DELETE request to the Users#destroy action
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".
# ./spec/requests/authentication_pages_spec.rb:106:in `block (5 levels) in <top (required)>'
2) Authentication authorization as wrong user submitting a GET request to the Users#edit action
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".
# ./spec/requests/authentication_pages_spec.rb:90:in `block (5 levels) in <top (required)>'
3) Authentication authorization as wrong user submitting a PATCH request to the Users#update action
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".
# ./spec/requests/authentication_pages_spec.rb:95:in `block (5 levels) in <top (required)>'
The code for my /spec/requests/authentication_pages_spec.rb is:
require 'spec_helper'
describe "Authentication" do
subject { page }
describe "signin page" do
before { visit signin_path }
it { should have_content('Sign in') }
it { should have_title('Sign in') }
end
describe "signin" do
before { visit signin_path }
describe "with invalid information" do
before { click_button "Sign in" }
it { should have_title('Sign in') }
it { should have_error_message('Invalid') }
describe "after visiting another page" do
before { click_link "Home" }
it { should_not have_error_message('Invalid') }
end
end
describe "with valid information" do
let(:user) { FactoryGirl.create(:user) }
before { sign_in user }
it { should have_title(user.name) }
it { should have_link('Users', href: users_path) }
it { should have_link('Profile', href: user_path(user)) }
it { should have_link('Settings', href: edit_user_path(user)) }
it { should have_link('Sign out', href: signout_path) }
it { should_not have_link('Sign in', href: signin_path) }
describe "followed by signout" do
before { click_link "Sign out" }
it { should have_link('Sign in') }
end
end
end
describe "authorization" do
describe "for non-signed-in users" do
let(:user) { FactoryGirl.create(:user) }
describe "when attempting to visit a protected page" do
before do
visit edit_user_path(user)
valid_signin(user)
end
describe "after signing in" do
it "should render the desired protected page" do
expect(page).to have_title('Edit user')
end
end
end
describe "in the Users controller" do
describe "visiting the edit page" do
before { visit edit_user_path(user) }
it { should have_title('Sign in') }
end
describe "submitting to the update action" do
before { patch user_path(user) }
specify { expect(response).to redirect_to(signin_path) }
end
describe "visiting the user index" do
before { visit users_path }
it { should have_title('Sign in') }
end
end
end
describe "as wrong user" do
let(:user) { FactoryGirl.create(:user) }
let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
before { sign_in user, no_capybara: true }
describe "submitting a GET request to the Users#edit action" do
before { get edit_user_path(wrong_user) }
specify { expect(response.body).not_to match(full_title('Edit user')) }
specify { expect(response).to redirect_to(root_url) }
end
describe "submitting a PATCH request to the Users#update action" do
before { patch user_path(wrong_user) }
specify { expect(response).to redirect_to(root_url) }
end
end
describe "as non-admin user" do
let(:user) { FactoryGirl.create(:user) }
let(:non_admin) { FactoryGirl.create(:user) }
before { sign_in non_admin, no_capybara: true }
describe "submitting a DELETE request to the Users#destroy action" do
before { delete user_path(user) }
specify { expect(response).to redirect_to(root_url) }
end
end
end
end
And the code for my utilities.rb is:
include ApplicationHelper
def valid_signin(user)
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
def sign_in(user, options={})
if options[:no_capybara]
# Sign in when not using Capybara.
remember_token = User.new_remember_token
cookies[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
else
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
end
def valid_user()
fill_in "Name", with: "Example User"
fill_in "Email", with: "user@example.com"
fill_in "Password", with: "foobar"
fill_in "Confirmation", with: "foobar"
end
RSpec::Matchers.define :have_error_message do |message|
match do |page|
expect(page).to have_selector('div.alert.alert-error', text: message)
end
end
When I run the rails server, everything works perfectly.
The interesting thing is that my logs are different between when I run it on my server and when I run the actual tests. On the server, logged in as user id 2, I get this:
Started GET "/users/1/edit" for 127.0.0.1 at 2013-12-31 21:28:31 -0800
Processing by UsersController#edit as HTML
Parameters: {"id"=>"1"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 2]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", "1"]]
Redirected to http://localhost:3000/
Filter chain halted as :correct_user rendered or redirected
Completed 302 Found in 4ms (ActiveRecord: 0.2ms)
In my test.log file, I see this:
Binary data inserted for `string` type on column `password_digest`
[1m[35mSQL (0.4ms)[0m INSERT INTO "users" ("created_at", "email", "name", "password_digest", "remember_token", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["created_at", Sat, 28 Dec 2013 18:50:19 UTC +00:00], ["email", "michael@example.com"], ["name", "Michael Hartl"], ["password_digest", "$2a$04$qTOUv775ioIiAdufscqASuTZBoJEafqvDzc/.FGqmFR30NzQPalLa"], ["remember_token", "698696f7cfbefa641e2b87450b57499b056932ff"], ["updated_at", Sat, 28 Dec 2013 18:50:19 UTC +00:00]]
[1m[36m (0.0ms)[0m [1mRELEASE SAVEPOINT active_record_1[0m
Started GET "/users/1/edit" for 127.0.0.1 at 2013-12-28 10:50:19 -0800
Processing by UsersController#edit as HTML
Parameters: {"id"=>"1"}
Redirected to http://www.example.com/signin
Filter chain halted as :signed_in_user rendered or redirected
Completed 302 Found in 1ms (ActiveRecord: 0.0ms)
Edit1: And here is my signed_in_user
code:
private
def user_params
params.require(:user).permit(:admin, :name, :email, :password, :password_confirmation)
end
# Before filters
def signed_in_user
debugger
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def correct_user
@user = User.find(params[:id])
redirect_to root_path unless current_user?(@user)
end
def admin_user
redirect_to root_path unless current_user.admin?
end
def strict_signed_in_user
redirect_to root_url, notice: "You are already signed in." unless !signed_in?
end
Edit2: Using debugger
I've managed to find a few errors like this:
F/Users/rasheedbustamam/Rails projects/sample_app/spec/support/utilities.rb:11
if options[:no_capybara]
[6, 15] in /Users/rasheedbustamam/Rails projects/sample_app/spec/support/utilities.rb
6 click_button "Sign in"
7 end
8
9 def sign_in(user, options={})
10 debugger
=> 11 if options[:no_capybara]
12 # Sign in when not using Capybara.
13 remember_token = User.new_remember_token
14 cookies[:remember_token] = remember_token
15 user.update_attribute(:remember_token, User.encrypt(remember_token))
(rdb:1) v l
self = #<RSpec::Core::ExampleGroup::Nested_1::Nested_3::Nested_2::Nested_2:0x00000109aeb1b8>
options = {:no_capybara=>true}
remember_token = nil
user = #<User:0x00000109af02f8>
Of note is the fact that remember_token
is nil
which seems like it's a problem.
Thanks so much in advance!