6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2021年10月5日 現場Rails Chapter5-12 詳細表示機能のSpecを追加する

詳細表示機能Specを追加する

前回の一覧表示機能に続いて、詳細表示機能のテストコードを追記します。

describe 'タスク管理機能', type: :system do

  let!(:task_a) { FactoryBot.create(:task, name: '最初のタスク'), user: user_a)}

  ...省略
  
  describe '詳細表示機能' do
    context 'ユーザーAがログインしているとき' do
      let(:login_user) { user_a }
      
      before do
        visit task_path(task_a)
      end
      
      it 'ユーザーAが作成したタスクが表示される' do
        expect(page).to have_content '最初のタスク'
      end
    end
  end
end

let!を用いてtask_aを定義しておくと、タスク作成処理を共通化することが出来るため、一覧表示機能でタスクを作成する処理を記述する必要がなくなります。

shared_examplesを利用する

共通したitの内容をまとめる事ができる機能です。
今回の例の場合、詳細表示機能のテストと一覧表示機能のテストで itの内容が被ってしまっています。 その場合に、以下のようにshared_examplesを用います。

shared_examples_for 'ユーザーAが作成したタスクが表示される' do 
  it { expect(page).to have_content '最初のタスク' }  
end

このように共通化の記述をした上で、これまでitを書いていた場所には以下のように書きます。

it_behaves_like 'ユーザーAが作成したタスクが表示される'

使用上の注意としては、すぐに理解できる名前にし、可読性を損なわないようにする必要があります。

新規作成機能のSystem Spec

describe 'タスク管理機能', type: :system do
  describe '新規作成機能' do
    let(:login_user) { user_a }

    before do
      visit new_task_path
      fill_in 'Name', with: task_name
      click_button '登録する'
    end
    
    context '新規作成画面で名称を入力したとき' do
      let(:task_name) { '新規作成のテストを書く' }
      
      it '正常に登録される' do
        # .alert-successというCSSクラスを指定している
        # 特定のタグやCSS要素に特定の文字列が表示されていることを検証する
        expect(page).to have_selector '.alert-success', text: '新規作成のテストを書く'
      end
    end
    
    context '新規作成画面で名称を入力しなかったとき' do
      let(:task_name) { '' }
      
      it 'エラーとなる' do
        # 検証エラーを表示する領域内に、「名称を入力してください」というエラーメッセージが表示される。
        within '#error_explanation' do
          expect(page).to have_content '名称を入力してください'
        end
      end
    end
  end
end

withinメソッド

画面内の特定の範囲に絞って検証することが出来ます。 '名称を入力してください'というエラーメッセージが画面内に1つだけしか存在しない場合などを想定した上でerror_explanationというidの要素を指定して検証しています。

letの上書き

同じ名前のletを複数回定義すると、常に下の階層に定義したletが使われます。つまり、letは上書きができます。しかし、同じ名前のletを複数回定義すると、最終的にどのletが使われるのか分からなくなります。そのため、適切なバランスでletを使います。

describe 'タスク管理機能', type: :system do
  describe '新規作成機能' do  
    let(:login) { user_a }  
    let(:task_name) { '新規作成のテストを書く' } # デフォルトとして設定  

    before do  
      ...
    end

    context '新規作成画面で名称を入力したとき' do  
      it '正常に登録される' do  
        expect(page).to have_selector '.alert-success', text: '新規作成のテストを書く'
      end
    end  

    context '新規作成画面で名称を入力しなかったとき' do  
      let(:task_name) { '' } # 上書き  

      it 'エラーになる' do  
        within '#error_explanation' do  
          expect(page).to have_content '名称を入力してください'
        end
      end
    end
  end
end

参照

使えるRSpec入門・その4「どんなブラウザ操作も自由自在!逆引きCapybara大辞典」