【Rails6】RSpecによる検索機能（ransack）の結合テストの実装

#はじめに
サービスの品質を保つために必要不可欠なテストを実施しております。

今回は、ransackを使用して、実装した検索機能の結合テストを実装し、その実装内容を記事にしていきたいと思います。

#前提
・ransackというgemを使っての検索機能は実施済み

```Gemfile
gem 'ransack'
```

・投稿時の結合テストと同じ、テストファイルに検索機能の内容も記述しています。
　投稿時におけるテストコードの記述は以下のURLよりご覧になれます。

https://qiita.com/narimiya/items/45a4561349f1039a9a65

#バージョン
rubyのバージョン　ruby-2.6.5
Railsのバージョン Rails:6.0.0
rspec-rails 4.0.0

#実施したテスト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/90ab69c1-31ae-4c2d-c9c3-920c648687de.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/9e7c2c2d-5f01-fbc7-ab4b-1324d5416238.png)

#検索画面
![検索.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/708fb68a-d07f-f6ee-56ae-899ef99e0389.gif)

キーワード検索ができ、検索すると投稿したタイトルが表示される。

#definitionsテーブルのカラムの紹介

```xxx_create_definitions.rb
class CreateDefinitions < ActiveRecord::Migration[6.0]
  def change
    create_table :definitions do |t|
      t.text       :title,          null: false
      t.text       :body,           null: false
      t.references :user,           foreign_key: true
      t.timestamps
    end
  end
end
```

#検索に関するコントローラーの内容

```app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
#省略
  before_action :set_search

  def set_search
#省略

    @definition_key = Definition.ransack(params[:q])
    @search_definitions = @definition_key.result(distinct: true).page(params[:page])

#省略
  end

#省略
end
```
※viewに関しての記述の掲載は省略しております。

#モデル内のバリデーション

```app/models/definition.rb
class Definition < ApplicationRecord
  belongs_to :user
  has_many :answers, dependent: :destroy
  has_many :reviews, dependent: :destroy
  has_many :notifications, dependent: :destroy
  has_many :likes, dependent: :destroy

  validates :title, presence: true
  validates :body, presence: true

# 〜省略〜
```


#FactoryBotの内訳

```spec/factories/definitions.rb
FactoryBot.define do
  factory :definition do
    title                        {Faker::Lorem.sentence}
    body                         {Faker::Lorem.sentence}
    association :user
  end
end
```

#サポートモジュール
新規投稿する際の記述をモジュール化しています。

```spec/support/definition_up_support.rb
module DefinitionUpSupport
  def definition_up(definition_title, definition_body)
 
    # 新規投稿ページへのリンクがあることを確認する
    expect(page).to have_content('投稿')

    # 投稿作成ページに移動する
    visit new_definition_path

    # フォームに情報を入力する
    fill_in 'definition[title]', with: definition_title
    fill_in 'definition[body]', with: definition_body

    # 送信するとDefinitionモデルのカウントが1上がることを確認する
    expect{
      find('input[name="commit"]').click
    }.to change { Definition.count }.by(1)

    # 投稿完了ページに遷移することを確認する
    expect(current_path).to eq(root_path)
  end
end
```

#テストコードの内容

```spec/system/definitions_spec.rb
#投稿における結合テストの記述は省略

RSpec.describe '投稿のタイトルの検索', type: :system do
  before do
    @definition = FactoryBot.create(:definition)
    @definition_title = "あいうえお"
    @definition_body = Faker::Lorem.sentence
  end
    context '投稿の検索ができるとき' do
        it 'ログインしたユーザーは自らが投稿した投稿の検索ができる' do
        # definitionを投稿したユーザーでログインする
        sign_in(@definition.user)

        # 新規投稿する
        definition_up(@definition_title, @definition_body)
      
        # 投稿ページに移動する
        visit root_path(anchor:"definitions")

        # 検索欄に検索キーワードを入力する
        fill_in 'q[title_cont]', with: 'あ'
        # 検索ボタンをクリックする
        find('#definition_title_search').click
        # 検索結果があることを確認する
        expect(page).to have_content(@definition.title)
        end
   end
```

#補足説明
##fill_in 'q[title_cont]', with: 'あ'について
検索入力欄のname属性の値をfill_inの要素としています。

今回はキーワード入力して検索できるテストを実施したいので、そのキーワードとなる「あ」（適当）をwith以下に指定しています。

## find('#definition_title_search').clickについて
findの引数には検索マークの記述内のidの値を指定しています。

```app/views/index.html.erb
#省略
    <i class="fas fa-search" id='definition_title_search'></i> 
#省略
```

idの値は自身で任意に設定できます。
idを指定する際は文頭に#をつけます。


##expect(page).to have_content(@definition.title)について
最終的にタイトルの表示が確認できればいいので、記述の意味としては
「ページ内に投稿のタイトルがあることを確認する」
になります。

以上です。