LoginSignup
0
0

More than 1 year has passed since last update.

railsチュートリアル第九章 二つの目立たないバグ

Posted at

二つの目立たないバグ

ユーザーがログイン中の場合にのみログアウトさせる必要がある。
、ユーザーが複数のブラウザ(FirefoxやChromeなど)でログインしていたときに起こります

2番目のウィンドウでユーザーをログアウトするテスト

test/integration/users_login_test.rb

require 'test_helper'

class UsersLoginTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
    # ハッシュで呼び出す。
    # なんでもハッシュで呼び出せるようになるのか?
  end
.
.
. 
  test "login with valid information followed by logout" do
    get login_path
    # ログイン画面にいく
    post login_path, params: { session: { email:    @user.email,
                                          password: 'password' } }
    # データをデータベースに投稿
    assert is_logged_in?
    # ログインされているよね?
    assert_redirected_to @user
    # ユーザー情報を取り出すのか?
    follow_redirect!
    # もう一回確認
    assert_template 'users/show'
    # ユーザーページに移動する
    assert_select "a[href=?]", login_path, count: 0
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
    delete logout_path
    assert_not is_logged_in?
    assert_redirected_to root_url
    # 2番目のウィンドウでログアウトをクリックするユーザーをシミュレートする
    delete logout_path
    follow_redirect!
    assert_select "a[href=?]", login_path
    # これは表示する
    assert_select "a[href=?]", logout_path,      count: 0
    assert_select "a[href=?]", user_path(@user), count: 0
    # 上2行は非表示になっていることを確認。
  end
end

delete logout_pathを書くことによって二度目のログアウトを試すことができることがわかった。

テスト
ubuntu:~/environment/sample_app (advanced-login) $ rails t
Running via Spring preloader in process 8268
Started with run options --seed 30959

ERROR["test_login_with_valid_information_followed_by_logout", #<Minitest::Reporters::Suite:0x0000555ef3ce2c08 @name="UsersLoginTest">, 5.425516088000222]
 test_login_with_valid_information_followed_by_logout#UsersLoginTest (5.43s)
NoMethodError:         NoMethodError: undefined method `forget' for nil:NilClass
            app/helpers/sessions_helper.rb:58:in `forget'
            app/helpers/sessions_helper.rb:67:in `log_out'
            app/controllers/sessions_controller.rb:32:in `destroy'
            test/integration/users_login_test.rb:44:in `block in <class:UsersLoginTest>'

  24/24: [============================] 100% Time: 00:00:05, Time: 00:00:05

Finished in 5.96672s
24 tests, 58 assertions, 0 failures, 1 errors, 0 skips

NoMethodError: undefined method `forget' for nil:NilClass
NoMethodError:
「メソッドがない」という意味
undefined method `forget' for nil:NilClass
nilクラスになっているためforgetメソッドが見つからないのかな?

ログイン中の場合のみログアウトする

app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
.
.
.
  def destroy
  # ユーザー削除
    log_out if logged_in?
    # log_outメソッドを発動 もしログインされてたら
    redirect_to root_url
    # ホーム画面に戻る
  end
end
テスト
ubuntu:~/environment/sample_app (advanced-login) $ rails t
Running via Spring preloader in process 4083
Started with run options --seed 36998

  24/24: [============================] 100% Time: 00:00:03, Time: 00:00:03

Finished in 3.43251s
24 tests, 61 assertions, 0 failures, 0 errors, 0 skips

上のコードで条件をつけることによってログアウトできるようにしたみたい。

ダイジェストが存在しない場合のauthenticated?のテスト

test/models/user_test.rb

require 'test_helper'

class UserTest < ActiveSupport::TestCase
.
.
.
  test "authenticated? should return false for a user with nil digest" do
    assert_not @user.authenticated?('')
    # 記憶ダイジェストはからじゃないよね?
  end
end
テスト
ubuntu:~/environment/sample_app (advanced-login) $ rails t
Running via Spring preloader in process 4630
Started with run options --seed 26378

ERROR["test_authenticated?_should_return_false_for_a_user_with_nil_digest", #<Minitest::Reporters::Suite:0x00007fd9c14daa60 @name="UserTest">, 2.703540293999822]
 test_authenticated?_should_return_false_for_a_user_with_nil_digest#UserTest (2.70s)
BCrypt::Errors::InvalidHash:         BCrypt::Errors::InvalidHash: invalid hash
            app/models/user.rb:49:in `new'
            app/models/user.rb:49:in `authenticated?'
            test/models/user_test.rb:88:in `block in <class:UserTest>'

  25/25: [============================] 100% Time: 00:00:03, Time: 00:00:03

Finished in 3.43387s
25 tests, 61 assertions, 0 failures, 1 errors, 0 skips

BCrypt::Errors::InvalidHash: BCrypt::Errors::InvalidHash: invalid hash
無効なハッシュがあるからエラーになるのかな?

authenticated?を更新して、ダイジェストが存在しない場合に対応

app/models/user.rb

class User < ApplicationRecord
.
.
.
  # 渡されたトークンがダイジェストと一致したらtrueを返す
  def authenticated?(remember_token)
    return false if remember_digest.nil?
    # 記憶ダイジェストが空の場合 falseを返すことができる
    BCrypt::Password.new(remember_digest).is_password?(remember_token)
    # remember_tokenとremamber_digestを比較するもの
    # bycryptで暗号化
    # .is_password?で==の働きをする

  end

   # ユーザーのログイン情報を破棄する
  def forget
  # ユーザーがログアウトできるようにするため
    update_attribute(:remember_digest, nil)
    # .forgetで.rememberが取り消される
    # nilに更新される
  end
end
テスト
ubuntu:~/environment/sample_app (advanced-login) $ rails t
Running via Spring preloader in process 4973
Started with run options --seed 52742

  25/25: [============================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.38406s
25 tests, 62 assertions, 0 failures, 0 errors, 0 skips

演習

1.
リスト 9.16で修正した行をコメントアウトし、2つのログイン済みのタブによるバグを実際に確かめてみましょう。まず片方のタブでログアウトし、その後、もう1つのタブで再度ログアウトを試してみてください。

コメントアウト後accountが消えなかった。 修正後消えた。

2.
リスト 9.19で修正した行をコメントアウトし、2つのログイン済みのブラウザによるバグを実際に確かめてみましょう。まず片方のブラウザでログアウトし、もう一方のブラウザを再起動してサンプルアプリケーションにアクセスしてみてください。

できなかった。

3.
上のコードでコメントアウトした部分を元に戻し、テストスイートが red から green になることを確認しましょう。

buntu:~/environment/sample_app (advanced-login) $ rails t
Running via Spring preloader in process 8142
Started with run options --seed 10285

ERROR["test_authenticated?_should_return_false_for_a_user_with_nil_digest", #<Minitest::Reporters::Suite:0x000055d781f9bba0 @name="UserTest">, 5.757596166999974]
 test_authenticated?_should_return_false_for_a_user_with_nil_digest#UserTest (5.76s)
BCrypt::Errors::InvalidHash:         BCrypt::Errors::InvalidHash: invalid hash
            app/models/user.rb:51:in `new'
            app/models/user.rb:51:in `authenticated?'
            test/models/user_test.rb:88:in `block in <class:UserTest>'

 FAIL["test_login_with_valid_information_followed_by_logout", #<Minitest::Reporters::Suite:0x000055d781e67db0 @name="UsersLoginTest">, 6.913151000999733]
 test_login_with_valid_information_followed_by_logout#UsersLoginTest (6.91s)
        Expected true to be nil or false
        test/integration/users_login_test.rb:41:in `block in <class:UsersLoginTest>'

  25/25: [============================] 100% Time: 00:00:07, Time: 00:00:07

Finished in 7.02619s
25 tests, 57 assertions, 1 failures, 1 errors, 0 skips

BCrypt::Errors::InvalidHash: BCrypt::Errors::InvalidHash: invalid hash
ダイジェストが無効になっているためかな?
Expected true to be nil or false
記憶ダイジェストが空になっていない。

多分ブラウザが違うとログイン状態になったままなのかな?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0