LoginSignup
7
8

More than 3 years have passed since last update.

capybaraでファイルダウンロードをテストする

Posted at

Capybaraでファイルをダウンロードするテストを書いたので備忘録

Capybaraでファイルをダウンロードすると、デフォルトのダウンロードディレクトリ(~/Downloads)にファイルがダウンロードされるため、テストがしづらい。
設定を追加して、システムテストを実行しやすくする。

まずは、Capybaraで利用するWebDriverにダウンロードディレクトリを設定する

# spec/support/capybara.rb
# frozen_string_literal: true

require 'capybara/rspec'

# 読みこんで、Capybara.current_driverの初期化を済ませる
require 'action_dispatch/system_test_case'

Capybara.register_driver(:pc_headless) do |app|
  options = Selenium::WebDriver::Chrome::Options.new
  options.headless!

  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end

RSpec.configure do |config|
  config.before(type: :system) do |example|
    driven_by(:pc_headless)

    # ここ。ダウンロード先を指定する
    page.driver.browser.download_path = CapybaraDownloadsHelper.path
  end
end

続いて、ダウンロードファイルをテストで利用するためのヘルパーを用意する

# spec/support/xxx_helper.rb
# frozen_string_literal: true

# Capybaraでダウンロードしたファイルを管理する
module CapybaraDownloadsHelper
  PATH = Rails.root.join('tmp', 'data', 'downloads').to_s.freeze

  class << self
    # ダウンロード先のディレクトリ
    #
    # @return [String]
    def path
      File.join(PATH, Thread.current.object_id.to_s)
    end

    # ダウンロードしたファイル一覧を返す
    #
    # @return [Array<String>]
    def files
      Dir[File.join(path, '*')]
    end

    # ダウンロードが完了したか
    #
    # @return [boolean] ダウンロードが完了していればtrue
    def downloaded?
      files.grep(/\.crdownload$/).none? && files.any?
    end

    # ダウンロードしたファイルを削除する
    #
    # @return [void]
    def delete_all
      FileUtils.rm_f(files)
    end
  end
end

RSpec.configure do |config|
  config.before(:all) do
    FileUtils.mkdir_p(CapybaraDownloadsHelper.path)
  end

  config.after(:all) do
    FileUtils.rm_rf(CapybaraDownloadsHelper.path)
  end

  config.before do
    CapybaraDownloadsHelper.delete_all
  end
end

これで、簡単にテストを行うことができるようになる。

RSpec.describe 'download', type: :system do
  it 'downloads file' do
    find('#download_link').click

    Timeout.timeout(10.second) do
      loop do
        break if CapybaraDownloadsHelper.downloaded?
      end
    end

    file = CapybaraDownloadsHelper.files[0]
    expect(file).to test_something
  end
end
7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8