テストが不安定問題
feature specで、クリックできたり、できなかったりする問題。
Ajaxが終了するのを待っても、sleepしても不安定だった。
なぜ不安定かというと、highchartsなどのグラフ描画ライブラリを使っていて、svgの描画が実行され、アンカー要素が最初にあった位置から移動してしまい、クリックができなかったりしたからだと推測した。
画面遷移するまで待つメソッドを定義
待ってもダメなので、何度もクリックさせるような仕組みを作ってみた。
module WaitUntilTransition
# 画面遷移するまでリンクのクリックを行う
#
# @param [String] link_text クリックするリンクのテキスト
# @param [String] within_selector withinを使って領域を絞り込む際のセレクタ
# @param [String] next_page_selector 次のページに存在するセレクタ。nilの場合は`within_selector`が`next_page_selector`になる
def wait_until_transition_by_click(link_text, within_selector, next_page_selector=nil)
if next_page_selector.nil?
next_page_selector = within_selector
within_selector = nil
end
Timeout.timeout(Capybara.default_max_wait_time) do
begin
unless page.all(next_page_selector).present?
if within_selector.nil?
find_link(link_text).click
else
within(within_selector) do
find_link(link_text).click
end
end
sleep 1
if within_selector.nil?
raise if find_link(link_text, wait: 1)
else
if page.all(within_selector).present?
within(within_selector) do
raise if find_link(link_text, wait: 1)
end
end
end
end
rescue => e
retry
end
end
end
end
RSpec.configure do |config|
config.include WaitUntilTransition, type: :feature
end
最初のページには存在せず、次のページに存在するセレクタを条件とする。
- 次のページに存在するはずのセレクタがあるかチェックする
- 1がなければ、クリックを実行し、多少sleepをした後にまだクリック対象の要素が存在するかチェックする。その際に、タイムアウトを防ぐために、敢えてwaitを短くする。
- クリック対象要素が存在するようならば画面遷移していないのでraiseで例外を発生させる。
- retryでもう一度1から3まで試す
- 1で次ページのセレクタがあれば、画面遷移したと見なす
- それでもタイムアウトするならば、他に問題がある!
以上。
使い方
require 'rails_helper'
feature 'サンプル', js: true do
scenario '次のページに遷移すること' do
wait_until_transition_by_click '次のページへ', '#pager', '#next-page-selector'
within '#next-page-selector' do
expect(page).to have_content '次のページにあるコンテンツ'
end
end
end
不安定だったテストが今の所100%の成功率になったので、これで様子を見る。