【RSpec】Railsチュートリアル第6版　第9章

#はじめに
Railsチュートリアル第6版のテストをRSpecで書き直していく。

###目次
- [第3章](https://qiita.com/supyolo888/items/35081ead2cfafb40a995)
- [第4章](https://qiita.com/supyolo888/items/939b670b62eb18467f6d)
- [第5章](https://qiita.com/supyolo888/items/42234ac2ed3919b14586)
- [第6章](https://qiita.com/supyolo888/items/bd10e64c77fe391cf203)
- [第7章](https://qiita.com/supyolo888/items/d2824ced26402b5f58d1)
- [第8章](https://qiita.com/supyolo888/items/508caaa40edf307093ed)
- 第9章（本記事）
- [第10章](https://qiita.com/supyolo888/items/a8695b20ec8082f85223)
- [第11章](https://qiita.com/supyolo888/items/5c81331e46f1d9d5ab3c)
- [第12章](https://qiita.com/supyolo888/items/fbb95671d39dfbf9df90)
- [第13章](https://qiita.com/supyolo888/items/c88b6acd4ff55750defc)
- [第14章](https://qiita.com/supyolo888/items/532390902bf3e0f5348e)

#Minitest

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

```rb:test/integration/users_login_test.rb
require 'test_helper'

class UsersLoginTest < ActionDispatch::IntegrationTest
  .
  .
  .
  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
  end
end
```

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

```rb:test/models/user_test.rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase

  def setup
    @user = User.new(name: "Example User", email: "user@example.com",
                     password: "foobar", password_confirmation: "foobar")
  end
  .
  .
  .
  test "authenticated? should return false for a user with nil digest" do
    assert_not @user.authenticated?('')
  end
end
```

###log_in_asヘルパーを追加する

```rb:test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
.
.
.
class ActiveSupport::TestCase
  fixtures :all

  # テストユーザーがログイン中の場合にtrueを返す
  def is_logged_in?
    !session[:user_id].nil?
  end

  # テストユーザーとしてログインする
  def log_in_as(user)
    session[:user_id] = user.id
  end
end

class ActionDispatch::IntegrationTest

  # テストユーザーとしてログインする
  def log_in_as(user, password: 'password', remember_me: '1')
    post login_path, params: { session: { email: user.email,
                                          password: password,
                                          remember_me: remember_me } }
  end
end
```

###［remember me］チェックボックスのテスト


```rb:test/integration/users_login_test.rb
require 'test_helper'

class UsersLoginTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end
  .
  .
  .
  test "login with remembering" do
    log_in_as(@user, remember_me: '1')
    assert_not_empty cookies[:remember_token]
  end

  test "login without remembering" do
    # cookieを保存してログイン
    log_in_as(@user, remember_me: '1')
    delete logout_path
    # cookieを削除してログイン
    log_in_as(@user, remember_me: '0')
    assert_empty cookies[:remember_token]
  end
end
```

###永続的セッションのテスト

```rb:test/helpers/sessions_helper_test.rb
require 'test_helper'

class SessionsHelperTest < ActionView::TestCase

  def setup
    @user = users(:michael)
    remember(@user)
  end

  test "current_user returns right user when session is nil" do
    assert_equal @user, current_user
    assert is_logged_in?
  end

  test "current_user returns nil when remember digest is wrong" do
    @user.update_attribute(:remember_digest, User.digest(User.new_token))
    assert_nil current_user
  end
end
```

#RSpec

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

```rb:spec/requests/users_sessions_spec.rb
require 'rails_helper'

RSpec.describe "session request", type: :request do

  let(:user) {FactoryBot.create(:user)}

  it "log in and log out" do
    post login_path, params: { session: {
      email: user.email,
      password: user.password,
    } }
    expect(response).to redirect_to user_path(user)
    expect(is_logged_in?).to be_truthy 
    delete logout_path
    expect(response).to redirect_to root_path
    expect(is_logged_in?).to be_falsey
    delete logout_path
    expect(response).to redirect_to root_path
    expect(is_logged_in?).to be_falsey
  end

end
```

`is_logged_in?`を使いたいので、request specに記述。

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

```rb:spec/models/user_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do

  before do
    @user = User.new(name: "Example User", email: "user@example.com",
                     password: "foobar", password_confirmation: "foobar")
  end
  .
  .
  .
  it "authenticated? should return false for a user with nil digest" do
    expect(@user.authenticated?("")).to be_falsy
  end

end
```

###log_in_asヘルパーを追加する

```rb:spec/support/support.rb
module Support

  def is_logged_in?
      !session[:user_id].nil?
  end
 
  def log_in_as(user, remember_me: "1")
    post login_path, params: { session: {
      email: user.email,
      password: user.password,
      remember_me: remember_me,
    } }
  end
  
end

RSpec.configure do |config|
  config.include Support
end
```

###［remember me］チェックボックスのテスト

```rb:spec/requests/users_sessions_spec.rb

require 'rails_helper'

RSpec.describe "UsersSessions", type: :request do

  let(:user) {FactoryBot.create(:user)}
  .
  .
  .
  it "login with remembering" do
    log_in_as(user, remember_me: "1")
    expect(cookies[:remember_token]).not_to eq ""
  end

  it "login without remembering" do
    log_in_as(user, remember_me: "1")
    expect(cookies[:remember_token]).not_to eq ""
    delete logout_path
    log_in_as(user, remember_me: "0")
    expect(cookies[:remember_token]).to eq ""
  end

end
```


###永続的セッションのテスト

```rb:spec/helpers/sessions_helper_spec.rb

require 'rails_helper'

RSpec.describe SessionsHelper, type: :helper do

  let(:user) { FactoryBot.create(:user) }

  before do
    remember(user)
  end

  it "current_user returns right when session is nil" do
    expect(current_user).to eq user
    expect(is_logged_in?).to be_truthy
  end

  it "current_user returns nil when remember digest is wrong" do
    user.update_attribute(:remember_digest, User.digest(User.new_token))
    expect(current_user).to eq nil
  end

end
```