目的
Capybaraを用いたRSpecのfeature specで、bootstrap3を使って実装したモーダルを動作させた振る舞いをテストする
問題
もともとのテストは以下。リソース作成のあと、編集ボタンをクリックするとモーダルが表示される仕様なのだが、アプリケーション上では正しく動作するものの、Capybara DSLでフローを記述しても、出てくるべきモーダルが表示されずに困った。
# encoding: UTF-8
require 'spec_helper'
describe 'CreditCard', type: :feature, js: true do
def create_credit_card(
name: nil, number: nil, pin: nil)
visit new_credit_card_path
find_link('クレジットカードを登録する').click
fill_in 'credit_card_name', with: name
fill_in 'credit_card_number', with: number
fill_in 'credit_card_pin', with: pin
sleep 0.5
click_button '登録'
end
it 'クレジットカードを登録したあと、登録情報を編集する' do
create_credit_card(
card: 'VISA',
number: '1234-5678-9012-3456',
pin: '000')
expect(page).to have_content 'クレジットカードを登録しました'
within '#credit-card__info' do
find_button('カード情報を編集する').click
end
=> #credit-card__info下にある「カード情報を編集する」ボタンをクリックすると、通常はモーダルが表示されるはずが、表示されず、ここでテストが落ちる
fill_in 'credit_card_name', with: 'Master'
click_button '保存'
expect(page).to have_content 'クレジットカードを編集しました'
expect(page).to have_content 'Master'
expect(page).to have_content '1234-5678-9012-3456'
end
DOM上はモーダル部分にあたるHTMLが生成されているので、save_and_open_page
で見るとモーダル要素は描画されている。が、JavaScriptを使ってドライバのスクリーンショットを撮影するsave_screenshot
を使ってみると、いっこうにモーダルは表示されていない。
対処
これは実はbootstrapのモーダル表示時に実行されるCSS animationの表示が正しく動いていないためであり、モーダルを表示させるときに該当するクラスを削除することで正しく動いた。
以下の1行を、モーダル表示するアクションの前に入れてあげることで、fadeクラスによって発火していたアニメーションが実行されず、モーダルが正しく表示されるようになった。
# fadeクラスを削除
page.evaluate_script('$(".fade").removeClass("fade")')
# ボタンをクリックするとモーダルが表示されるので、先に進むことができる
within '#credit-card__info' do
find_button('カード情報を編集する').click
end
...
Capybaraを使ったfeature specは使っているjavascipt driverに依存する部分が多いので、色々なワークアラウンドが存在しているけど、たいていはjavascriptによる問題なので、こういったスクリプトを直接実行することで避けられることもしばしばある。