How to test file download with rspec 1.3.0/capybara 0.3.9/selenium? How to test file download with rspec 1.3.0/capybara 0.3.9/selenium? selenium selenium

How to test file download with rspec 1.3.0/capybara 0.3.9/selenium?


I tested that when I click on a link I should receive *.pdf file.

click_on "link_to_pdf"page.response_headers['Content-Type'].should eq "application/pdf"

It doesn't work with selenium, so better to specify not javascript driver. I am sure that it works with RackTest.

feature "Download pdf", :js => false doend


I have tried to implement something similar and spend lots of hours. Finally I have some solution, maybe it fit for you as well.

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: :docgem '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'endgroup :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  endendconfig.use_transactional_fixtures = falseActiveRecord::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)endRSpec.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=endend

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)        endendclass 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  endend

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)  endend

spec/mpodels/spec.rb

  describe 'Download file' do    specify do      visit '/createfile'      click_on 'create file'            page.response_headers['Content-Type'].should == "text/lfile"            header = page.response_headers['Content-Disposition']            header.should match /^attachment/            header.should match /filename=\"temp.txt\"$/       end    end