Suffix

Sinatra view tests with Capybara & HAML

Using Capybara for unit, instead of acceptance testing.

Ever seen something like this in a Capybara view spec?

visit('/')
page.has_css?('tr.foo')

Capybara simulates user behavior, it will act like if a user is visiting the page and interact with it. For acceptance testing, this is just fine. It will call the controller and render the page, full stack, and it's probably what you want.

Isolation testing

Sometimes, however, you do not want to test the full stack. Sometimes you want to test in isolation, only testing your view without running the controller code.

It has to be said this is not the goal of Capybara. Capybara is a tool made for acceptance testing, not for unit testing. So, why do it? Using Webrat is a simple workaround but I don't like to mix both frameworks in the same project so here is a hack on how you can use Capybara to test views in isolation:

it 'has an awesome title' do
  engine = Haml::Engine.new(IO.read('index.haml'))
  rendered = engine.render(Object.new, :@title => 'Awesome title')
  rendered.should have_css('tr.foo')
end

It reads the HAML file and renders its HTML. Don't forget to specify your view variables as they won't exist since we are not using the controller.

Adding has_xpath? and has_css?

Since we don't use the Capybara 'page' element we don't have access to all the nice has_xpath? and has_css? selectors so we'll need to add these ourselves. You can easily do this by extending the String class, just add the following in a spec/support/string.rb file:

class String
  def has_xpath?(path)
    !Nokogiri::HTML(self).xpath(path).empty?
  end

  def has_css?(path)
    has_xpath?(Nokogiri::CSS.xpath_for(path).join(' | '))
  end
end

Make sure you have the Nokogiri gem installed and voila, that should be it.