こんにちは、Nanayakuです。
form_forからform_withに変更した時、System spec(fill_in)でエラーが起きたので、その対処法を紹介します。
目次
fill_inでエラーになる
どのようなエラーが起きていたかと言うと、fill_inで入力するメールアドレス (label)が見つからないと言うエラーでした。
下記のようなログインのテストを実行します。
RSpec.feature 'Users', type: :system do before do @user = User.create( name: 'TEST_USER', email: 'test@example.com', password: 'password1234' ) end it 'ログインする' do visit root_path visit login_path fill_in 'メールアドレス', with: 'test@example.com' fill_in 'パスワード', with: 'password1234' click_on 'ログインする' expect(page).to have_content 'ログインしました' end end
root_path
login_path
<h1 class="text-conteiner text-center text-white">ログイン</h1> <%= form_for :session, url: login_path do |f| %> <%= f.label :email, 'メールアドレス' , class: 'text-white' %> <%= f.text_field :email, class: 'form-control' %> <%= f.label :password, 'パスワード' , class: 'text-white' %> <%= f.password_field :password, class: 'form-control' %> <%= f.submit "ログインする", class: 'btn-block btn-white vertical-btn' %> <% end %>
すると、下の画像のようにメールアドレスが見つけられないとエラーが出ます。
'メールアドレス'を'email'に変更しても同じでした。
対処法
対処法は、入力部分をidで指定する方法です。
メールアドレス の入力部分に「id: 'sesstion_email'」、パスワードの入力部分に「id: 'sesstion_password'」を追記します。
追記したものが、下記になります。
<h1 class="text-conteiner text-center text-white">ログイン</h1> <%= form_with scope: :session, url: login_path, local: true do |form| %> <%= form.label :email, 'メールアドレス' , class: 'text-white' %> <%= form.text_field :email, class: 'form-control', id: 'sesstion_email' %> #↑↑↑↑↑↑↑↑↑↑↑ <%= form.label :password, 'パスワード' , class: 'text-white' %> <%= form.password_field :password, class: 'form-control', id: 'sesstion_password' %> #↑↑↑↑↑↑↑↑↑↑↑↑↑ <%= form.submit "ログインする", class: 'btn-block btn-white vertical-btn' %> <% end %>
テストは以下のように書き直すと、テストが通ります。
require 'rails_helper' RSpec.feature 'Users', type: :feature do before do @user = User.create( name: 'TEST_USER', email: 'test@example.com', password: 'password1234' ) end it 'ログインする' do visit root_path visit login_path fill_in 'sesstion_email', with: 'test@example.com' fill_in 'sesstion_password', with: 'password1234' click_on 'ログインする' expect(page).to have_selector '.alert', text: 'ログインしました' end end
上手くいかなかった方法
「Capybara で同名の CSS セレクタを持つ複数の HTML 要素から任意の要素を見つける | EasyRamble」を参考に、共通のCSSクラスを指定する方法を行いましたが、ログインに成功できませんでした。
自分は、共通のクラスの「form-control」を指定しました。
require 'rails_helper' RSpec.feature 'Users', type: :system do before do @user = User.create( name: 'TEST_USER', email: 'test@example.com', password: 'password1234' ) end it 'ログインする' do visit root_path visit login_path first(".text-white", visible: false).set("test@example.com") page.all(".text-white", visible: false)[1].set("password1234") click_on 'ログインする' expect(page).to have_selector '.alert', text: 'ログインしました' end end
参考サイト
【RSpec/capybara】fill_inが上手く動作しない - Qiita
Capybara で同名の CSS セレクタを持つ複数の HTML 要素から任意の要素を見つける | EasyRamble
まとめ
form_forからform_withに変更し、System specの「fill_in」でエラーが起きた時は、「label」名ではなく「id」名で指定する。