Rspec view testing with capybara and rails3
Asked Answered
F

7

20

I really like the way RSpec is able to separate controller and view tests but have some problems with getting capybara matchers to work in a view test. What i basically try to achieve is sth like this:

describe "some page" do
  it "should render with lots of stuff" do
    assign ..
    render
    rendered.should have_button ('Any button') #or any capybara matcher, really
  end
end

I've seen some posts on the net showing how to configure capybara and rails3 to work smoothly with cucumber or rspec controller tests, but this is not really what I want - that is, testing the views at the lowest level possible.

Also if there's another way to do this (not requiring lots of custom code, couse I know i could write some matchers that extract given selectors from rendered using nokogiri or whatever tool suitable) that'd be great too - using capybara is not a requirement.

Ferdinana answered 16/1, 2011 at 15:59 Comment(0)
A
18

There is now an option to use Capybara matchers (without Webrat baggage) when testing controllers (and views too). I'm using it this way:

describe GlobalizeTranslationsController do

  render_views
  let(:page) { Capybara::Node::Simple.new(@response.body) }

  describe "PUT :update" do
    before do
      put :update
    end

    it "displays a flash notice" do
      page.should have_selector('p.notice')
    end

  end

end

Full code:

References:

Ascomycete answered 5/8, 2011 at 14:4 Comment(3)
I really don't recommend testing controllers like that. Using your example, that kind of test fits better on the view level.Markel
Fully agree! Controller specs should only test controller logic, not the views. If you want to test views create requests/features specs (using Capybara + Poltergeist or capybara-webkit).Vex
This is a perfect case for view specs: relishapp.com/rspec/rspec-rails/v/2-0/docs/view-specs/view-specHallucinate
A
11

Capybara currently does not work with view specs (there are plans to make it work in the future). The simplest answer is to just add gem 'webrat' to the Gemfile and you're basically set. You might not have have_button but you'll have have_selector, have_tag and similar available.

Btw: as far as I know capybara and webrat can co-exist in one project.

Ascomycete answered 10/3, 2011 at 12:1 Comment(2)
Has anyone had any problems with Capybara matchers leaking into view tests?Wersh
Just a note for anyone stumbling by these days: Capybara does support view specs now: github.com/jnicklas/capybara/blob/master/…Lilithe
A
10

Slightly simpler than Pawel's answer, but the gist is the same; the following works for me with rails 3.1.0, rspec 2.6.0, capybara 1.1.1:

page = Capybara::Node::Simple.new( rendered )
page.should have_content( "blah" )
Aerify answered 10/11, 2011 at 21:5 Comment(0)
M
4

You can't call capybara's methods on rendered, that's just a string. You can use Capybara's string method though to wrap rendered in a Capybara node. Then, you can call Capybara's methods on that node:

describe "some page" do
  it "should render with lots of stuff" do
    assign ..
    render
    Capybara.string(rendered).should have_button('Any button')
  end
end

For more information, check out this post:

http://www.tamingthemindmonkey.com/2011/11/07/capybara-matchers-and-scoping-in-view-specs

Macrae answered 21/3, 2013 at 13:11 Comment(0)
C
1

At the bottom of this page, in the "Webrat and Capybara" section, it looks like Capybara is unsupported for rspec view specs

http://relishapp.com/rspec/rspec-rails

Cataplexy answered 23/1, 2011 at 9:4 Comment(1)
Correct. If you use Capybara's default driver (:rack_test), writing your view tests as "request tests" with Capybara should still give you reasonably good performance, by the way. It's how I essentially test my views. You just don't get to use assign, so you have a little less control compared to "real" view tests.Sonia
L
1

Updating this old question as things have changed since most of the other answers were added:

Capybara now does support view specs (out of the box) and this is documented on Capybara's master branch.

To quote the docs:

Finally, Capybara matchers are supported in view specs:

RSpec.describe "todos/show.html.erb", type: :view do
  it "displays the todo title" do
    assign :todo, Todo.new(title: "Buy milk")

    render

    expect(rendered).to have_css("header h1", text: "Buy milk")
  end
end

Support for these without additional let(:page) style code appears to have been added in an earlier version. (It's working for me in capybara 2.4.4 and 2.2).
Note also that only a limited subset of matchers are supported; however you can gain more functionality by using Capybara.string; ex:

expect(Capybara.string(rendered).first('td')).to have_no_content 'Tom Riddle'
Lilithe answered 24/8, 2015 at 1:56 Comment(0)
I
0

You can also use capybara syntax

describe "some page" do 
  it 'should render hello with name' do
    assign(:user, double("User", first_name: "John"))
    render
    expect(rendered).to have_content("Hello John")
  end
end
Inverson answered 20/5, 2014 at 17:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.