Rails Tutorialの第４版をRSpecでテスト-5

[Ruby on Rails チュートリアル][link-1]の第4版を学習し、[Everyday Rails - RSpecによるRailsテスト入門][link-2]でRSpecを学習したので、[Ruby on Rails チュートリアル][link-1]をRSpecでテストしてみました。
今回は第11章のテストを書きます。

第3章～第10章のテストは以下。
 - [Railsチュートリアルの第4版をRSpecでテスト-1][link-3]（第3章～第6章）
 - [Railsチュートリアルの第4版をRSpecでテスト-2][link-4]（第7章～第8章）
 - [Railsチュートリアルの第4版をRSpecでテスト-3][link-5]（第9章）
 - [Railsチュートリアルの第4版をRSpecでテスト-4][link-6]（第10章）

[link-1]:https://railstutorial.jp/
[link-2]:https://leanpub.com/everydayrailsrspec-jp
[link-3]:https://qiita.com/yano12/items/eba8693272c31d6af7f0
[link-4]:https://qiita.com/yano12/items/4ef93129a50249adcb8d
[link-5]:https://qiita.com/yano12/items/319615e6e5fdcd7d844a
[link-6]:https://qiita.com/yano12/items/99e3fd4213f61339bad4
[link-7]:https://railstutorial.jp/chapters/account_activation?version=5.1#sec-exercises_mailer_templates
[link-8]:https://qiita.com/yano12/items/f5167416f3c20e1896d4
[link-9]:https://railstutorial.jp/chapters/password_reset?version=5.1#cha-password_reset
[link-10]:https://qiita.com/IrieLuka/items/34b0edccecc036d24748

# アカウントの有効化
[Ruby on Rails チュートリアル 11章][link-7]のアカウントの有効化をテストしていきます。

## 送信メールのテスト
アカウント有効化のメールが正しく送信されることをテストします。
Userメイラーを生成すると，spec/mailers/user_mailer_spec.rbが自動で生成されるので、これを利用してアカウント有効化メールの送信とメールプレビューをテストします。

```spec/mailers/user_mailer_spec.rb
require "rails_helper"

RSpec.describe UserMailer, type: :mailer do
  let(:user) { FactoryBot.create(:user) }
  
  describe "account_activation" do
    let(:mail) { UserMailer.account_activation(user) }

    # メール送信のテスト
    it "renders the headers" do
      expect(mail.to).to eq ["tester1@example.com"]
      expect(mail.from).to eq ["noreply@example.com"]
      expect(mail.subject).to eq "Account activation"
    end
    
    # メールプレビューのテスト
    it "renders the body" do
      expect(mail.body.encoded).to match user.name
      expect(mail.body.encoded).to match user.activation_token
      expect(mail.body.encoded).to match CGI.escape(user.email)
    end
  end
end
```

実行しパスするのを確認します。

## 有効化のテスト
続いて、アカウント有効化が正しく機能することをテストします。
spec/requests/user_spec.rbにcreateアクションのテストを追加しアカウント有効化をテストします。

```spec/requests/user_spec.rb
require 'rails_helper'

RSpec.describe "User pages", type: :request do
  let(:user) { FactoryBot.create(:user) }
  let(:other_user) { FactoryBot.create(:user) }
  
  # 他のアクションのテストは省略

  describe "#create" do
    include ActiveJob::TestHelper
    
    it "is invalid with invalid signup information" do
      perform_enqueued_jobs do
        expect {
          post users_path, params: { user: { name: "",
                                            email: "user@invalid",
                                            password: "foo",
                                            password_confirmation: "bar" } }
        }.to_not change(User, :count)
      end
    end
    
    it "is valid with valid signup information" do
      perform_enqueued_jobs do
        expect {
          post users_path, params: { user: { name: "ExampleUser",
                                            email: "user@example.com",
                                            password: "password",
                                            password_confirmation: "password" } }
        }.to change(User, :count).by(1)
        
        expect(response).to redirect_to root_path
        user = assigns(:user)    # gem 'rails-controller-testing'をインストール
        # 有効化していない状態でログインしてみる
        sign_in_as(user)
        expect(session[:user_id]).to be_falsey
        # 有効化トークンが不正な場合
        get edit_account_activation_path("invalid token", email: user.email)
        expect(session[:user_id]).to be_falsey
        # トークンは正しいがメールアドレスが無効な場合
        get edit_account_activation_path(user.activation_token, email: 'wrong')
        expect(session[:user_id]).to be_falsey
        # 有効化トークンが正しい場合
        get edit_account_activation_path(user.activation_token, email: user.email)
        expect(session[:user_id]).to eq user.id
        expect(user.name).to eq "ExampleUser"
        expect(user.email).to eq "user@example.com"
        expect(user.password).to eq "password"
      end
    end
  end
end
```

ここでは、assignsメソッドを使って対応するアクション内のインスタンス変数にアクセスしています。
assignsメソッドを使用するためにGemfileに'rails-controller-testing'をインストールします。

```Gemfile
group :test do
  gem 'rails-controller-testing'
# 他のgemは省略
```

実行しテストがパスするのを確認します。

今回は以上です。
12章は完成し次第書いていきます。

#追記
第12章のテストを書きました。
 - [Railsチュートリアルの第4版をRSpecでテスト-6][link-10]（第12章）