enter the code here. I am trying to finish Michael Hartl Ruby on Rails v3.2. The tutorial, and I'm stuck on Chapter 9.2.2 .
The following is the error message I get, even if after completing this section all my tests should pass:
sample_app mikael$ bundle exec rspec spec/ .................................................................F.. Failures: 1) User pages edit with valid information Failure/Error: it { should have_link('Sign out', :href => signout_path) } expected link "Sign out" to return something
The problem is that after a signed user successfully updates their profile, they automatically log out of the system, which leads to a failure of editing with a reliable information test, because after the update the user must remain in the system and the Exit link must exist.
I combed it, trying to find my mistake, or where I did not follow the textbook correctly, but I can not find a solution.
I can get all my tests to go through before completing section 9.2.2.
Here are the files that I updated in chapter 9 (includes section 9.2.2 and all previous sections):
<strong> specifications / requests / authentication_pages_spec.rb
require 'spec_helper' describe "Authentication" do subject { page } describe "signin page" do before { visit signin_path } it { should have_selector('h1', text: 'Sign in') } it { should have_selector('title', text: 'Sign in') } end describe "signin" do before { visit signin_path } describe "with invalid information" do before { click_button "Sign in" } it { should have_selector('title', text: 'Sign in') } it { should have_selector('div.flash.error', text: 'Invalid') } describe "after visiting another page" do before { click_link "Home" } it { should_not have_selector('div.flash.error') } end end describe "with valid information" do let(:user) { FactoryGirl.create(:user) } before do fill_in "Email", with: user.email fill_in "Password", with: user.password click_button "Sign in" end it { should have_selector('title', text: user.name) } 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) { Factory(:user) } describe "in the Users controller" do describe "visiting the edit page" do before { visit edit_user_path(user) } it { should have_selector('title', text: 'Sign in') } end describe "submitting to the update action" do before { put user_path(user) } specify { response.should redirect_to(signin_path) } 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 } describe "visiting Users#edit page" do before { visit edit_user_path(wrong_user) } it { should have_selector('title', text: 'Home') } end describe "submitting a PUT request to the Users#update action" do before { put user_path(wrong_user) } specify { response.should redirect_to(root_path) } end end end end
<strong> specifications / queries / user_pages_spec.rb
require 'spec_helper' describe "User pages" do subject { page } describe "profile page" do let(:user) { FactoryGirl.create(:user) } before { visit user_path(user) } it { should have_selector('h1', text: user.name) } it { should have_selector('title', text: user.name) } end describe "signup" do before { visit signup_path } describe "with invalid information" do it "should not create a user" do expect { click_button "Sign up" }.not_to change(User, :count) end end describe "error messages" do before { click_button "Sign up" } let(:error) { 'errors prohibited this user from being saved' } it { should have_selector('title', text: 'Sign up') } it { should have_content(error) } end describe "with valid information" do before do fill_in "Name", with: "Example User" fill_in "Email", with: " user@example.com " fill_in "Password", with: "foobar" fill_in "Confirmation", with: "foobar" end describe "after saving the user" do before { click_button "Sign up" } let(:user) { User.find_by_email(' user@example.com ') } it { should have_selector('title', text: user.name) } it { should have_selector('div.flash.success', text: 'Welcome') } it { should have_link('Sign out') } end it "should create a user" do expect { click_button "Sign up" }.to change(User, :count).by(1) end end end describe "edit" do let(:user) { FactoryGirl.create(:user) } before do sign_in user visit edit_user_path(user) end describe "page" do it { should have_selector('h1', text: "Edit user") } it { should have_selector('title', text: "Edit user") } it { should have_link('change', href: 'http://gravatar.com/emails') } end describe "with invalid information" do let(:error) { '1 error prohibited this user from being saved' } before { click_button "Update" } it { should have_content(error) } end describe "with valid information" do let(:user) { FactoryGirl.create(:user) } let(:new_name) { "New Name" } let(:new_email) { " new@example.com " } before do fill_in "Name", with: new_name fill_in "Email", with: new_email fill_in "Password", with: user.password fill_in "Confirmation", with: user.password click_button "Update" end it { should have_selector('title', text: new_name) } it { should have_selector('div.flash.success') } it { should have_link('Sign out', :href => signout_path) } specify { user.reload.name.should == new_name } specify { user.reload.email.should == new_email } end end end
application / controllers / users_controller.rb
class UsersController < ApplicationController before_filter :signed_in_user, only: [:edit, :update] before_filter :correct_user, only: [:edit, :update] def show @user = User.find(params[:id]) end def new @user = User.new end def create @user = User.new(params[:user]) if @user.save sign_in @user flash[:success] = "Welcome to MK Rails!" redirect_to @user else render 'new' end end def edit end def update if @user.update_attributes(params[:user]) flash[:success] = "Profile updated" redirect_to @user else render 'edit' end end private def signed_in_user redirect_to signin_path, notice: "Please sign in." unless signed_in? end def correct_user @user = User.find(params[:id]) redirect_to(root_path) unless current_user?(@user) end end
application / helpers / sessions_helper.rb
module SessionsHelper def sign_in(user) cookies.permanent[:remember_token] = user.remember_token current_user = user end def signed_in? !current_user.nil? end def current_user=(user) @current_user = user end def current_user @current_user ||= user_from_remember_token end def current_user?(user) user == current_user end def sign_out cookies.delete(:remember_token) end private def user_from_remember_token remember_token = cookies[:remember_token] User.find_by_remember_token(remember_token) unless remember_token.nil? end end
specifications / support / utilities.rb
def full_title(page_title) base_title = "MK Rails" if page_title.empty? base_title else "#{base_title} | #{page_title}" end end def valid_signin(user) fill_in "Email", with: user.email fill_in "Password", with: user.password click_button "Sign in" end RSpec::Matchers.define :have_error_message do |message| match do |page| page.should have_selector('div.flash.error', text: message) end end def sign_in(user) visit signin_path fill_in "Email", with: user.email fill_in "Password", with: user.password click_button "Sign in"
Any help in understanding the problem is greatly appreciated!