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"