Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Capybara-Webkit to Headless Chrome: What to Know

Francisco Silva

February 23, 2024

Min Read
Capybara-Webkit to Headless Chrome: What to Know

Setting up the environment

Making the switch requires Chrome, of course, and a couple of dependencies to make sure everything's neatly integrated with Capybara.

This part's fairly straightforward, it shouldn't be much of hassle for you.

Installing Chrome

First things first, you need to install Chrome's latest stable version
In Linux, you can do so as such:


Installing Dependencies

Next up, you'll need two more tools:

  • ChromeDriver: Chrome's implementation of WebDrivers interface for remote control;
  • Selenium: needed to implement the automation and testing tools that you'll use with Capybara.

The gem webdrivers helps with the installation of ChromeDriver, automatically downloading, installing and keeping the driver up-to-date.

Then, you should add both to the project in your Gemfile, as shown below:


Don't forget to bundle install afterwards.

Setting up the drivers

Now, you just need to register the drivers, and configure them in spec_helper.rb:


This sets the default driver to :headless_chrome. If you'd like to watch the tests execute, just change it to :chrome in the last two lines.

You may also notice the enable-features tag in chrome's options, this is a temporary fix because of an issue in Chrome 74 in which cookies get randomly cleared during execution, which might cause Chrome to freeze.

According to Chromium’s bug tracker, this will be fixed in version v75.

If you're running the project in Docker, you may also need to add 'no-sandbox' to Chrome's options:


Cleaning things up

Now that that's taken care of, you can go ahead and remove capybara-webkit from the Gemfile, as well as any import or configuration you might have left (look for Capybara::Webkit).

blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo

Issues that might come up

For some projects, the tests may already be running smoothly after these steps, but for others that may not be the case. With a new browser and tools running the tests, new features and new problems also come up.

Capybara-webkit had a couple of useful but non-standard methods, and Selenium does not support all the methods Capybara has to offer. So this creates quite a gap, and any test that was using unsupported methods has to be patched.

  • Element#trigger is not supported by Selenium, although in most cases it should not be used, since it allows actions that the user will never be able to do.

Nevertheless, an easy workaround, if you’re triggering a click, would be to send the return keystroke to the element:

Or to click the element through javascript:

If you're dealing with another sort of event, you can use jQuery like so:

  • resize_window is renamed to resize_window_to in Selenium.
  • Reading JavaScript logs is a bit different. In the driver configuration you'll have to change the capabilities to something such as:


And then to read the logs, you can simply:

You can read more about Chrome's capabilities and options here.

  • Inspecting and setting the requests' headers is not supported in Selenium by default. This means that page.driver.header, page.response_headers and page.status_code aren't available.

Fixing this last point is somewhat of a challenge, but GitLab's solution is a great workaround. When faced with the same problem while porting their browser from PhantomJS to Chrome, they implemented a Middleware to intercept the requests' headers (more about it here).

To implement this solution, I simply included these files

lib/testing:

spec/support/helpers:

The namespaces have to be changed to match your project, and the 'concurrent-ruby' gem imported, as it is required in the middleware:

Remember to also import the files in spec_helper.rb:

And with all that setup, all you have to do to get the header's details is the following:

blue arrow to the left
Imaginary Cloud logo

A couple more tips

Now that everything is up and running, let me share a few more tips to take the most of Headless Chrome & ChromeDriver and avoid some common issues.

Animations can be a hassle, especially scroll animations

Capybara clicks on elements in the following way:

  1. Find DOM element;
  2. Calculate element coordinates;
  3. Click on said coordinates.

If the page is, for example, scrolling when the element is meant to be clicked, the coordinates might get outdated between step 2 and 3, meaning that the click will fall in the wrong place.

One possible solution for this problem is to wait for the animations to end, in this case I waited for the jQuery animation scrolling the body to stop:


Another option would be to disable jQuery animations in testing altogether, like this:

It's worth noting that disabling the animations can also improve the tests' performance.

If this fix doesn't work for you, and you really want to cancel all animations, check out this great article put together by the folks at Doctolib.

Fixed elements stealing your clicks

Capybara only clicks on elements if they are visible, so if you have a navbar or a popup obscuring an element, you might get an error like this:

Element is not clickable at point (100, 200). Another element would receive the click: ... (Selenium::WebDriver::Error::UnknownError)

To deal with this, you can close all popups on the page, and scroll down to the element before clicking it.

A simple method, implementing this idea, would be:


blue arrow to the left
Imaginary Cloud logo

Conclusion

Chrome's headless mode and ChromeDriver that comes with it have been strongly adopted for testing and automation, especially since QtWebkit was deprecated, and, with it, projects that were based on it, such as PhantomJS and capybara-webkit.

Even the maintainer of PhantomJS, the once popular headless browser has deprecated his project in favor of ChromeDriver. And thoughtbot, the creators of capybara-webkit, are starting to play around with ChromeDriver as well.

While capybara-webkit did the job for quite some time, the change to a more modern alternative (Chrome's headless mode) will make tests more reliable and stable. All of this with the additional advantage of using the same browser engine as most users, which makes the tests actions much more similar to what a real-life user interaction would look like.

Happy testing folks!

   

Ready for a UX Audit? Book a free call

Found this article useful? You might like these ones too!

blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
blue arrow to the left
Imaginary Cloud logo
Francisco Silva
Francisco Silva

Enthusiast of all things Front-End. In a committed love/hate relationship with CSS. Most often seen scraping data for side-projects he'll never finish.

Read more posts by this author

People who read this post, also found these interesting:

arrow left
arrow to the right
Dropdown caret icon