Thursday, August 18, 2011

Migrating from Webrat to Capybara

This post is a collection of tips and hints on how to migrate from Webrat to Capybara. I am assuming RSpec syntax in the examples.

Installation

gem install capybara
or add
gem capybara 
to your Gemfile and run 'bundle'.
Complete instructions are provided here


Changes in syntax

Selectors for the content of an element

before:
response.should have_selector("title", :content => "My Title")
after:
response.body.should have_selector("head title", :text => "My Title")
Update response is not a capybara object but an RSpec one used in controller specs, use page for integration tests.

Value of an input field

before:
response.should have_selector("input", :value => "input field value")
after:
response.body.should have_selector("input[value='input field value']")

Link with url and content

before:
response.should have_selector("a", :href => "/url/path", :content => "Link text"
after:
response.body.should have_link("Link text", :href => "/url/path")

Selectors cannot be nested

Instead you can use
within("div.container") do
  response.body.should have_link("Link text")
end

or just combine selectors one after the other in one big string
response.body.should have_selector("div.container a[href='/url/path']")
Note from Jonas Nicklas
If there are multiple divs with class container on the page, this will not work as you expect. within in Capybara differs from Webrat in that it only matches on the first found element, not on all found elements.

Annoyances and pitfalls

- failing specs don't show actual output instead you get a generic 'expected to return something'
- view specs completely ignore attributes such as "text" and "href". Embed the attributes directly in the selector instead.

Why Capybara

Capybara offers a lot more flexibility in what can be tested and how. It gives you the ability to choose drivers that can run javascript so you can test your web application end to end. I will include my favourite tips below

save_and_open_page

in your specs to view the page at any point in your spec execution as it is

Mobile driver

Capybara.register_driver :mobile do |app|  
   Capybara::RackTest::Driver.new(app, :headers => {'HTTP_USER_AGENT' => 'Mobile'})
end

now all you have to do is flag your spec with
:mobile => true
and they will run with the mobile driver.
Note:mobile => true will only work with RSpec. Use :driver => :mobile for all other cases.
_____________________
Thanks to Jonas Nicklas for clearing up some points.

5 comments:

  1. It's been a pleasure reading your blog. I have bookmarked your website so that I can come back & read more in the future as well.

    ReplyDelete
  2. You just cleared up some major confusion for me, namely the changing of the :content to :text in Capybara. Thanks for the great resource!

    ReplyDelete
  3. So any reason why one would want to use one over the other? Or is that for a different blog post?

    ReplyDelete
  4. @Hyderabad @Dominick Thank you

    @roger Capybara offers more flexibility in what can be tested and the number of drivers available for it is always increasing. It is also more heavily developed and the community seems to be standardizing around it.

    ReplyDelete
  5. I also bookmarked your website.Its really worth reading.OS Migration

    ReplyDelete