Capybara: Most okayest helper to download and inspect files
Testing file download links in an end-to-end test can be painful, especially with Selenium.
The attached download_helpers.rb
provides a download_link
method for your Capybara tests. It returns a hash describing the download's response:
Copydetails = download_link('Download report') details[:disposition] # => 'attachment' or 'inline' details[:filename] # => 'report.txt' details[:text] # => file content as string details[:content_type] # => 'text/plain'
Features
Compared to other approaches this helper has many useful features:
- Works with both Selenium and Rack::Test drivers without limitations.
- Understands the
[download]
Archive and[download=filename.ext]
attributes. - Allows filename, disposition, content type and text content of a download link to be inspected in Ruby.
- Uses a filename from the response URL if no filename is sent by the server.
- Does not leave the current page when downloading.
- Works with both static files and
send_file
Archive . - Fails the test if the server doesn't respond with a HTTP 2xx status.
- Works in CI.
Limitations
- The helper cannot inspect downloads that are triggered or created by JavaScript.
For alternatives see Cucumber: Testing file downloads with Selenium.
Usage in RSpec feature specs
Copy the DownloadHelpers
module to spec/support
.
You can now include Archive the helper in all your feature specs:
CopyRSpec.configure do |config| config.include(DownloadHelpers, type: :feature) end
Usage in Cucumber scenarios
Copy the DownloadHelpers
module to features/support
.
Then include the helper in your scenarios and define some step definitions:
CopyWorld(DownloadHelpers) When('I download {string}') do |locator| @last_download = download_link(locator) end Then('the download should have the filename {string}') do |filename| expect(@last_download[:filename]).to eq(filename) end Then('the download should have the content type {string}') do |content_type| expect(@last_download[:content_type]).to eq(content_type) end Then /^the download should display as (attachment|inline)$/ do |filename| expect(@last_download[:disposition]).to eq(filename) end Then('the download should contain the following lines:') do |table| table.raw.each do |row| expect(@last_download[:text]).to include(*row), "Expected downloaded file to include \"#{row}\"" end end
You can now write steps like this:
CopyScenario: Download text file with Rack::Test When I go to the list of downloads And I download "download text" Then the download should display as attachment And the download should have the filename "test.txt" And the download should have the content type "text/plain" And the download should contain the following lines: | Line 1 | | Line 2 |
Your development team has a full backlog of feature requests, chores and refactoring coupled with deadlines? We are familiar with that. With our "DevOps as a Service" offering, we support developer teams with infrastructure and operations expertise.