How to test CSV file download in Capybara and RSpec?
Adapted from CollectiveIdea and another source.
Works on OSX. Firefox 34.0.5
Spec:
describe 'Download CSV' do
let( :submission_email ){ 'foo@example.com' }
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
Spec helper:
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
Rspec test CSV file download
At your describe block call render_views
as in:
describe Admin::ApplicationsController do
render_views
... # all the other code
end
Calling render_views
instructs RSpec to render the view contents inside a controller spec. This is turned off by default because when you're running controller specs you usually don't care about the view contents and this makes your tests run faster.
You can see the official documentation for the latest Rails version here.
Is it possible to test file download in Poltergiest without using selenium or chrome driver
The latest released PhantomJS doesn't support downloading files, so you are limited to the method, you linked to, of checking response_headers. You mention that it isn't feasible because the filename has a timestamp in it, but as long as you're not trying to verify the exact value of the timestamp portion of it you can use the match
matcher with a regex. Something like
page.response_headers['Content-Disposition'].should match(/filename="file-\d+\.pdf"/)
should match filenames like file-1234.pdf
Test file download with Capybara and Cucumber
I have done it in my recent project as shown below
Given Download folder for export is empty
And Joe clicks "Download Csv" button
Then The contents of the downloaded csv should be:
|TEAM_ID | TEAM_EXTERNAL_ID | TYPE | REG_OPTION | TEAM_REG_BRACKET | RACE_NAME | WAVE | BIB | BRACKET | STATUS | TEAM_NAME | TEAM_TYPE | ATHLETE_COUNT | MIN_MEMBERS | MAX_MEMBERS | TEAM_MEMBERS |
| 8 | | TEAM | 10k Aggregate | N/A | 10k | Universal | 208 | Overall | DNF | Team 08 | Aggregate |0 | | | |
And the capybara for this cucumber will be like
Given(/^Download folder for export is empty$/) do
FileUtils.rm_rf('/home/vagrant/Downloads/')
end
And(/^(\S*) clicks "([^"]*)" button$/) do |user, arg|
button = find_button(arg)
button.click
end
And /^The contents of the downloaded csv should be:$/ do |table|
for i in 0..5
if(Dir.glob('/home/vagrant/Downloads/*.csv'))
break;
end
sleep(1); // if not found wait one second before continue looping
end
if(Dir.glob('/home/vagrant/Downloads/*.csv'))
Dir['/home/vagrant/Downloads/*'].each do |file_name|
arr = CSV.read(file_name, :col_sep => "\t", :row_sep => "\r\n", encoding: "UTF-16:UTF-8")
table.raw[0...table.raw.length].each_with_index do |row, row_index|
row.each_with_index do |value, index|
if arr[row_index][index] == nil
arr[row_index][index] = ""
end
if index == 1
else
puts "#{index}" + 'Value in table = ' + "#{value} + 'Value in file' + #{arr[row_index][index]}"
value.should eq arr[row_index][index]
end
end
end
end
else
puts "/home/vagrant/Downloads/*.csv file not found!"
end
end
Hope this resolves you problem for downloading CSV and verifying its contents too :)
Related Topics
Handling Exceptions Raised in a Ruby Thread
Rails 3 Install Error: "Invalid Value for @Cert_Chain"
Is Everything an Object in Ruby
Add Space After Commas Only If It Doesn't Already
How to Convert a String to Lower or Upper Case in Ruby
How to Round a Time Down to the Nearest 15 Minutes in Ruby
Create Directory If It Doesn't Exist with Ruby
Difference Between Resource and Resources in Rails Routing
What Exactly "Config.Assets.Debug" Setting Does
Missing Host to Link To! Please Provide the :Host Parameter, for Rails 4
Ruby Regex Error: Incompatible Encoding Regexp Match (Ascii-8Bit Regexp with Utf-8 String)
Form_For Error Messages in Ruby on Rails
Chaining Methods Using Symbol#To_Proc Shorthand in Ruby