質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Cookie

HTTPにおけるCookieとは、クライアントのウェブブラウザ上に保存された一時的なデータを指します。クライアント側のJavaScriptでも、サーバー側のHTTPヘッダーでもクッキーの読み書き・修正・削除が可能です。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

1358閲覧

ブラウザ上の動作は正常であるが、rspecのテストが通らない

Harluz

総合スコア19

Cookie

HTTPにおけるCookieとは、クライアントのウェブブラウザ上に保存された一時的なデータを指します。クライアント側のJavaScriptでも、サーバー側のHTTPヘッダーでもクッキーの読み書き・修正・削除が可能です。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2020/12/06 01:25

rails tutorialの9章を参考にログイン機構を作成。
テストについては、rspecを使用しているが、テストが通らない

newHTML

1<div class="row"> 2 <div class="col-md-6 col-md-offset-3"> 3 <%= form_with(url: login_path, scope: :session, local: true) do |f| %> 4 5 <%= f.label :email %> 6 <%= f.email_field :email, class: 'form-control' %> 7 8 <%= f.label :password %> 9 <%= f.password_field :password, class: 'form-control' %> 10 11 <%= f.label :remember_me, class: "checkbox inline" do %> 12 <%= f.check_box :remember_me %> 13 <span>Remember me on this computer</span> 14 <% end %> 15 16 <%= f.submit "Log in", class: "btn btn-primary" %> 17 <% end %> 18 19 <p>New user? <%= link_to "Sign up now!", signup_path %></p> 20 </div> 21</div>

ログインにおいて、emailとpasswordを入力する。
remember_meのチェックボックスがあり、「0」か「1」の情報をsessionに格納する。

SessionsController

1class SessionsController < ApplicationController 2 3 def new; end 4 5 def create 6 @user = User.find_by(email: params[:session][:email].downcase) 7 if @user&.authenticate(params[:session][:password]) 8 log_in @user 9 params[:session][:remember_me] == '1' ? remember(@user) : forget(@user) 10 redirect_to @user 11 else 12 flash.now[:danger] = 'Invalid email / password combination' 13 render 'new' 14 end 15 end 16end 17
params[:session][:remember_me] == '1' ? remember(@user) : forget(@user)

チェックをつけた場合、session[:remember_me]には’1’が格納されている。
'1'の場合、 remember(@user)が発火する。

SessionsHelper

1 def remember(user) 2 user.remember #userにremember_digestにハッシュ化したremember_tokenを格納するメソッド 3 cookies.permanent.signed[:user_id] = user.id 4 cookies.permanent[:remember_token] = user.remember_token 5 end

この処理によりcookieにuser_idとremember_tokenが保存される。
rememberメソッドの中身については、下記コードの通り

Userrb

1class User < ApplicationRecord 2 # 仮想的なremember_token属性を追加 3 attr_accessor :remember_token 4 5 # 渡された文字列のハッシュ値を返す 6 def self.digest(string) 7 cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : 8 BCrypt::Engine.cost 9 BCrypt::Password.create(string, cost: cost) 10 end 11 12 # ランダムな文字列でトークンを返す 13 def self.new_token 14 SecureRandom.urlsafe_base64 15 end 16 17 # 永続セッションのためにユーザーをデータベースに記憶する 18 def remember 19 self.remember_token = User.new_token 20 update_attribute(:remember_digest, User.digest(remember_token)) 21 end 22end

以上の前提より、rspecにて
「remember_meが’1’である時、cookieのremember_tokenはnilではない」
というテストを下記の通り実装

TestHelper

1include ApplicationHelper 2 3module TestHelper 4 # ログインする情報を渡すメソッド 5 def log_in_as(user, remember_me: '1') 6 post login_path, params: { session: { 7 email: user.email, 8 password: user.password, 9 remember_me: remember_me 10 } } 11 end 12end

SessionsRequestSpec

1let(:user) { FactoryBot.create(:user) } 2it 'Apply remember_me' do 3 log_in_as(user) 4 expect(response.cookies['remember_token']).not_to eq nil 5end

とした際にテストログは下記画像の通りとなっており、remember_tokenはnilになっている状況らしい
イメージ説明

問題の仮説
1私のロジックが間違えている
2タイポの可能性
3rspecがcookieの情報をテストできていない可能性
4rspec内でのメソッドの呼び出すタイミングがずれている(letなど)

何か手がかりでも良いので回答をいただけると助かります。
ほか、参照したいデータがありましたらその都度対応いたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

別で立ち上げていた問題を解決した際にこちらも解決しました。
https://teratail.com/questions/312871

おそらくは、sessionの値をrspecを実行した際に取得できなかったことが原因と思います。
他にはテストの実行環境が間違えていないか確認する必要がありました。

投稿2021/01/02 02:17

Harluz

総合スコア19

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問