LoginSignup
9
6

More than 5 years have passed since last update.

Capybara Poltergeist で Bootstrap3 のモーダルを使ったテストが失敗する

Last updated at Posted at 2017-03-03

こんな感じの rspec が成功したり失敗したりしていました。

click_link '田中 花子' # モーダルを呼び出す
click_link 'キャンセル' # モーダル内のリンクをクリックするはず(ができないことがある)
expect(page).to have_css '.is-canceled' # クリックできてなければ失敗する

問題の原因

Bootstrap3 のモーダルがスクロールしている最中にモーダル内のボタンをクリックすると、クリックしたときにはその位置にすでにボタンがないことがあるようです。

poltergeistのソースを見ると、このへんで問題が起きていそうでした。

  mouseEvent: (name) ->
    if area_image = @_getAreaImage()
      area_image.scrollIntoView()
    else
      @scrollIntoView()
    # クリックしたいDOMノードの位置を取得
    pos = this.mouseEventPosition() 
    # その位置でノードがクリックできるかチェック(ここでも失敗する可能性はありそうだけど、今回はここではない)
    test = this.mouseEventTest(pos.x, pos.y) 
    if test.status == 'success'
      if name == 'rightclick'
        @page.mouseEvent('click', pos.x, pos.y, 'right')
        this.trigger('contextmenu')
      else
        # 実際のクリックは座標だけで指定(クリックするノードを指定しているわけではないので、すでにそこにノードがなくてもエラーにならずにスルーされる)
        @page.mouseEvent(name, pos.x, pos.y) 
      pos
    else
      throw new Poltergeist.MouseEventFailed(name, test.selector, pos)

修正方法 その1

モーダルが出現するまでの時間 sleep します。

click_link '田中 花子' # モーダルを呼び出す
sleep 1 # モーダルがスクロール完了するのを待つ(bootstrap のモーダルのスクロールは 0.3s)
click_link 'キャンセル' # モーダル内のリンクをクリック
expect(page).to have_css '.is-canceled'

修正方法 その2

sleep なんて不確実な方法は嫌という場合、こんな感じのヘルパーを用意します。

  def wait_for_bs_modal
    script = <<~EOS
      window._capybaraModalWait = 1;
      jQuery(document).one("shown.bs.modal", function(){window._capybaraModalWait = 0;});
    EOS
    page.execute_script(script)
    yield
    Timeout.timeout(Capybara.default_max_wait_time) do
      loop until page.evaluate_script('window._capybaraModalWait').zero?
    end
  end

で、こう書きます。

# モーダルが出現するまで待つ
wait_for_bs_modal do
  click_link '田中 花子' # モーダルを呼び出す
end
click_link 'キャンセル' # モーダル内のリンクをクリック
expect(page).to have_css '.is-canceled'
9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6