課題:poltergeistのテストが安定しない
Bootstrap3のモーダル系を使ったテストがpoltergeistの気分次第で落ちる
sleepで調整しても終わりがないので、それを是正したい。
改善策:JavaScriptでフラグを立てて管理する方式にする
Capybara Poltergeist で Bootstrap3 のモーダルを使ったテストが失敗する
という記事を読んで、これはいいなぁと思ったので参考にすることに。
自分の場合は、モーダルが表示されたときよりもモーダルが消える前にテストが評価しようとして落ちたりしたので、そっちをなんとかしたかった。ついでにモーダル以外のも定義しときたかった(後で追加するの面倒)ので、いろんなイベントに対応できるようにメタプログラミングでメソッドを作るようにした。
(2018-07-03 追記)
wait_until_hidden_backdrop
を定義しました。hidden.bs.modal
が走った後でも、モーダルダイアログの背景(透過の黒背景)が画面を覆っている場合があったので、追加しました。wait_until_hidden_bs_modal
の中で背景が消えるまで待つという処理を入れてみたのですが、モーダルから更にモーダルを呼び出したりすると初回のモーダルの影響で背景が消えなくて処理が終わらずタイムアウトエラーになったので、個別に使うようにしています。
module WaitUntilBootstrap3Components
def self.define_wait_bootstrap3_event(event_name)
event_name_underscore = event_name.gsub('.', '_')
event_name_camelcase = event_name_underscore.camelize
define_method :"wait_until_#{event_name_underscore}" do |&b|
script = <<~EOS
window._capybara#{event_name_camelcase} = 1;
jQuery(document).one("#{event_name}", function(){ window._capybara#{event_name_camelcase} = 0; });
EOS
page.execute_script(script)
b.call unless b.nil?
Timeout.timeout(Capybara.default_max_wait_time) do
loop until page.evaluate_script("window._capybara#{event_name_camelcase}").zero?
end
end
end
def wait_until_hidden_backdrop
Timeout.timeout(Capybara.default_max_wait_time) do
loop until page.all('.modal-backdrop').blank?
end
end
def self.included(_)
%w(popover modal tooltip collapse dropdown tab).each do |component_name|
%w(shown.bs hidden.bs).each do |event_prefix|
define_wait_bootstrap3_event("#{event_prefix}.#{component_name}")
end
end
%w(loaded.bs.modal closed.bs.alert slid.bs.carousel inserted.bs.tooltip inserted.bs.popover).each do |event_name|
define_wait_bootstrap3_event(event_name)
end
end
end
RSpec.configure do |config|
config.include WaitUntilBootstrap3Components, type: :feature
end
使い方
Bootstrap3で使われるイベント名の.
を_
に変換して、メソッドの接頭辞にwait_until_
をつけるという感じです。
# モーダルが開き終わるのを待つ
wait_until_shown_bs_modal do
click_button "モーダルを表示する"
end
# モーダル上で作業する
# モーダルが閉じるのを待つ
wait_until_hidden_bs_modal do
click_button "閉じる"
end
感想
よく落ちていた箇所のテストがこれで安定するようになったので、bootstrap3を入れているプロジェクトにどんどん適用していきたい所存。