Capybara
A DSL for testing web applications
Now, we want to test a Ruby application, and we don’t really want to write a lot of Javascript code in order to do so.
And the Javascript code we would have to write actually is quite a bit of a hassle, unless we use a bunch of libraries. For example, it’s not even very easy to click on a link in a browser through plain Javascript. That’s because the document object model (DOM), as defined by the W3C is quite an odd construct.
The code for clicking on a link might look something like this:
var element = document.querySelector("a[href='/location.html']");
var event = document.createEvent("MouseEvents");
event.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
element.dispatchEvent(event);
That’s right. One does not just “click”. One creates a mouse event, sets it up with tons of options, and then “dispatches” it on the element.
Luckily there are Ruby libraries to help with this kind of stuff. The probably most widely used one is Capybara.
That’s right. Capybara maybe has the most badass mascot animal of all open source libraries.
It also defines a DSL for describing interactions with web pages. The DSL includes handy methods such as:
visit "/members" # go to a URL
click_on "Add member" # click on a link
fill_in "Name", with: "Monsta!" # fill in a form field
click_on "Submit" # submit the form
Now that looks a little more handy.
With Capybara you can easily inspect the HTML of a page, find elements
(remember how we added another gem rspec-html-matchers
? Capybara brings
similar functionality), interact with the page by clicking around, filling in
form fields, submitting forms etc. You can also evaluate Javascript on the page
(in order to simulate certain things), work with native browser alert windows,
and a lot more. You can even take screenshots, even though there’s no browser
window.
How does Capybara know how to talk to Phantom.js though?
As mentioned there are a lot of different headless browsers, and Capybara can
talk to some of them. In order to do so Capybara uses “drivers”. And the driver
for talking to Phantom.js is called Poltergeist,
because a name like CapybaraPhantomjsDriver
would have been too boring.
Anyway, we want to install both gems:
$ gem install capybara poltergeist
Let’s try it out!
Create a file capybara.rb
and add the following:
require 'capybara/poltergeist'
Capybara.default_driver = :poltergeist
browser = Capybara.current_session
browser.visit 'http://rubymonstas.org'
puts browser.html
Awesome. Again, that prints out the HTML of our homepage.
Now, let’s click on a link:
browser = Capybara.current_session
browser.visit 'http://rubymonstas.org'
browser.click_on 'Ganz oben office'
puts browser.text
That prints out:
Where we meet How to get to the office space where we meet (the former Travis CI office).
...
As you can see we’ve successfully navigated to another page, and now look at the plain text of that other.
If we want to make our test not depend on the link text (because that might change at any time) then we can also use XPath or CSS selectors.
CSS selectors are a little more common because many developers already know them from CSS and Javascript (e.g. JQuery). XPath selectors on the other hand are even more powerful.
For example, this CSS selector says “select the a
tag that has the attribute
href="/location.html"
.
browser.find('a[href="/location.html"]').click