RSpecのいろいろ（個人メモ用）

#はじめに
RSpecで覚えることが多々有り、とりあえず、使ったものを書いてるだけのページです。

#ジャンプ（ショートカット）
私が使っているのはmacです。
Cmd + Shift + y で関連するファイルとテストファイルを行き来出来ます。

#Factory Botを省略
毎回テストでFactoryBotと書かなくてよくなる

```rb:spec/rails_helper.rb

RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end
```

#helperの作成

`spec/support`フォルダーを作り、その中にhelperのファイルをつくる。
今回は`spec/support/json_api_helper.rb`

```rb:spec/support/json_api_helper.rb

module JsonApiHelpers
  def json
    JSON.parse(response.body)
  end

  def json_data
    json['data']
  end
end

```

次にrails_helper.rbに追加で記述する

```rb:spec/rails_helper.rb

# コメントになっているので外す↓
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }

RSpec.configure do |config|
  # ここに使うmoduleを記述する
  config.include JsonApiHelpers
end
```

#described_class

参考サイト↓
[Rails tips: テストから共通機能を切り出すリファクタリング（翻訳）](https://techracho.bpsinc.jp/hachi8833/2018_04_17/54695)

```rb
RSpec.describe User do
   let(:user) { described_class.new }
   # 上も下も同じ内容になるみたいです。
   let(:user) { User.new }
end
```

#gem shoulda-matchers

ここに詳しく書いてあります。モデルのテストを書くのに便利！
[shoulda-matchers-Github](https://github.com/thoughtbot/shoulda-matchers)

書いてみたコード

```rb:spec/models/user_spec.rb
require 'rails_helper'
RSpec.describe User, type: :model do
# 上部のコード省略
  it { is_expected.to validate_presence_of(:name) }
  it { is_expected.to validate_presence_of(:email) }
  it { is_expected.to validate_presence_of(:password) }
  it { is_expected.to validate_length_of(:name).is_at_most(30) }
  it { is_expected.to validate_length_of(:email).is_at_most(30) }
  it { is_expected.to validate_length_of(:password).is_at_least(6) }
  it { is_expected.to validate_length_of(:password).is_at_most(128) }
  it { is_expected.to validate_uniqueness_of(:email).case_insensitive }
  it do
    is_expected.to allow_values('first.last@foo.jp',
                                'user@example.com',
                                'USER@foo.COM',
                                'A_US-ER@foo.bar.org',
                                'alice+bob@baz.cn').for(:email)
  end
  it do
    is_expected.to_not allow_values('user@example,com',
                                    'user_at_foo.org',
                                    'user.name@example.',
                                    'foo@bar_baz.com',
                                    'foo@bar+baz.com').for(:email)
  end
  it { is_expected.to have_many(:articles) }
end
```

#carrirwaveのテスト
factory botに画像データを入れたい時（carrirwave)

参考リンク↓
[画像アップロード CarrierWaveを使ったmodelのRSpecを通す](https://qiita.com/motty93/items/5cbc46ce79a502fcaa65)


```rb:spec/factories/articles.rb
FactoryBot.define do
  factory :article do
    profile_image { Rack::Test::UploadedFile.new(File.join(Rails.root, 'spec/fixtures/profile_image.jpg')) }
  end
end
```
specデレクトリー配下にfixturesファイルを作り、その中にサンプルの画像を入れています。

#Testデータを複数登録する

`create_list`メソッドを使う　例↓

```rb:requests/user_request_spec.rb

RSpec.describe 'UserRequest', type: :request do
  describe 'GET #index' do
    before do
      @user = create(:user)
    end
    context 'as an authenticated user' do
      it 'is having pagination' do
        create_list(:user, 100)
        log_in_as(@user)
        get users_path
        assert_select 'div.pagination', count: 2
        User.paginate(page: 1).each do |user|
          assert_select 'a[href=?]', user_path(user), text: user.name
        end
      end
    end
  end
end
```
#test内でログインするhelperの作成(log_in_asと命名)

```rb:support/sessions_helper.rb

module SessionsHelper
  #true、falseを返す
  def is_logged_in?
    !session[:user_id].nil?
  end

　#ログインする
  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
```