tl;dr
Prefer request specs over end-to-end tests (Capybara) to joyfully test file downloads!
Why?
Testing file downloads via Capybara is not easy and results in slow and fragile tests. We tried different approaches and the best one is just okay.
Tests for file downloads via Capybara ...
- ... are slow,
- ... are fragile (breaks CI, breaks if Selenium driver changes, ...),
- ... need workarounds for your special use cases,
- ... and have limitations.
How?
You should instead write request specs, because they ...
- ... are fast,
- ... are easy to write,
- ... are stable,
- ... and don't need workarounds.
describe Backend::ResourcesController do
describe '#index' do
it 'sends a xlsx export' do
# create your exportable data
create(:resource, ...)
# call your export endpoint
get '/backend/resources.xlsx'
# check that all expectations are fulfilled
expect(response).to be_ok
expect(response.headers['Content-Disposition']).to eq('attachment; filename="export.xlsx"')
expect(response.content_type).to eq('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
expect(RubyXL::Parser.parse_buffer(response.body)).to contain_all_expected_data
end
end
end
But!
Using a request spec doesn't test my export link or button!
Then write a small end-to-end test, e.g. that only checks that your link has the correct href
or that your link or button sends a request to the export endpoint.
How to test file downloads with Capybara
If you still want to write an end-to-end test with Capybara you should check out these cards:
Posted by Julian to makandra dev (2024-03-15 12:37)