RubyFlow The Ruby and Rails community linklog

Migrating from Webrat to Capybara

This is a collection of tips on how to migrate from Webrat to Capybara using RSpec.

Comments

I tried to post this comment on the blog, but that didn’t work unfortunately. So posting this here in the hope that someone sees it:

Thank you for compiling your notes, unfortuantely quite a bit of this information is inaccurate. I feel like I need to set the record straight, so that others who come here aren’t misled by some of these examples.

From the top:

gem "capybara" # needs to be a quoted string

this doesn’t work:

response.body.should have_selector("head title", :text => "My Title")

Capybara has no response object. Instead you would have to do something like:

page.should have_selector("head title", :text => "My Title")

page is a shorthand for accessing the current Capybara session.

response.body.should have_selector("input[value='input field value']")

same here, actually even though it is undocumented, Capybara supports the option :with, to select elements by label.

page.should have_selector("input", :with => 'input field value')

but this selector can be more elegantly written as:

page.should have_field("Field name", :with => "value")

in Capybara.

Be careful with this one:

within("div.container") do
  response.body.should have_link("Link text")
end

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. This might be a better example:

within("div#sidebar") do
  page.should have_link("Link text")
end

Clearly there will only be one div with id=”sidebar” on the page. This is what within is meant for. Personally I feel there is no point in testing for the fact that a link is nested in a particular generic div. If it’s not unique, it’s not worth checking for. If you have to, though, you can achieve the same thing with standard enumberable methods:

all('div.container').any? do |container|
  container.has_link?('foo')
end.should be_true

not super elegant though.

Finally, if you do this:

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

You cannot select the driver with :mobile => true, you will need to do :driver => :mobile. Capybara only registers the special :js => true option

@Jonas Thanks for the comment, and sorry I just noticed it :s - Regarding the response object, I was referring to the response object that comes with RSpec, but if we’re not using RSpec it would not work. - Didn’t know about :with. That’s why I love Capybara, there is a lot of flexibility, though it is hard to find :) - For driver selection, I guess it must be an RSpec thing, cause it is working for me.

Thanks again for clearing things up. I will update the post.

Post a comment

You can use basic HTML markup (e.g. <a>) or Markdown.

As you are not logged in, you will be
directed via GitHub to signup or sign in