2016-03-15 83 views
1

我有這樣的代碼來驗證頻道的訂閱者:使用cookies.signed [:USER_ID]在水豚測試

​​

,一切工作正常。問題出在功能測試中。 當我運行這個測試:

require 'rails_helper' 

feature 'Chat room' do 
    scenario "send one message" do 
    user = create(:user) 
    login_as(user, :scope => :user) 

    expect { 
     fill_in 'message', with: 'hello friend' 
     click_button 'Send' 
     byebug 
    }.to change(Message, :count).by(1) 
    expect(current_path).to eq root_path 
    expect(page).to have_content 'hello friend' 
    end 
end 

測試日誌,說,「未經授權的連接嘗試被拒絕」。由於cookie爲空,因此無法進行身份驗證。

那麼如何在水豚測試中設置cookie?

我試過這樣做cookies.signed[:user_id] = user.id在測試中,但它不起作用。

如何在測試中設置像這樣的餅乾cookies.signed[:user_id] = user.id

+0

你是什麼login_as'的'界定,而/你什麼時候實際訪問的網頁的工作? –

回答

0

您還應該將用戶標識存儲在會話中 - 而不是存儲在cookie本身*中。該cookie應該只包含一個會話標識符。

而且你應該把你的驗證邏輯收集到一個地方,這樣它就不會在你的控制器中被複制。

module AuthenticationHelper 
    def current_user 
    @current_user || = User.find_by(session[:user_id]) 
    end 

    def signed_in? 
    current_user.is_a?(User) 
    end 

    def sign_in(user) 
    reset_session # prevents session fixation 
    @current_user = user 
    session[:user_id] = user.id 
    end 

    def sign_out 
    reset_session 
    @current_user = nil 
    end 

    def authorize! 
    raise AuthenticationError unless current_user 
    end 
end 

這應該是在你的應用程序的唯一的地方它知道用戶是如何在會議上連載。更好的辦法是使用Warden而不是重新發明輪子。

當測試控制器和視圖,你可以簡單的存根current_user方法 - 然而,對於功能規格,你實際上應該通過實際登錄的步驟向用戶發送:

def sign_user_in(user) 
    visit new_session_path 
    fill_in 'Email', with: user.email 
    fill_in 'Password', with: user.password 
    click_button 'Log in' 
end 

這可以確保您的驗收測試實際上覆蓋系統,並避免將任何底層系統知識納入您的測試。然而,渲染登錄頁面會導致性能損失,這會大大降低測試套件的速度。

作爲一種變通方法,您可以直接發送POST請求:

def sign_user_in_directly(user) 
    page.driver.post(sessions_path, { 
    params: { 
     email: user.email, 
     password: user.password 
    } 
    }) 
end 

注意,這取決於驅動程序 - 一些javascript驅動程序可能支持或不支持這一點。

+0

* Rails中的默認會話存儲是* cookie存儲* - 但您仍然應該使用會話機制,因爲它可以幫助您防止會話固定和基於cookie的攻擊。 http://guides.rubyonrails.org/security.html#session-hijacking – max

0

假設你打電話的login_as是來自Warden測試助手,它的功能是設置好的,以便下一個請求在響應中設置會話cookie。因此,您可能需要在致電login_as後訪問一個頁面。此外,由於單擊「發送」是異步的,因此在檢查Message.count已更改之前,需要等待某些內容發生更改,如果您想要非片狀測試,那麼您實際上不應該使用帶有current_path的.eq。因此,所有的組合像

#don't visit the page where you can fill in the message before calling login_as 


scenario "send one message" do 
    user = create(:user) 
    login_as(user, :scope => :user) 
    visit 'the path to the page where you can fill in a message' 
    expect { 
    fill_in 'message', with: 'hello friend' 
    click_button 'Send' 
    expect(page).to have_css('#messages', text:'hello friend') # adjust selector depending on where the message is supposed to appear 
    expect(page).to have_current_path(root_path) 
    }.to change(Message, :count).by(1) 
end 

應該爲你