以下はコントローラーにあります:
respond_to do |format|
format.csv { send_data as_csv, type:'text/csv' }
end
仕様:
click_link 'Download CSV'
page.driver.browser.switch_to.alert.accept
expect( page ).to have_content csv_data
しかし、これはうまくいきません:
Failure/Error: page.driver.browser.switch_to.alert.accept
Selenium::WebDriver::Error::NoAlertPresentError: No alert is present
[ファイルの保存]ダイアログボックスが表示されますが、「アラート」ダイアログではないようです。
「OK」をクリックしてカピバラにデータを表示させる方法は?
CollectiveIdea および別のソースから転載。
OSXで動作します。 Firefox 34.0.5
スペック:
describe 'Download CSV' do
let( :submission_email ){ '[email protected]' }
let( :email_csv ){ "id,email,created_at\n1,#{ submission_email }," }
specify do
visit '/emails'
expect( page ).to have_content 'Email Submissions'
click_on 'Download CSV'
expect( DownloadHelpers::download_content ).to include email_csv
end
end
仕様ヘルパー:
require 'shared/download_helper'
Capybara.register_driver :Selenium do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.dir'] = DownloadHelpers::PATH.to_s
profile['browser.download.folderList'] = 2
# Suppress "open with" dialog
profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/csv'
Capybara::Selenium::Driver.new(app, :browser => :firefox, :profile => profile)
end
config.before( :each ) do
DownloadHelpers::clear_downloads
end
shared/download_helper.rb:
module DownloadHelpers
TIMEOUT = 1
PATH = Rails.root.join("tmp/downloads")
extend self
def downloads
Dir[PATH.join("*")]
end
def download
downloads.first
end
def download_content
wait_for_download
File.read(download)
end
def wait_for_download
Timeout.timeout(TIMEOUT) do
sleep 0.1 until downloaded?
end
end
def downloaded?
!downloading? && downloads.any?
end
def downloading?
downloads.grep(/\.part$/).any?
end
def clear_downloads
FileUtils.rm_f(downloads)
end
end
私は同様のものを実装しようとし、何時間も費やしました。最後に私はいくつかの解決策を持っています、おそらくあなたにも適しています。
Gemfile:
#source 'https://rubygems.org'
gem 'Rails', '4.2.2'
gem 'bcrypt', '3.1.7'
gem 'bootstrap-sass', '3.2.0.0'
gem 'faker', '1.4.2'
gem 'carrierwave', '0.10.0'
gem 'mini_magick', '3.8.0'
gem 'fog', '1.36.0'
gem 'will_paginate', '3.0.7'
gem 'bootstrap-will_paginate', '0.0.10'
gem 'sass-Rails', '5.0.2'
gem 'uglifier', '2.5.3'
gem 'coffee-Rails', '4.1.0'
gem 'jquery-Rails', '4.0.3'
gem 'turbolinks', '2.3.0'
gem 'jbuilder', '2.2.3'
gem 'sdoc', '0.4.0', group: :doc
gem 'rename'
gem 'sprockets', '3.6.3'
gem 'responders', '~> 2.0'
gem 'inherited_resources'
group :development, :test do
gem 'sqlite3', '1.3.9'
gem 'byebug', '3.4.0'
gem 'web-console', '2.0.0.beta3'
gem 'spring', '1.1.3'
end
group :test do
gem 'minitest-reporters', '1.0.5'
gem 'mini_backtrace', '0.1.3'
gem 'guard-minitest', '2.3.1'
gem 'capybara', '2.8.1'
gem 'rspec', '3.5.0'
gem 'rspec-Rails', '~> 3.4'
gem 'cucumber-Rails', :require => false
gem 'shoulda-matchers', '~> 3.0', require: false
gem 'database_cleaner'
gem 'factory_girl_Rails', '~> 4.5.0'
end
spec/Rails_helper.rb
ENV['Rails_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/Rails'
require 'shoulda/matchers'
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :Rails
end
end
config.use_transactional_fixtures = false
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.filter_Rails_from_backtrace!
end
spec/spec_helper.rb
ENV["Rails_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/Rails'
require 'capybara/rspec'
require 'capybara/Rails'
require 'download_helper'
Capybara.register_driver :Selenium do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.dir'] = DownloadHelpers::PATH.to_s
profile['browser.download.folderList'] = 2
profile['browser.helperApps.neverAsk.saveToDisk'] = 'text/csv'
Capybara::Selenium::Driver.new(app, :browser => :firefox, :profile => profile)
end
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_Host_groups
config.include Capybara::DSL
=begin
config.filter_run_when_matching :focus
config.example_status_persistence_file_path = "spec/examples.txt"
config.disable_monkey_patching!
if config.files_to_run.one?
config.default_formatter = 'doc'
end
config.profile_examples = 10
config.order = :random
Kernel.srand config.seed
=end
end
test/test_helper.rb
ENV['Rails_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'Rails/test_help'
require 'capybara/Rails'
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
include ApplicationHelper
def is_logged_in?
!session[:user_id].nil?
end
# Logs in a test user.
def log_in_as(user, options = {})
password = options[:password] || 'password'
remember_me = options[:remember_me] || '1'
if integration_test?
post login_path, session: { email:user.email, password: password, remember_me: remember_me }
else
session[:user_id] = user.id
end
end
private
# Returns true inside an integration test.
def integration_test?
defined?(post_via_redirect)
end
end
class ActionDispatch::IntegrationTest
# Make the Capybara DSL available in all integration tests
include Capybara::DSL
# Reset sessions and driver between tests
# Use super wherever this method is redefined in your individual test classes
def teardown
Capybara.reset_sessions!
Capybara.use_default_driver
end
end
spec/download_helper.rb
module DownloadHelpers
TIMEOUT = 1
PATH = Rails.root.join("tmp/downloads")
extend self
def downloads
Dir[PATH.join("*")]
end
def download
downloads.first
end
def download_content
wait_for_download
File.read(download)
end
def wait_for_download
Timeout.timeout(TIMEOUT) do
sleep 0.1 until downloaded?
end
end
def downloaded?
!downloading? && downloads.any?
end
def downloading?
downloads.grep(/\.part$/).any?
end
def clear_downloads
FileUtils.rm_f(downloads)
end
end
spec/mpodels/spec.rb
describe 'Download file' do
specify do
visit '/createfile'
click_on 'create file'
page.response_headers['Content-Type'].should == "text/csv"
header = page.response_headers['Content-Disposition']
header.should match /^attachment/
header.should match /filename=\"temp.csv\"$/
end
end
rack_test
ドライバー(javascript /ブラウザーなし)を使用している場合、これを行う別の方法を見つけました:
DOWNLOAD_CACHE_PATH = Rails.root.join("tmp/downloaded_file").to_s
setup do
File.delete(DOWNLOAD_CACHE_PATH)
end
test "download file" do
visit download_file_path
# simulate file download
File.write(DOWNLOAD_CACHE_PATH, page.body)
csv = CSV.open(DOWNLOAD_CACHE_PATH)
# assert something on the csv data
end
ブラウザーによっては、そのブラウザーのプロファイルが必要になります。そのプロファイルへの保存を要求するプロパティを無効にすることをお勧めします。