Edited at

[rails] system specにおけるtake_screenshotの問題を雑に修正する

More than 1 year has passed since last update.

rspec-rails 3.7でsystem specが追加されてfailしたら自動でschreenshotを取ってくれて便利なんですが、いくつか問題があったので雑に修正しました。

注意) 当記事では著者が書いたコードを指して(パッチの当て方や文字列の末尾を取得しているところなどを)「雑に」と言っています。

参考にさせていただいた記事を指しているわけでは決してありません。

Capybara+headless-chrome でフルサイズのスクリーンショットを撮るは素晴らしい記事です。


ファイル名が長すぎてエラーになる。

rspecのネストが深くなるとschreenshotのファイル名が長くなりすぎてエラーが発生してしまいます。

https://github.com/rails/rails/issues/32346

こちらでissueがあがっているんですが、5.2.1 milestone から外されてしまい、対応は少し待たないといけないようです。

仕方ないのでモンキーパッチで雑に対応します。

# frozen_string_literal: true

require 'action_dispatch/system_testing/test_helpers/screenshot_helper'

module ActionDispatch::SystemTesting::TestHelpers::ScreenshotHelper
LINUX_MAX_FILE_NAME_LENGTH = 255
EXT_NAME = '.png'

# https://github.com/rails/rails/blob/a3ecf4ff1dbb92259e1627bdd09546211f25d906/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb#L24
def take_screenshot
save_image
puts display_image
rescue Errno::ENAMETOOLONG
max_length = LINUX_MAX_FILE_NAME_LENGTH - EXT_NAME.length
omitted_image_name = image_name[- max_length, max_length]

path = Rails.root.join("tmp/screenshots/#{omitted_image_name}#{EXT_NAME}")
page.save_screenshot(path)

puts "[Screenshot]: #{path}"
end
end

このファイルをspec/supportにおいて、読み込んであげればOKです。


headless-chrome でフルサイズのスクリーンショットが撮れない

フルサイズのスクリーンショットを取るためにはcapybaraのsave_screenshotfull: trueのオプションを与える必要があるのですが、何故かそうなっていません。↓

https://github.com/rails/rails/blob/a3ecf4ff1dbb92259e1627bdd09546211f25d906/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb#L54

しかも、現状 headless-chrome だとfull: trueのオプションを与えてもフルサイズのスクリーンショットが撮れないようです。

こちらの記事(Capybara+headless-chrome でフルサイズのスクリーンショットを撮る)を参考に更にモンキーパッチを当てます。

# frozen_string_literal: true

require 'action_dispatch/system_testing/test_helpers/screenshot_helper'

module ActionDispatch::SystemTesting::TestHelpers::ScreenshotHelper
LINUX_MAX_FILE_NAME_LENGTH = 255
EXT_NAME = '.png'

# https://github.com/rails/rails/blob/a3ecf4ff1dbb92259e1627bdd09546211f25d906/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb#L24
def take_screenshot
resize_window_to_full_screen

save_image
puts display_image
rescue Errno::ENAMETOOLONG
max_length = LINUX_MAX_FILE_NAME_LENGTH - EXT_NAME.length
omitted_image_name = image_name[- max_length, max_length]

path = Rails.root.join("tmp/screenshots/#{omitted_image_name}#{EXT_NAME}")
page.save_screenshot(path)

puts "[Screenshot]: #{path}"
end

private

# https://qiita.com/g-fujioka/items/091c400814800f1280ff
def resize_window_to_full_screen
# rubocop:disable Metrics/LineLength
width = Capybara.page.execute_script('return Math.max(document.body.scrollWidth , document.body.offsetWidth , document.documentElement.clientWidth , document.documentElement.scrollWidth , document.documentElement.offsetWidth);')
height = Capybara.page.execute_script('return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);')
# rubocop:enable Metrics/LineLength

Capybara.current_session.driver.browser.manage.window.resize_to(width, height)
end
end

これでフルサイズのスクリーンショットが撮れるようになりました。

快適!