こんにちは。メドピアのRuby(Rails)化をお手伝いしている@willnetです。最近大阪Ruby会議02に妻子を連れて参加したのですが、👶が行き帰りの新幹線に合わせて寝てくれたおかげで大変スムーズに移動できました。
さて、以前poltergeistからheadless chromeへ移行する時に気をつけることというブログエントリを書きました。
その中で、ファイルダウンロードのテストをheadless chromeで実行するための設定について書いています。しかし、この設定では最近のchrome(chromedriver)では動かなくなってしましました。このエントリでは最新のやり方について紹介します。
これまでの設定例
以前のブログエントリに掲載したコードを一部再掲します。
Capybara.register_driver :headless_chrome 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=1900,1200 lang=ja no-sandbox disable-dev-shm-usage), } ) ) 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: DownloadHelper::PATH.to_s, } ) driver end Capybara.javascript_driver = :headless_chrome
これまで、headless chromeでのファイルダウンロード機能はデフォルトで無効だったので、有効にするために上記のようなコードを書く必要がありました。
しかし最近のchromedriver(v77以降)の仕様変更により、上記のコードは動かなくなってしまいます。
新しいchromedriverでは、上記のような設定をせずともデフォルトでファイルのダウンロードが有効になっています。このとき、デフォルトではカレントディレクトリがダウンロード先になります。上記の設定がこのデフォルトの挙動に置き換わってしまうため、DownloadHelper::PATH
にファイルがダウンロードされることを期待しているすべてのダウンロード関連のテストが失敗するようになります。
(追記)この現象はv77時点ではlinux版のchromedriverでのみ起こるようです。macの場合はこれまでの書き方か、後述しているSelenium::WebDriver::Chrome::Driver#download_path=
を利用した書き方でのみテストが通り、次の解決策で紹介した書き方だとテストが失敗します(ややこしいですね…)。
解決策
次のように修正すると、ダウンロード先をDownloadHelper::PATH
で設定したディレクトリに変更できます。
Capybara.register_driver :headless_chrome do |app| browser_options = Selenium::WebDriver::Chrome::Options.new browser_options.args << '--headless' browser_options.args << '--disable-gpu' browser_options.args << '--no-sandbox' browser_options.args << '--disable-dev-shm-usage' browser_options.args << '--lang=ja' browser_options.args << '--window-size=1920,1200' # この行がメインの変更 browser_options.add_preference(:download, default_directory: DownloadHelper::PATH.to_s) Capybara::Selenium::Driver.new( app, browser: :chrome, options: browser_options ) end Capybara.javascript_driver = :headless_chrome
以前の設定と比べて、selenium-webdriverに対するオプションの渡し方が新しいものに変わっています。が、そこは本筋ではないので置いておいて、browser_options.add_preference(:download, default_directory: DownloadHelper::PATH.to_s)
がメインの変更点です。これによりchromedriverでのダウンロードディレクトリの設定を変更することができます。
ちなみにselenium-webdriverには3.13.0以降でSelenium::WebDriver::Chrome::Driver#download_path= メソッドが生えているため、v77未満のchromeを利用している場合は、bridge = driver.browser.send(:bridge) ...
のようにせずとも次のように書くことができるようになっています(内部でやっていることは一緒です)。こちらのほうが簡潔で良い感じですね。
# 略 driver = Capybara::Selenium::Driver.new( app, browser: :chrome, options: browser_options ) driver.browser.download_path = DownloadHelper::PATH.to_s driver end # 略
お手持ちのchromeのバージョンに合わせてご利用ください。
謝辞
このエントリで紹介した内容について、@jnchitoさんに情報提供いただきました。ありがとうございました(\( ⁰⊖⁰)/)
@netwillnet 以下の記事をありがたく参考にさせてもらっているプロジェクトがあるのですが、Chrome 77になってからCircle CIが落ちるようになりました。https://t.co/I4dnceNqwy
— Junichi Ito (伊藤淳一) (@jnchito) September 17, 2019
どうやら77 + Linux環境でのダウンロードパスの指定方法が変わったみたいです。(続く)
(☝︎ ՞ਊ ՞)☝︎是非読者になってください
メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!
■募集ポジションはこちら
https://medpeer.co.jp/recruit/entry/
■開発環境はこちら