Rails 3 assert_select undefined method matches? - ruby-on-rails-3

Trying to get started on view testing in Rails 3. I want to validate that I have a form getting kicked out in the view that has the right URL for the action. So I am using assert_select. I actually got a failing test first, using this syntax in the spec (using Rspec):
response.should assert_select "form[action=#{my_model_path}]"
Looking at the rendered HTML, sure enough, the view was rendering the 'edit' url, not the 'new' url due to the wrong model being passed down. Groovy, start red.
I make the model a 'new' one, and I look at my rendered output, and it's what I'd expect, BUT the test fails, and the error message says:
NoMethodError:
undefined method `matches?' for #<Array:0x0000012a1a5d58>
I've looked all over the web for this, found one guy that mentioned the error, but got no resolution. Any ideas?

Figured out that I could get this to work by nesting my assert_select calls, like so:
response.should assert_select "form" do
assert_select "[action=?]", my_model_path
end

Related

Model paper clips validations errors are not displayed in simple_form

I am using paper_clip and simple_form gems. Unfortunately, it seems that paper clip validations errors are not displayed in my form.
I have try several types and syntax of paper_clip content_type validations and even they work (the uploaded files types are restricted) no error is displayed in the form.
Has anyone knew know how to fix this?
Here's what I suspect - the paperclip validation is likely being made on an attribute that's not actually an input in simple_form.
You might have something like this in your form:
<%= f.input :picture, :label => "Picture" %>
But paperclip's validation errors aren't going to be put on 'picture' - they'll be put on another attribute, like 'picture_file_name'. Since simple_form has a 'picture' input, and not a 'picture_file_name' input, it doesn't know where to put the errors, so they don't show up.
Take a look at your errors array and confirm what attribute's getting the errors. Then use simple_form's errors helper in your view to put that attribute's error in the appropriate place:
<%= f.error :picture_file_name %>
Unfortunately paperclip provides own format for validation errors storing them in 3 different attributes without linking to base model attribute:
*_file_name, *_file_size, *_content_type
Therefore simple_form or any other form view helper could not map paperclip validation errors with field name.
You can patch paperclip like described here http://dev.mensfeld.pl/2013/05/paperclip-bootstrap-and-simpleform-working-together-on-rails/ and forget about this issue forever

Capybara skipping over a click_button

I have a test that fills out some fields and then is supposed to click a button. This is all done after loading up a modal window. However, it seems that it just skips over it and doesn't click the button. I have tried debugging it manually and calling it myself and it'll work fine but when I run the test by itself it doesn't click it.
Given /^I login with "(.*?)" and "(.*?)"$/ do |email, password|
within "#signin_fields" do
fill_in("custom_fields_email", :with => email)
fill_in("custom_fields_password", :with => password)
end
click_button("Sign In") if page.should have_selector(".btn-signin")
end
I even added a check to make sure it was on the page but since the removal of wait_until, I'm not sure how I'm supposed to let the page load and then make sure it clicks the button properly. Any ideas would heavily appreciated.
This post may help: How do you get rspec to output what it encountered rather than it "didn't find what it expected"? Basically, for debugging, you can add the line save and open page and inspect what the spec is finding and whether it differs from the results of your own debugging.
The following row from your code is incorrect as have_selector is a RSpec matcher:
click_button("Sign In") if page.should have_selector(".btn-signin")
Instead you should use any of Capybara::Node::Matchers like:
click_button("Sign In") if page.has_selector?(".btn-signin")
page.should have_selector(".btn-signin") isn't going to return true or false and therefor the button will never be clicked. Just do this:
click_button(".btn-signin")
If it should be there then the test will fail if it doesn't appear on the page.

Capybara can't find link on the page

I'm trying to get my first capybara tests going. I following Ryan Bate's philosophy and putting some functional tests into my controller spec files.
describe UsersController do
render_views
it "can get the home page" do
get 'home'
response.body.should include("Login")
end
it "should log in" do
get 'home'
puts response.body
click_link('Login')
response.body.should include("Email")
response.body.should include("Password")
end
end
In it should login I ran into problems so began with just trying to make sure I can find and click the link. No luck. In the test as above I'm just trying to make sure the link exists
The puts response.body produces the following output
...
<div id="user_nav">
Register or Login
</div>
...
and I also see the element on the actual page. It seems only my test can't find it. The first test does pass.
1) UsersController should log in
Failure/Error: click_link('Login')
Capybara::ElementNotFound:
no link with title, id or text 'Login' found
# (eval):2:in `click_link'
# ./spec/controllers/users_controller_spec.rb:14:in `block (2 levels) in <top (required)>'
I'm using Rails 3.2, Rpsec 2.11 and Capybara 1.1.2.
(I've already checked the other questions on stackoverflow as well as a few tutorials and screencasts. I can't see any reason it can't find an element given an id tag, but I'm probably missing something obvious.
I think the reason it's not working is that you're using get for what is essentially an integration test. See this post: http://blog.plataformatec.com.br/2012/06/improving-the-integration-between-capybara-and-rspec/
If my understanding is correct, you need to use visit in order to use click_link on the page:
it "should log in" do
visit home_path
click_link('Login')
page.should ...
end
See also this answer on SO: Rspec and capybara, difference between visit and get methods, with regards to the current_path object

Rspec view testing with capybara and rails3

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.
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:
https://github.com/Exvo/exvo_globalize/blob/master/spec/controllers/globalize_translations_controller_spec.rb
References:
http://robots.thoughtbot.com/post/8087279685/use-capybara-on-any-html-fragment-or-page
http://cakebaker.42dh.com/2010/09/19/cucumber-switching-from-webrat-to-capybara/
http://trevorturk.com/2010/12/22/using-capybara-without-cucumber-in-rails-3
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.
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" )
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
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
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'
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

Rspec2 and Rails 3 - View Spec Routing for Nested Resources

I have a nested resource, setup like this:
resources :chickens do
resources :eggs
end
The views for the EggsController are under views/eggs, but:
describe "eggs/index.html.erb" do
gives a "No route matches {:action => "create", :controller => "eggs"} error on calling render. How do I get RSpec to find the correct (nested) route for view specs?
As a side note, is there any way to specify a nested resource to the Rails 3 controller scaffold generator?
The test looks ok to me...
By any chance do you have a form on your eggs/index.html.erb for creating new eggs that might not yet be wired up correctly? It seems it may be trying to render the index view but failing because the view is trying build a route that doesn't exist? You'd want to make sure that the form is using the correct nested resource route. Does the view render when you load it up in the browser?