Skip to content

Rodrigo Urubatan – About Code

Helping ruby developers to use the best tools for each job so they can solve hard problems, with less bugs and have more free time.

Menu
  • Home
  • My last presentations
  • About
  • Privacy Policy
Menu

Testing download contents with Cucumber+Capybara and chromedriver

Posted on 2021-06-05 by Rodrigo Urubatan

Working on a project these days where I work with Cucumber and Capybara, I had to test the contents of filed downloaded from the application, the downloads were being sent using “send_file” and chrome was adding them directly to the user Downloads folder, and the capybara tests had no access to the file contents after that.

My goal was to have the test code in Gherkin like this:

  1. When I click on "Download"
  2. Then the downloaded content should be:
  3.     """
  4.     id,name,age
  5.     1,John Doe,35
  6.     3,Mary Jane, 27
  7.     8,Little Joe, 9
  8.     """

But after cucumber executes

  1. When I click on "Download"

The file was downloaded, it doesn’t wait for the download to finish and the next step had no access to the downloaded file.

After some research I found out that I could configure a profile to Chrome before instantiating the browser in Capybara.

  1. Capybara.register_driver :chrome do |app|
  2.   profile = Selenium::WebDriver::Chrome::Profile.new
  3.   profile['download.default_directory'] = TestDownloadHelpers::PATH.to_s
  4.   Capybara::Selenium::Driver.new(app, browser: :chrome, profile: profile)
  5. end
  6. Capybara.javascript_driver = :chrome

In a simple explanation, this snippet sets a profile in the browser to be instantiated, configuring the default download directory to the tmp/downloads folder in my rails app.

This also mean that we can set ay number of other chrome properties as required, but we’ll get there sometime in the future ๐Ÿ˜€

Then I created this download helper in a new file under features/support

  1. module TestDownloadHelpers
  2.   TIMEOUT = 30
  3.   PATH    = Rails.root.join('tmp/downloads')
  4.  
  5.   extend self
  6.  
  7.   def downloads
  8.     Dir[PATH.join('*')].sort_by{ |f| File.mtime(f) }
  9.   end
  10.  
  11.   def download
  12.     downloads.last
  13.   end
  14.  
  15.   def download_content
  16.     wait_for_download
  17.     File.open(download, &:read)
  18.   end
  19.  
  20.   def wait_for_download
  21.     Timeout.timeout(TIMEOUT) do
  22.       sleep 0.1 until downloaded?
  23.     end
  24.   end
  25.  
  26.   def downloaded?
  27.     !downloading? && downloads.any?
  28.   end
  29.  
  30.   def downloading?
  31.     downloads.grep(/\.crdownload$/).any?
  32.   end
  33.  
  34.   def clear_downloads
  35.     FileUtils.mkdir_p(PATH)
  36.     FileUtils.rm_f(downloads)
  37.   end
  38. end
  39.  
  40. World(DownloadHelpers)
  41.  
  42. Before do
  43.   clear_downloads
  44. end
  45.  
  46. After do
  47.   clear_downloads
  48. end

An important point here is that the “downloading?” method uses the chrome partial download extension, so this entire solution only works for Chrome, if you need a multi browser solution this code will need a lot of updating.

With these small changes I was able to download files directly to the temp download folder, then check the downloaded file contents correctly with this simple snippet.

Then('the downloaded content should be:') do |content|
  text = download_content
  expect(text).to eq(content)
end

Making my initial test pass, and allowing me to completely test my downloads.

I hope this small snippets help someone else ๐Ÿ˜€

Please feel free to leave any comments bellow.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent posts

  • I see Dead Jobs everywhere (sidekiq DeadSet)
  • Quick tips that help: rails notes
  • Ruby 3.2.0 released with WASI, YJIT, RegExp improvements, …
  • Rubyconf Thailand quick summary and slides
  • Testing download contents with Cucumber+Capybara and chromedriver

Comments

  1. When Kubernetes is not the right choice? | Rodrigo Urubatan - About Code on Rails from “zero” to kubernetes – first pod
  2. When Kubernetes is not the right choice? | Rodrigo Urubatan - About Code on How to use docker to have an uniform development environment for your rails project
  3. Rails from "zero" to kubernetes โ€“ ingress reverse proxy | Rodrigo Urubatan - About Code on Rails from “zero” to kubernetes – a service to access your pod
  4. Rails from "zero" to kubernetes โ€“ horizontal autoscaling | Rodrigo Urubatan - About Code on Rails from “zero” to kubernetes – a service to access your pod
  5. Jeronimo on 6 Lessons From CrossFit That will help your developer career (Or any other career in the matter of fact)

Arquives

  • February 2023
  • January 2023
  • December 2022
  • June 2021
  • March 2020
  • January 2020
  • July 2019
  • June 2019
  • May 2019
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • February 2018
  • January 2018
  • November 2017
  • August 2015
  • August 2014
  • July 2014
  • August 2007

Categories

  • articles
  • cfp
  • firebase
  • gems
  • git
  • opinion
  • presentations
  • projects
  • rails6
  • ruby
  • Sem categoria
  • server-api
  • Uncategorized
© 2023 Rodrigo Urubatan – About Code | Powered by Minimalist Blog WordPress Theme