I am trying to implement some integration tests for my application to test a voting system I have in place but have run into some problems. First off, here is the test code I am trying to get to pass:
describe "vote_up_user" do
it "should update the user rating" do
click_link "user_up_arrow"
response.should have_selector("#user_rating", :content => "1")
end
end
Here is the link that gets clicked:
<%= link_to image_tag("uparrowbig.png"), vote_up_user_path(@user), :method => :post,
:id => "user_up_arrow", :class => "arrow", :remote => true %>
The corresponding action:
respond_to :html, :js
def vote_up_user
@voted_on_user = User.find(params[:id])
current_user.vote_exclusively_for(@voted_on_user)
respond_with(@voted_on_user, :location => user_path(@voted_on_user))
end
and in case anyone is interested the corresponding votes/vote_up_user.js.erb:
$("user_rating").update('<%= @voted_on_user.plusminus.to_s %>')
$("user_up_arrow").update('<%= image_tag("uparrowbigselect.png") %>')
$("user_down_arrow").update('<%= image_tag("downarrowbig.png") %>')
My problem is that I keep failing at the 开发者_如何学运维click_link line with the following error:
Missing template votes/vote_up_user with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]}
I can understand why this is failing as I do not have a template that is html.erb in the specified path. I actually have a js.erb file instead as this is an AJAX call, but this is not included in the :formats array and thus is not found. My question is then, what would be the best way to ensure that the :js format is search for when the integration test clicks on the link? Is this something I can simply adjust in the test or will I need to add it to the link helper?
I suspect the reason it's not working is that RSpec alone can't test Javascript.
When you add remote => true
to a link, it only adds data-remote="true"
as an attribute of the link, which doesn't mean anything without Javascript. That's why you see in your error :formats=>[:html]
. It is only going to look for html views. In order for Rails to request the .js.erb view by default, you either need to have the .js on the end of the URL that it is requesting or actually use Javascript to request the page.
To get Javascript to actually run in your tests, you need to use something like Capybara. When you run your test, you'll actually see your browser start up and it will run your test actually in the browser.
If this is what you want to do, I would recommend watching Ryan Bates' recent Railscast: http://railscasts.com/episodes/257-request-specs-and-capybara
Update based on comments
respond_with
will only redirect to the location you specify on POST, PUT, or DELETE requests. While you have :method => :post
in the link, links will always generate GET requests when Javascript is disabled (since you're not using AJAX). Without Javascript, the only way to generate a POST request is with a form tag.
If you want it to degrade gracefully in this situation, you should either create an html view for these situations or put a block after the respond_with
like this:
respond_with(@voted_on_user, :location => user_path(@voted_on_user)) do |format|
format.html { redirect_to user_path(@voted_on_user) }
end`
精彩评论