Waiting for watir-webdriver downloads (and determining the file name)

There was an interesting question on Stackoverflow recently about waiting for a file download whilst running a watir-webdriver test. Whilst it’s happy to download files, watir-webdriver won’t wait until they have downloaded, so essentially this is up to you to check.

The easiest way I have found to do this is, just before you download the file, check the contents of your download directory, then commence the download, and then wait until there’s an additional file in your downloads directory.

Once you have the additional file, you can read its file name to determine what was actually downloaded. This is useful for dynamic file names, or even static file names when you’re downloading multiples (as Firefox will add a (1), (2), (3) etc. to the file name).

The code to do this as follows:

require 'watir-webdriver'

file_name = nil
download_directory = "#{Dir.pwd}/downloads"
download_directory.gsub!("/", "\\") if Selenium::WebDriver::Platform.windows?
downloads_before = Dir.entries download_directory
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.folderList'] = 2 # custom location
profile['browser.download.dir'] = download_directory
profile['browser.helperApps.neverAsk.saveToDisk'] = "text/csv,application/pdf"
b = Watir::Browser.new :firefox, :profile => profile

b.goto 'https://dl.dropbox.com/u/18859962/hello.csv'

30.times do
  difference = Dir.entries(download_directory) - downloads_before
  if difference.size == 1
    file_name = difference.first 
  sleep 1
raise "Could not locate a new file in the directory '#{download_directory}' within 30 seconds" if not file_name
puts file_name

As usual, let me know if you know of a better way to do this.

Author: Alister Scott

Alister is an Excellence Wrangler for Automattic.

6 thoughts on “Waiting for watir-webdriver downloads (and determining the file name)”

  1. You may want to add:

    profile[‘app.update.enabled’] = false

    To the profile setup so that Firefox won’t display update dialogs if an update is available.

    BTW, the code works great for detecting downloads and waiting for them to finish before closing the browser.


  2. I used the example code almost verbatim under Windows and got a popup indicating an update to Firefox when WebDriver loaded Firefox. I could repeat it by re-running the script.

    I stopped the script and looked at about:config in the Firefox that WebDriver started and saw ‘app.update.enabled’ was true.

    Adding the command stopped the update popups….so maybe WebDriver and Windows has an issue with Firefox. Otherwise, things worked as expected.


  3. Hi Alister,
    Thanks a bunch, your code saved me a lot of time. Though sometimes, I am facing an issue:
    I am using an ‘ensure’ clause at the end to close browser. Now while I do get a new file_name and no error is raised, the file is actually not downloaded in the mentioned folder. My assumption is that a file is being created (which increments the count), but the browser gets closed before the entire download, hence removing the temporarily created file.
    Did you face this issue ever, or is there any workaround for it?

    Thanks in advance.


    1. some problem in chrome or firefox webdriver (like this http://code.google.com/p/chromedriver/issues/detail?id=130)
      do not allow write good tests for file downloads

      after I read next post

      I writed next ruby script for download files

      require ‘rubygems’
      require “net/http”
      require “uri”

      def download(_url, _download_path = ”)
      url = URI.parse _url
      http_object = Net::HTTP.new(url.host, url.port)
      http_object.use_ssl = true if (url.scheme == ‘https’ || url.port == 443)

      http_object.start.request_get(url.path) do |response|
      start_time = Time.now
      response[“Content-Disposition”] =~ /^.+?filename=”(.+?)”$/
      file_name = $1
      file = open(_download_path + file_name, ‘wb’)
      length = response[‘Content-Length’].to_i
      response.read_body do |fragment|
      done = (done || 0) + fragment.length
      progress = done.quo(length) * 100
      file_size = File.size(_download_path + file_name)/1024.0/1024.0
      puts “-“*80
      puts “Download time – #{Time.now – start_time}”
      puts “Download speed – #{file_size/(Time.now – start_time)} MB/s”
      puts “-“*80


      I hope this code will be useful for those who need test file download (not browser file download dialog window)


Comments are closed.