9.4 sign out

whew!!!, last chapter is a long one!

 

now, we are going to implement sign out.

 

1. no wonders, we will start from TDD.

 

 

describe "DELETE 'destroy'" do
	it "should sign a user out" do
		test_sign_in(Factory(:user))
		delete :destroy
		controller.should_not be_signed_in
		response.should redirect_to(root_path)
	end
end
 

now we define the test_sign_in method in the spec_helper.

 

RSpec.configure do |config|
  def test_sign_in(user)
    controller.sign_in(user) 
  end
end

 2. the destroy function in controller:

 

 

def destroy
  sign_out
  redirect_to root_path
end

 

3. the sign_out fuction in sessions_helper.rb

 

 

def sign_out
  cookies.delete(:remember_token)
  self.current_user = nil
end

 

4. sign in upon sign up.

 

let's first write a test to test that a signup user is auto signed in.

 

 

describe Usercontroller do
	describe "POST 'create'" do
		it "should sign the user in" do
			post :create, :user => @attr
			controller.should be_signed_in
		end
	end
end

 then we just need to add a line of code to the User models create method:

 

if @user.save
	sign_in @user
	flash[:success] = "Welcom....."
	redirect_to @user
else
	.....
end

 

5. next, we will change the layout links, so that after user signed in, the link text change to "sign out"

although what we want to change is views, we can still strat from TDD of integration test.

 

luckily, we already have Layout links integration test.

 

describe "Layout links" do
	describe "when not signed in" do
		it "should have a sign in link" do
			visit root_path
			response.should have_selector("a", :href => signin_path, :content => "Sign in")
		end
	end
	describe "when signed in" do
		before(:each) do
			@user = Factory(:user)
			visit signin_path
			fill_in :email, :with => @user.email
			.....
			click_button
		end
		it "should have a sign out link" do
			visit root_path
			reponse.should have_selector("a", :href => signout_path, :content => "Sign out")
		end
		it "should have a profile link" do
                    visit root_path
                    response.should have_selector("a", :href => user_path(@user), :content => "Profile")
                 end
end

 now it is time the change the layout header, to change the link according to signed in or not.

 

 

<% if signed_in? %>
<li><%= link_to "Sign out", signout_path, :method => :delete %></li>
<%else%>
<li><%= link_to "Sign in", signin_path%></li>
<%end%>

 

for the view, need to add the profile link:

link_to "Profile", current_user

 

you can see that rails allow to specify a object to stand for the url

 

 

6. now we can add a integration test for both sign in and sign out.

I'll put this test in to users_spec.rb integration test.

 

 

describe "sign in/out" do
	describe "failure" do
		it "should not sign a user in" do
			visit signin_path
			fill_in :email, :with =>""
			fill_in :password, :with => ""
			click_button
			response.should have_selector("div.flash.error", :content => "Invalid")
		end
	end
	describe "success" do
		it "should sign user in and out" do
			user = Factory(:user)
			visit signin_path
			fill_in :email, :wtih => user.email
			fill_in :password, :with => user.password
			click_button
			controller.should be_signed_in
			click_link "Sign out"
			controller.should_not be_signed_in
		end
	end
end

 

please take special attention to the code:

 

click_link "Sign out"

by this singly line of code, it actuall tested the route, the link text, the url, and the changing of the layout link, 

 

I like this test method very much!!

click_link "Sign out"

你可能感兴趣的:(sign)