_ruby
TL;DR - Show Me The Code
require 'selenium-webdriver'
require 'rspec/expectations'
require 'uuid'
require 'fileutils'
include RSpec::Matchers
def setup
@download_dir = File.join(Dir.pwd, UUID.new.generate)
FileUtils.mkdir_p(@download_dir)
options = Selenium::WebDriver::Firefox::Options.new
options.add_preference('browser.download.dir', @download_dir)
options.add_preference('browser.download.folderList', 2)
options.add_preference('browser.helperApps.neverAsk.saveToDisk',
'image/jpeg, application/pdf, application/octet-stream')
options.add_preference('pdfjs.disabled', true)
@driver = Selenium::WebDriver.for(:firefox, options: options)
end
def teardown
@driver.quit
FileUtils.rm_rf(@download_dir)
end
def run
setup
yield
teardown
end
run do
@driver.get('https://the-internet.herokuapp.com/download')
download_link = @driver.find_element(css: '.example a')
download_link.click
# Wait up to 5 seconds for the file to download
wait = Selenium::WebDriver::Wait.new(timeout: 5)
wait.until { Dir.glob("#{@download_dir}/*").any? }
files = Dir.glob("#{@download_dir}/**")
expect(files.size).to eq 1
file = files.first
expect(File.size(file)).to be > 0
end
Code Walkthrough
Importing Libraries
Lines 1 to 4 are pulling in our requisite libraries (e.g., selenium-webdriver
to drive the browser,
rspec/expectations
and RSpec::Matchers
for assertions, uuid
to help create a uniquely named temporary
download directory, and fileutils
to create & destroy the temp directory) and wiring up our setup
method.
Setup and Teardown
Lines 8 to 24 are setting up and tearing down the test. Our setup
method is where the magic is happening in this
example. In it, we're creating a uniquely named temp directory and storing the absolute path of it in an instance
variable that we'll use throughout this file.
We're also setting a few browser preferences (for Firefox in this case) and plying it with the necessary configuration parameters to make it automatically download the file where we want. Here's a breakdown of each of them:
browser.download.dir
accepts a string. This is how we set the custom download path. It needs to be an absolute path.browser.download.folderList
takes a number. It tells Firefox which download directory to use.2
tells it to use a custom download path, wheras1
would use the browser's default path, and0
would place them on the Desktop.browser.helperApps.neverAsk.saveToDisk
tells Firefox when not to prompt for a file download. It accepts a string of the file's MIME type. If you want to specify more than one, you do it with a comma-separated string.pdfjs.disabled
is for when downloading PDFs. This overrides the sensible default in Firefox that previews PDFs in the browser. It accepts a boolean.
These preferences are then passed into our instance of Selenium.
In teardown
we make sure to clean up the temp directory after closing the browser. Other than that, it's business
as usual.
The run
method is a custom method that we've defined to execute our test. It's a simple wrapper around the setup
and teardown
methods. We're using it to keep our test code clean and easy to read.
The Test
Lines 33 to 42 are the test itself.
After loading the page we find the first download link and click it. The click triggers an automatic download to
the temp directory created in setup
. After that, we perform some rudimentary checks to make sure the directory
isn't empty and that the file isn't empty either.
Executing the Test
Before executing the test, we need to make sure the required dependencies are declared on the Gemfile
file.
Toggle to see the Gemfile
file.
source 'https://rubygems.org'
gem 'rspec', '~> 3.10'
gem 'selenium-webdriver', '~> 4.24.0'
gem 'uuid'
Finally, we can run the test by executing ruby download.rb
from the command-line.