How to Test CSV File Download in Capybara and Rspec

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



Leave a reply



Submit