Rails6 + Bootstrap4 + RSpec トグル表示のリンクやモーダルのテストについて
Q&A
Closed
解決したいこと
- Navbar上のトグルスイッチを押してドロップメニューを表示
- メニューの中のログインのリンクを押すとログイン用フォームをモーダルで表示
- フォーム全部空欄で’送信’ボタンを押し、モーダル上でエラーメッセージが出ることを確認する アプリ上では動くのですが、一連の動作をどうやってRSpecで表記すればよいのか分からず詰まっています。 ご教授いただければ有難いです。
環境
主なGemファイルは以下です。
ruby '2.7.4'
gem 'active_storage_validations', '0.8.2'
gem 'aws-sdk-s3', '1.46.0', require: false
gem 'bcrypt', '3.1.13'
gem 'bootsnap', '1.4.5', require: false
gem 'bootstrap', '~> 4.6.0'
gem 'image_processing', '1.9.3'
gem 'jbuilder', '2.9.1'
gem 'jquery-rails'
gem 'mini_magick', '4.9.5'
gem 'puma', '4.3.6'
gem 'rails', '6.0.3'
gem 'rails-i18n'
gem 'sass-rails', '5.1.0'
gem 'sprockets-rails', '~> 3.2.2'
gem 'turbolinks', '5.2.0'
gem 'uglifier'
gem 'webpacker', '~> 3.5'
gem 'will_paginate', '3.1.8'
group :development, :test do
gem 'byebug', '11.0.1', platforms: [:mri, :mingw, :x64_mingw]
gem 'shoulda-matchers'
gem 'spring-commands-rspec'
gem 'sqlite3', '1.4.2'
end
group :test do
gem 'capybara', '3.28.0'
gem 'database_cleaner'
gem 'factory_bot_rails'
gem 'faker'
gem 'guard', '2.13.0'
gem 'guard-minitest', '2.4.4'
gem 'launchy'
gem 'minitest-reporters', '1.1.14'
gem 'rails-controller-testing', '1.0.4'
gem 'rspec-rails'
gem 'selenium-webdriver', '3.142.4'
gem 'webdrivers', '4.1.2'
end
spec/rails_helpの主な内容が以下です
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
begin
ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
puts e.to_s.strip
exit 1
end
#capybara内のmethodを読み込む
require 'capybara/rspec'
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
config.include FactoryBot::Syntax::Methods
config.before(:each, type: :system) do
driven_by :selenium_chrome_headless
end
config.include ApplicationHelper
#signup_pathがundefinedと言われたので入れてみた
config.include Rails.application.routes.url_helpers
#強制的にCapybara::DSLを読み込む
config.include Capybara::DSL
#作成したヘルパーを追加
config.include TechHelper
#全てのテストにaggregate_failuresを適用する(ブロックまとめて書いても全部実行する)
config.define_derived_metadata do |meta|
meta[:aggregate_failures] = true unless meta.key?(:aggregate_failures)
end
end
#shoulda matcherを入れる
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
# トグルSWやモーダルなどで非表示になっているものをtestするため
Capybara.ignore_hidden_elements = false
# Capybaraのdriverを指定してみる(デフォルトは:rack_test)
Capybara.default_driver = :rack_test
# jsオプション有効時のドライバを設定(デフォルトは:selenium)
Capybara.javascript_driver = :selenium
#任意の場所でScreenshotを撮るために用意する
def take_screenshot
page.save_screenshot "tmp/capybara/screenshot-#{DateTime.now}.png"
end
layouts/_navbar.html.erbの抜粋は以下です
# <div class="modal fade role="dialog" aria-hidden="true">はappeication.html.erbに記載
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-secondary">
<div class="container">
<a id="logo" class="navbar-brand" href='/'>
<i class="fas fa-hand-holding-heart"></i>
ブランド
</a>
<button class="navbar-toggler" type="button" id="humberger"
data-toggle="collapse"
data-target="#navcol-1"
aria-controls="#navcol-1" aria-expanded="false"
aria-label="#navcol-1">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navcol-1">
<ul class="nav navbar-nav ml-auto">
<li>
<a class="text-light" href='/'>Home</a>
</li>
<li>
<%= link_to "ログイン", login_path, remote: true,
class: "text-light", id: "modal-open" %>
</li>
<li>
<a class="text-light" href='/signup'>新規登録</a>
</li>
</ul>
</div>
</div>
</nav>
layouts/sessions/_login_form-modal.html.erbの内容が以下です
<!-- ログインフォーム用モーダル -->
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">ログイン</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<hr style="margin-bottom: 3px">
<div class="modal-body">
<%= form_with(url: login_path, scope: :session,
class: 'js-form') do |f| %>
<!-- ここにエラーメッセージが出る-->
<div class="js-message-error"></div>
<%= f.label :email, "メールアドレス" %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password, "パスワード" %>
<%= f.password_field :password, class: 'form-control' %>
<hr />
<%= f.submit "送信", class: "mt2 btn btn-info form-btn float-right" %>
<% end %>
</div>
</div>
</div>
テストを試みているspecファイル(spec/systems/sessions_spec.rb)は以下です。
require 'rails_helper'
RSpec.describe 'Sessions', type: :system do
before do
visit root_path
end
it 'モーダルが表示されるか', js: true do
find(".navbar-toggler").click
sleep 0.5
take_screenshot
page.evaluate_script('$(".fade").removeClass("fade")')
click_link 'ログイン'
sleep 0.5
is_expected.to have_selector(text: "メールアドレス")
end
#一連の流れを以下のように書きましたが、うまくいかず、上記のexampleを書いて確認を試みました。
# #モーダルを表示して無効な値を入力する
# describe 'enter an invalid values', js: true do
# before do
# find(".navbar-toggler").click
# page.evaluate_script('$(".fade").removeClass("fade")')
# click_link 'ログイン'
# fill_in 'メールアドバイス', with: ''
# fill_in 'パスワード', with: ''
# click_button '送信'
# end
# #エラーメッセージが出る
# it 'gets an error message' do
# is_expected.to have_selector(text: "入力内容に誤りがあります")
# end
# #一度モーダルを閉じる
# context 'close modal' do
# before do
# click_on 'x'
# click_on 'ログイン'
# end
# #エラーメッセージが消える
# it 'is message disappear' do
# is_expected.to_not have_selector(text: "入力内容に誤りがあります" )
# end
# end
# end
end
発生している問題・エラー
Failures:
1) Sessions モーダルが表示されるか
Failure/Error: click_link 'ログイン'
Selenium::WebDriver::Error::ElementNotInteractableError:
element not interactable
(Session info: headless chrome=93.0.4577.82)
[Screenshot]: toggleが開いておらずプルダウンが出てないスクリーンショット
# 0 chromedriver 0x0000000100c976d9 chromedriver + 2758361
# 1 chromedriver 0x000000010134a893 chromedriver + 9783443
# 2 chromedriver 0x0000000100a2298f chromedriver + 182671
# 3 chromedriver 0x0000000100a57f39 chromedriver + 401209
# 4 chromedriver 0x0000000100a4c358 chromedriver + 353112
# 5 chromedriver 0x0000000100a74022 chromedriver + 516130
# 6 chromedriver 0x0000000100a4c0e5 chromedriver + 352485
# 7 chromedriver 0x0000000100a7429e chromedriver + 516766
# 8 chromedriver 0x0000000100a86514 chromedriver + 591124
# 9 chromedriver 0x0000000100a74243 chromedriver + 516675
# 10 chromedriver 0x0000000100a4aa0e chromedriver + 346638
# 11 chromedriver 0x0000000100a4bc75 chromedriver + 351349
# 12 chromedriver 0x0000000100c5e1df chromedriver + 2523615
# 13 chromedriver 0x0000000100c709f2 chromedriver + 2599410
# 14 chromedriver 0x0000000100c4302b chromedriver + 2412587
# 15 chromedriver 0x0000000100c71e1a chromedriver + 2604570
# 16 chromedriver 0x0000000100c5396c chromedriver + 2480492
# 17 chromedriver 0x0000000100c8bd38 chromedriver + 2710840
# 18 chromedriver 0x0000000100c8bec1 chromedriver + 2711233
# 19 chromedriver 0x0000000100c9c6f8 chromedriver + 2778872
# 20 libsystem_pthread.dylib 0x00007fff204a78fc _pthread_start + 224
# 21 libsystem_pthread.dylib 0x00007fff204a3443 thread_start + 15
# ./spec/systems/sessions_spec.rb:13:in `block (2 levels) in <main>'
Finished in 6.9 seconds (files took 1.23 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/systems/sessions_spec.rb:8 # Sessions モーダルが表示されるか
自分で試したこと
qiitaの記事などを参考に
js: true
を入れる、sleep
で少し待つ、page.evaluate_script('$(".fade").removeClass("fade")')
を入れてみる
を試みましたが、どれも効果がありませんでした。
スクショではそもそもプルダウンが開いていないので、何か根本的に誤りがあるのかもと感じています
何かお気づきの点があればご指摘いただきたく。
よろしくお願いします。
0