railsチュートリアル第八章 レイアウト変更をテストする

###レイアウト変更をテストする
####fixture向けのdigestメソッドを追加する
app/models/user.rb

```rb
class User < ApplicationRecord
  before_save { email.downcase! }
  # データベースに保存する前に処理をする。
  # 入力されたメールアドレスを小文字にする。
  validates :name,  presence: true, length: { maximum: 50 }
  #属性はname,属性の存在を検証、 最大50字まで
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
  #最大255字まで
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
                    #???
  has_secure_password
  #セキュアなパスワードの実装
  validates :password, presence: true, length: { minimum: 5 }
  # パスワードのバリデーションの設定
  # 最低は六文字
  
  def User.digest(string)
  # 渡された文字列のハッシュ値を返す
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
   
    BCrypt::Password.create(string, cost: cost)
    # fixture用のパスワードを作成します
    # stringはハッシュ化する文字列
    # costはコストパラメータと呼ばれる値
    # ハッシュを算出するための計算コストを指定
  end
end
```
digestメソッドができたので、有効なユーザーを表すfixtureを作成

####ユーザーログインのテストで使うfixture
test/fixtures/users.yml

```yml
michael:
  name: Michael Example
  email: michael@example.com
  password_digest: <%= User.digest('password') %>
```
テストユーザー用の有効なパスワードを作成

```
<%= User.digest('password') %>
```
password属性を追加すると、そのようなカラムはデータベースに存在しないというエラーが発生する。

####有効な情報を使ってユーザーログインをテストする
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" do
    get login_path
    post login_path, params: { session: { email:    @user.email,
                                          password: 'password' } }
    assert_redirected_to @user
    # リダイレクト先が正しいかどうかをチェック
    follow_redirect!
    # そのページに実際に移動
    # ログインパスのリンクがページにないかどうかで判定
    assert_template 'users/show'
    assert_select "a[href=?]", login_path, count: 0
    # 一回も名前付きルートのloginにいかないことを確認?
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
  end
end
```
テスト

```
ubuntu:~/environment/sample_app (basic-login) $ rails test test/integration/users_login_test.rb
Running via Spring preloader in process 4542
Started with run options --seed 26059

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

Finished in 3.30648s
1 tests, 6 assertions, 0 failures, 0 errors, 0 skips
```

###演習
1.
リスト 8.15の8行目にあるif userから後ろをすべてコメントアウトすると、ユーザー名とパスワードを入力して認証しなくてもテストが通ってしまうことを確認しましょう（リスト 8.26）。通ってしまう理由は、リスト 8.9では「メールアドレスは正しいがパスワードが誤っている」ケースをテストしていないからです。このテストがないのは重大な手抜かりですので、テストスイートで正しいメールアドレスをUsersのログインテストに追加して、この手抜かりを修正してください（リスト 8.27）。テストが red （失敗）することを確認し、それから先ほどの8行目以降のコメントアウトを元に戻すと green （パス）することを確認してください（この演習の修正は重要なので、この先の 8.3のメインのコードにも修正を反映してあります）。

```rb
 def create
    user = User.find_by(email: params[:session][:email].downcase)
    # 送信されたメアドを使ってデータベースから取り出す。
    #emailを小文字にする
    if user # && user.authenticate(params[:session][:password])
    # user  取得したユーザーが有効かどうか？
    # その後にデータベース上にパスワードがあるか？
    # ユーザーログイン後にユーザー情報のページにリダイレクトする
      log_in user
      # ユーザーのブラウザ内の一時cookiesに暗号化済みのユーザーIDが自動で作成
      redirect_to user
      # 名前付きルート/userのビューを表示する
    else
      flash.now[:danger] = 'Invalid email/password combination'
      # flash.nowでリクエストが発生後メッセージを消滅する
      # エラーメッセージを作成する
        render 'new'
        # newアクションのビューを表示
    end
  end
```

```
ubuntu:~/environment/sample_app (basic-login) $ rails t
Running via Spring preloader in process 5829
Started with run options --seed 62915

  23/23: [============================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.98344s
23 tests, 50 assertions, 0 failures, 0 errors, 0 skips
```
確認されないからかな？

```rb
require 'test_helper'

class UsersLoginTest < ActionDispatch::IntegrationTest
  
  def setup
    @user = users(:michael)
    # ハッシュで呼び出す。
    # なんでもハッシュで呼び出せるようになるのか？
  end
  
  test "login with valid email/invalid password" do
    get login_path
    assert_template 'sessions/new'
    post login_path, params: { session: { email:    @user.email,
                                          password: "invalid" } }
    assert_template 'sessions/new'
    assert_not flash.empty?
    get root_path
    assert flash.empty?
  end
  
  test "login with valid information" do
    get login_path
    post login_path, params: { session: { email:    @user.email,
                                          password: 'password' } }
    assert_redirected_to @user
    # リダイレクト先が正しいかどうかをチェック
    follow_redirect!
    # そのページに実際に移動
    # ログインパスのリンクがページにないかどうかで判定
    assert_template 'users/show'
    assert_select "a[href=?]", login_path, count: 0
    # 一回も名前付きルートのloginにいかないことを確認?
    assert_select "a[href=?]", logout_path
    assert_select "a[href=?]", user_path(@user)
  end
end
```

```
ubuntu:~/environment/sample_app (basic-login) $ rails t
Running via Spring preloader in process 9430
Started with run options --seed 54106

 FAIL["test_login_with_valid_email/invalid_password", #<Minitest::Reporters::Suite:0x0000562f229a1aa8 @name="UsersLoginTest">, 1.4162409589998788]
 test_login_with_valid_email/invalid_password#UsersLoginTest (1.42s)
        expecting <"sessions/new"> but rendering with <[]>
        test/integration/users_login_test.rb:16:in `block in <class:UsersLoginTest>'

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

Finished in 2.17638s
24 tests, 52 assertions, 1 failures, 0 errors, 0 skips
ubuntu:~/environment/sample_app (basic-login) $ rails t
Running via Spring preloader in process 9467
Started with run options --seed 21895

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

Finished in 2.13073s
24 tests, 54 assertions, 0 failures, 0 errors, 0 skips
```

一応なったけどわからないなー　。
8.23:ユーザーログインのテストで使うfixtureと書いてあったから。
やってみたけど

2.
“safe navigation演算子”（または“ぼっち演算子”）と呼ばれる&.を用いて、リスト8.15の8行目の論理値（boolean値）のテストを、リスト 8.2812 のようにシンプルに変えてください。Rubyのぼっち演算子を使うと、obj && obj.methodのようなパターンをobj&.methodのように凝縮した形で書けます。変更後も、リスト 8.27のテストがパスすることを確認してください。

```rb
def create
    user = User.find_by(email: params[:session][:email].downcase)
    # 送信されたメアドを使ってデータベースから取り出す。
    #emailを小文字にする
    if user &.authenticate(params[:session][:password])
    # user  取得したユーザーが有効かどうか？
    # その後にデータベース上にパスワードがあるか？
    # ユーザーログイン後にユーザー情報のページにリダイレクトする
      log_in user
      # ユーザーのブラウザ内の一時cookiesに暗号化済みのユーザーIDが自動で作成
      redirect_to user
      # 名前付きルート/userのビューを表示する
    else
      flash.now[:danger] = 'Invalid email/password combination'
      # flash.nowでリクエストが発生後メッセージを消滅する
      # エラーメッセージを作成する
        render 'new'
        # newアクションのビューを表示
    end
  end
```