祝!Chrome Headless移行完了
私が担当しているプロジェクトのFeatureSpecで、Headless Chromeに移行が完了しました。なかなか大変だったので、ハマったポイントを覚えている限り書いておこうと思います。
- Capybara.register_driver周辺
- 画像をダウンロードしない設定など
- テーブルに行がなくなるとテーブルごとvisibleがfalse扱いになる
- DatePickerを使用している箇所にfill_inでデータを入れると、DatePickerが表示されっぱなしになり、被っているボタンが押せなくなる
- driver依存の操作ができなくなる
- trigger('click')など
- driver.network_trafficなど
- alert, confirm, promptなどのダイアログ系が自動でOKを押されなくなる
register_driverでHeadless Chromeを登録する
Seleniumのドライバーとして、chromeを登録し、オプションでHeadlessにしていきます。
chrome_optionsで色々と指定します。
- headless・・・Headlessにする
- disable-gpu・・・GPUを使わない(現状必須)
- window-size=1680,1050・・・ウィンドウサイズ指定
- blink-settings=imagesEnabled=false・・・画像をダウンロードしない
- lang=ja・・・日本語指定
また、bridgeを使ってファイルのダウンロードを許可し、ダウンロードパスを指定しています。
WaitForDownload::PATH
については、別記事のRSpecでファイルがダウンロードされるまで待つを参照してください。
Capybara.register_driver :selenium do |app|
driver = Capybara::Selenium::Driver.new(app, browser: :chrome,
desired_capabilities: Selenium::WebDriver::Remote::Capabilities.chrome(
login_prefs: { browser: 'ALL' },
chrome_options: {
args: %w(headless disable-gpu window-size=1680,1050 blink-settings=imagesEnabled=false lang=ja),
},
)
)
bridge = driver.browser.send(:bridge)
path = "session/#{bridge.session_id}/chromium/send_command"
bridge.http.call(:post, path, cmd: 'Page.setDownloadBehavior',
params: {
behavior: 'allow',
downloadPath: WaitForDownload::PATH
})
driver
end
Capybara.javascript_driver = :selenium
visible: falseになるものの検証をどうにかする
# テーブルのデータを削除する
within "table tbody" do
expect(page).to have_content "1行目"
click_button "削除"
end
# ここで、テーブルが非表示ですと怒られて落ちる
within("table tbody") do
expect(page).to have_no_content "1行目"
end
こういうのは、以下のようにしました。
expect(find('table', visible: false)).not_to be_visible
visible: false
のものは見えないことというテスト内容になるので当たり前すぎておかしい気もしますが、行がないことを検証できるからとりあえずこうしてます。
いい書き方があったらアドバイスください。
DatePicker対策
DatePickerが表示されっぱなし問題に関しては、新たにfill_in_date
メソッドを定義して対応しました。
def fill_in_date(target, options={})
fill_in target, options
hide_datepicker
end
def hide_datepicker
page.execute_script("$('.datepicker').hide()")
end
Driver依存のものの対応
find('.foo').trigger('click')は使えないので、find('.foo').clickに全て変更しました。
# before
find('.foo').trigger('click')
# after
find('.foo').click
network_trafficは、PDFファイルなどへリダイレクトしたときに、URLが取れないため、network_trafficからURLを取得してちゃんとアクセスしたことを検証していたのですが、それができなくなったので、ファイルがダウンロードされているかどうかという観点に変更して対応しました(ダウンロードされている=そのURLにアクセスした)
ダイアログ系の対応
これは、RSpec + Capybaraでアラート/確認ダイアログを操作する場合は page.driver.browser.switch_to.alert.accept じゃなくて page.accept_confirm を使おうを参考に対応しました。
# before
click_link '削除'
# after
accept_confirm { click_link '削除' }
ざっくり置換していきましたが、大概大丈夫でした。