Madogiwa Blog

主に技術系の学習メモに使っていきます。

Ruby on Rails: capybara-playwright-driverでsystem specを実行するMEMO📝

system specをseleniumではなくcapybara-playwright-driverを使ってplaywrightで動かしてみたのでメモ📝

github.com

playwrightに関しては以下に以前まとめていたので貼り付けておく。

madogiwa0124.hatenablog.com

準備

必要なライブラリをinstallします。

Gemfile

  gem "capybara-playwright-driver"
  gem "playwright-ruby-client"

package.json

    "@playwright/test": "1.41.1",

以下を実行してplaywrightで利用するbrowsersをinstallします。

$ npx playwright install

playwright driverを利用する

RSpec.configuredriven_by:playwrightを指定するだけでplaywrightでsystem specが実行されます🤖

# NOTE: 推奨値に変更
# > It is recommended to set the timeout to 15-30 seconds for Playwright driver.
# > https://playwright-ruby-client.vercel.app/docs/article/guides/rails_integration#update-timeout
Capybara.default_max_wait_time = 15

RSpec.configure do |config|
  config.before(:each, type: :system) do |example|
    example.metadata[:js] ? driven_by(:headless_chrome) : driven_by(:rack_test)
    if example.metadata[:js]
      headless = ENV.fetch("PLAYWIGHT_HEADLESS", "true") == "true"
      browser = ENV.fetch("PLAYWIGHT_BROWSER_TYPE", :chromium).to_sym
      driven_by(:playwright, options: {browser_type: browser, headless: headless})
    else
      driven_by(:rack_test)
    end
  end

スクリーン録画やトレースを利用する

またplaywrightのtraceや録画をcallbackを活用することで取得できるようだったので、

以下のような感じでtmp配下に配置するようにしてみました。

def save_playwright_screen_record(
  example,
  save_dir: "tmp/capybara/screen_records",
  file_name_proc: ->(example) { example.full_description.split(" ").join("_") }
)
  Capybara.current_session.driver.on_save_screenrecord do |video_path|
    file_name = "#{file_name_proc.call(example)}#{Pathname.new(video_path).extname}"
    FileUtils.mkdir_p Rails.root.join(save_dir)
    FileUtils.cp video_path, Rails.root.join(save_dir, file_name)
  end
end

def save_playwright_trace(
  example,
  save_dir: "tmp/capybara/traces",
  file_name_proc: ->(example) { example.full_description.split(" ").join("_") }
)
  Capybara.current_session.driver.on_save_trace do |trace_zip_path|
    file_name = "#{file_name_proc.call(example)}#{Pathname.new(trace_zip_path).extname}"
    FileUtils.mkdir_p Rails.root.join(save_dir)
    FileUtils.cp trace_zip_path, Rails.root.join(save_dir, file_name)
  end
end
RSpec.configure do |config|
  config.before(:each, type: :system) do |example|
    example.metadata[:js] ? driven_by(:headless_chrome) : driven_by(:rack_test)
    if example.metadata[:js]
      headless = ENV.fetch("PLAYWIGHT_HEADLESS", "true") == "true"
      browser = ENV.fetch("PLAYWIGHT_BROWSER_TYPE", :chromium).to_sym
      driven_by(:playwright, options: {browser_type: browser, headless: headless})
+    save_playwright_trace(example) if example.metadata[:trace]
+    save_playwright_screen_record(example) if example.metadata[:screen_record]
    else
      driven_by(:rack_test)
    end
  end

ビデオの保存はdriven_by(:playwright, options: {browser_type: browser, headless: headless, record_video_dir: "tmp/capybara/screen_record"})のようにrecord_video_dirを指定するだけも任意のディレクトリに配置できるがファイル名をいい感じにしたかったのでゴリっと書いてみた🦍 (もっといいやり方ありそうだけど。。。)

we can record the videos without specifying record_video_dir explicitly or preparing a temporary directory. capybara-playwright-driver automatically prepare and set record_video_dir internally. https://playwright-ruby-client.vercel.app/docs/article/guides/recording_video#using-screen-recording-from-capybara-driver

おわりに

capybara-playwright-driver 簡単に乗り換えられてありがたい・・・!!🙏✨

参考

note.com