2012-03-31 5 views
4

私はTurorial「Ruby on Railsに 『マイケル・ハートルのを読んでいる』が、私はこだわっているhere RSpecのは - テストが失敗した場合でも(ログインしているユーザーをシミュレートする)アプリケーションの作品

は、私がテストを書きました。

  1. は、ユーザーがログインして、それがログインページ
  2. にリダイレクトのアクセス users#editまたは users#updateにしようとされていない場合:ユーザーの編集/更新時にユーザー認証をチェックするために、私はまた、働くコントローラのコードと を書いてきました
  3. ユーザーがロギングしている場合dと、彼は別のユーザーが、問題はポイント2をテスト仕様であるルート

にリダイレクトされて編集しようと、私はuser_pathにPUTリクエストを送信し、私はルートにリダイレクトさが、実行していることを確認してくださいRSpecの私は次のエラーを取得:

Failures: 

    1) Authentication authorization as wrong user submitting a PUT request to users#update 
    Failure/Error: specify { response.should 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> 
    # ./spec/requests/authentication_pages_spec.rb:73:in `block (5 levels) in <top (required)>' 

をユーザーが全く記録されていない場合のように、それは、代わりにroot_urlsignin_urlにリダイレクトされますようだ...これは私が問題原因を推測するものです。

アプリケーションは、ユーザーを認証するためにトークンをCookieに格納します。あなたは方法はputを用いた場合でも、ユーザーがログインしていることを確認するremember_tokenクッキーを設定見ることができるように

# spec/support/utilities.rb 
def sign_in(user) 
    visit signin_path 
    fill_in "Email", with: user.email 
    fill_in "Password", with: user.password 
    click_button "Sign in" 
    # Make signin work even when not using capybara (e.g. when using get, or post) 
    cookies[:remember_token] = user.remember_token 
end 

delete、この私はsignin_user(user)と呼ばれるヘルパーメソッドを書き、spec/support/utilities.rbファイルにそれを置くをテストする 等...または少なくともそれは動作する必要があります!

どうすればこの仕様を通過させることができますか?

# spec/requests/authentication_pages_spec.rb 
require 'spec_helper' 

describe "Authentication" do 
    subject { page } 

    # ... 

    describe "authorization" do 
    # ... 

    describe "as wrong user" do 
     let(:user) { FactoryGirl.create(:user) } 
     let(:another_user) { FactoryGirl.create(:user, email: "[email protected]") } 

     before { sign_in(user) } 

     # ... 

     describe "submitting a PUT request to users#update" do 
     before { put user_path(another_user) } 

     specify { response.should redirect_to(root_url) } 
     end 
    end 
    end 
end 

UPDATE:これは私のUsersController次のとおりです。

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 the sample App!" 
     redirect_to @user 
    else 
     render "new" 
    end 
    end 

    def edit 
    end 

    def update 
    if @user.update_attributes(params[:user]) 
     sign_in(@user) 
     flash[:success] = "Your profile was successfully updated" 
     redirect_to @user 
    else 
     render "edit" 
    end 
    end 

    private 
    def signed_in_user 
     unless signed_in? 
     redirect_to signin_url, notice: "Please sign in to access this page." 
     end 
    end 

    def correct_user 
     @user = User.find(params[:id]) 
     redirect_to root_url unless current_user?(@user) 
    end 
end 
+0

あなたはコントローラが動作すると言いましたが、とにかくユーザーコントローラのコードを投稿できますか? 'edit' *と' update'アクションの両方が、あなたの2番目のポイントの 'root_url'にリダイレクトされていますか? – pjumble

+0

@pjumble返信いただきありがとうございます。質問をUsersControllerのコードで更新していることを確認してください。私はブラウザでテストしました。 –

+0

@pjumbleあなたの質問には、wgetでPUTリクエストをする方法がわかりません。マニュアルページで検索しましたが、何も見つかりませんでした。 –

答えて

3

あなたのgithubのリポジトリ上のコードの残りの部分からヘルパーを見た後、私は問題を参照してくださいと思います。

あなたの:remember_tokenを格納するためsession変数を使用している:

# Make signin work even when not using capybara (e.g. when using get, or post) 
cookies[:remember_token] = user.remember_token 

しかし:

def user_from_remember_token 
    remember_token = cookies[:remember_token] 
    User.find_by_remember_token(remember_token) unless remember_token.nil? 
    end 

あなたのテストヘルパーがクッキーを設定します。

def user_from_remember_token 
    remember_token = session[:remember_token] 
    User.find_by_remember_token(remember_token) unless remember_token.nil? 
    end 

本はクッキーを使用していますあなたのuser_from_remember_tokenがを探しているからですはクッキーではなく、ユーザーがログインしていないと考えて、root_pathの代わりにlogin_pathにテストがリダイレクトされます。

彼らはここにクッキーを使用する理由は言う:http://ruby.railstutorial.org/chapters/sign-in-sign-out?version=3.2#sec:a_working_sign_in_method


セッションを引き続き使用したい場合は、post経由でサインインするテストを調整する必要がありますので、putはセッションが設定されている、ために例:

describe "submitting a PUT request to users#update" do 
    before do 
     post sessions_path, :email => user.email, :password => user.password 
     put user_path(another_user) 
    end 
    specify { response.should redirect_to(root_url) } 
    end 
+0

あなたは正しいです、私はクッキーの代わりにセッションを使用しました(下位レベルでは両方ともクッキーを使用します)が、これは昨日忘れました。ありがとう、私はあなたのヒントを使用してテストでユーザーを記録しようとしています(私はいくつかの問題を抱えていますが、すぐに解決することを願っています) –

+0

あなたが書いたとおりにsession_pathに直接POSTリクエストを提出しようとしました。私は同じ問題を抱えています。私は置き換えようとしました:session:parametersしかし結果は同じです、ユーザはログに記録されていないようです –

+2

私はついにこの問題を解決し、テストでもユーザログイン作業をしました:私は 'cookies [:remember_token] = '' post_path'、 ':email => user.email、:password => user.password'(' post'に直接渡したことに注意してください) –

1

ありがとうございました!私はこの本を通って働いていて、同じ問題を抱えています。セッションを使用する理由は、exercise 2 in section 8.5がクッキーの代わりにセッションを使用するためです。

私の答えは少し異なります。私SessionsControllerはのparamsにセッション変数を使用しています。

def create 
    user = User.find_by_email(params[:session][:email]) 
    if user && user.authenticate(params[:session][:password]) 
     sign_in user 
     redirect_back_or user 
    else 
     flash.now[:error] = 'Invalid email/password combination' 
     render 'new' 
    end 
    end 

をので、修正が少し複雑です:

#spec/support/utilities.rb 
def sign_in(user) 
    visit signin_path 
    fill_in "session_email", with: user.email 
    fill_in "session_password", with: user.password 
    click_button "Sign in" 
    # Sign in when not using Capybara as well. 
    post sessions_path, {:session => { :email => user.email, :password => user.password }} 
end 
+0

セッションのハイジャックを避けるためにこれをやったことがあります。実際には使用しませんが、私はこの小さな変更をしようとしました) –

0

私は同じ問題が、別の原因がありました。

私はスペック/サポート/ utilities.rbに

def sign_in(user) 
    visit signin_path 
    fill_in "Email", with: user.email 
    fill_in "Password", with: user.password 
    click_button "Sign in" 
    # Sign in when not using Capybara as well 
    cookies[:remember_toke] = user.remember_token 
end 

最後の行が言うことに注意してくださいタイプミスがあったどういうわけか、それはテストが失敗する原因

「:remember_toke」の代わりに「remember_tokenを」サインオンにリダイレクトされました。

他の誰かが同じタイプのミスを犯した場合に備えて、私はここにこれを記録しています。

+0

ありがとう、私は誰かがそれが将来、いつか役に立つと思うでしょう;) –

関連する問題