Reputation: 1647
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: "[email protected]") }
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: "[email protected]"
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", "[email protected]"], ["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!
Upvotes: 0
Views: 1473
Reputation: 29439
Based on the output from your test, your signed_in_user
filter is causing a redirect, indicating that the login has failed. I'd suggest tracing the login execution through your controller code and/or sharing the relevant code here for review.
Update: As a follow-up to the comment thread, the Hartl tutorial has been used and verified by thousands of users, while there are occasional defects as Michael upgrades to accommodate new versions, in general, it is quite accurate and you'll be ok if you follow it carefully. One thing you cannot do is to mix and match software from various versions of the tutorial.
Upvotes: 1