appsignal

Automated screenshots using Capybara and Selenium

Thijs Cadier

Thijs Cadier on

Last week's AppSignal update included an updated interface design for every screen. This meant we had to update all screenshots on our homepage, to make sure they reflect the current state of the app. To reduce the vast amount of manual labor this takes, we decided to automate the process.

Luckily, we soon remembered that Selenium is capable of taking screenshots. We already use Selenium quite heavily through Capybara for our feature tests, so we set out to investigate if this could be a way to automate the task without introducing new moving parts. After some tinkering, we learned that our plan was feasible.

The API for taking a screenshot is straight-forward. Just set the browser window to the desired size, visit a page and take a screenshot:

Ruby
require 'capybara' Capybara.default_driver = :selenium page.driver.browser.manage.window.resize_to(1600, 1200) visit 'https://appsignal.com' page.save_screenshot(file)

This creates a png file in the specified location. There's a caveat if you want to take Retina screenshots though: the Chrome driver creates Retina screenshots, but only shoots the visible area. The Firefox driver on the other hand does shoot the entire page, but not in Retina resolution. And because not everyone on our team uses a Retina screen, they wouldn't be able to update the screenshots anyway.

After some searching, we found a solution to the problem in this Gist by chrism. Using this nifty hack we let Firefox blow up the page to double the normal size, right before taking a screenshot:

Ruby
page.driver.execute_script(' body = document.getElementsByTagName("body")[0]; body.style["transform-origin"] = "top left"; body.style["transform"] = "scale(2)"; ')

With the Retina screenshot of the entire page done, the next step is to crop it to the desired dimension using the convert CLI tool that's included with ImageMagick:

Ruby
`convert #{file} -crop #{1600 * 2}x#{ 800 * 2}+0+0 #{to_file}`

We have to double the dimensions, because ImageMagick does not know it's a Retina image. It just considers it to be 3200px by 1600px. The to_file directly points to the file in our assets folder.

Finally, we use pngquant to optimize the file. Our typical screenshots range from 220kB to 250kB, which means we should definitely minimize their sizes:

Ruby
`pngquant --force --output #{to_file} #{to_file}`

That's all there's to it. We wrote a Rakefile based on these commands that we can run again whenever we make design changes. You can find a Gist with the complete code right here.

Automating this process has already paid off, and will keep us sane in the future too. For now, enjoy the resulting images in all their Retina glory in the Tour and elsewhere!

Thijs Cadier

Thijs Cadier

Thijs is a co-founder of AppSignal who sometimes goes missing for months on end to work on our infrastructure. Makes sure our billions of requests are handled correctly. Holds the award for best drummer in the company.

All articles by Thijs Cadier

Become our next author!

Find out more

AppSignal monitors your apps

AppSignal provides insights for Ruby, Rails, Elixir, Phoenix, Node.js, Express and many other frameworks and libraries. We are located in beautiful Amsterdam. We love stroopwafels. If you do too, let us know. We might send you some!

Discover AppSignal
AppSignal monitors your apps