Capybara, Poltergeist and CSV Downloads

written on

It’s not so obvious how to test a scenario, where user clicks an export link and gets a CSV file download. Especially if the user is able to filter the generated CSV content before downloading.

Capybara’s Poltergeist engine is a wrapper for headless browser called PhantomJS. A basic Capybara spec to test the downloading might look like this:

“Basic CSV download spec”
1
2
3
4
5
6
7
8
9
10
11
12
13
it 'outputs valid csv with status' do
  login candy_user
  visit candy_invoices_path

  select 'sweets', :from => 'Type'
  click_button 'Apply filter'
  click_link 'Export Invoices'

  page.text.should eql(<<-CSV)
Customer;Month;Invoice #;Amount;Difference;Status;Type
Name 0;September 2002;INVOICE0;-;-;new;sweets
  CSV
end

We select a filter from a select box, apply the filter and download the CSV. The problem here is that Poltergeist starts a download when clicking the export link and the page.text contains the previous page, not the CSV one might expect. There seems to be no clean solution for this.

An easy way out is to register a different mime type for CSV files for the tests, so we can trick Poltergeist to render the CSV instead of downloading it:

“Basic CSV download spec”
1
2
3
4
5
6
7
8
9
before do
  Mime.send(:remove_const, :CSV)
  Mime::Type.register 'text/plain', :csv
end

after do
  Mime.send(:remove_const, :CSV)
  Mime::Type.register 'text/csv', :csv
end

And now our page.text contains the data we want.