Rspec测试无法丢失模板格式问题

时间:2011-03-15 14:19:59

标签: ruby-on-rails ajax tdd rspec integration-testing

我正在尝试为我的应用程序实现一些集成测试,以测试我已经到位的投票系统但遇到了一些问题。首先,这是我试图通过的测试代码:

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

以下是点击的链接:

<%= link_to image_tag("uparrowbig.png"), vote_up_user_path(@user), :method => :post,
        :id => "user_up_arrow", :class => "arrow", :remote => true %>

相应的行动:

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

如果有人对相应的投票感兴趣/ 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") %>')

我的问题是我一直在click_link行失败并出现以下错误:

 Missing template votes/vote_up_user with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]}

我可以理解为什么这会失败,因为我没有在指定路径中使用html.erb的模板。我实际上有一个js.erb文件,因为这是一个AJAX调用,但这不包含在:formats数组中,因此找不到。那么我的问题是,当集成测试点击链接时,确保:js格式搜索的最佳方法是什么?这是我可以在测试中简单调整的东西,还是我需要将它添加到链接助手?

1 个答案:

答案 0 :(得分:4)

我怀疑它不起作用的原因是RSpec单独无法测试Javascript。

当您将remote => true添加到链接时,它只会添加data-remote="true"作为链接的属性,这并不意味着没有Javascript。这就是你在错误:formats=>[:html]中看到的原因。它只会寻找HTML视图。为了让Rails默认请求.js.erb视图,您需要在其请求的URL末尾使用.js,或者实际使用Javascript来请求页面。

要让Javascript在您的测试中实际运行,您需要使用像Capybara这样的东西。当您运行测试时,您实际上会看到您的浏览器启动,它将在浏览器中实际运行您的测试。

如果这是你想做的事情,我建议你观看Ryan Bates最近的Railscast:http://railscasts.com/episodes/257-request-specs-and-capybara

根据评论进行更新

respond_with只会重定向到您在POST,PUT或DELETE请求中指定的位置。当链接中有:method => :post时,链接将始终在禁用Javascript时生成GET请求(因为您没有使用AJAX)。没有Javascript,生成POST请求的唯一方法是使用表单标记。

如果你希望它在这种情况下优雅地降级,你应该为这些情况创建一个html视图,或者像respond_with这样放一个块:

respond_with(@voted_on_user, :location => user_path(@voted_on_user)) do |format|
  format.html { redirect_to user_path(@voted_on_user) }
end`