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

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

####2番目のウィンドウでユーザーをログアウトするテスト
test/integration/users_login_test.rb

```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

```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

```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

```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で修正した行をコメントアウトし、２つのログイン済みのタブによるバグを実際に確かめてみましょう。まず片方のタブでログアウトし、その後、もう１つのタブで再度ログアウトを試してみてください。

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

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

できなかった。

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```
記憶ダイジェストが空になっていない。

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